mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-11-02 04:17:02 +00:00
Migrate to blake2b_simd and blake2s_simd crates
The primary reason for migrating is that these crates provide APIs for setting the personalisation string. This enables us to depend solely on published crates, and thus publish our own crates. The SIMD implementations are ported from libsodium. Closes #67.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
use blake2_rfc::blake2b::Blake2b;
|
||||
use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams};
|
||||
use byteorder::{LittleEndian, WriteBytesExt};
|
||||
use ff::{PrimeField, PrimeFieldRepr};
|
||||
|
||||
@@ -39,7 +39,7 @@ macro_rules! update_i64 {
|
||||
macro_rules! update_hash {
|
||||
($h:expr, $cond:expr, $value:expr) => {
|
||||
if $cond {
|
||||
$h.update(&$value);
|
||||
$h.update(&$value.as_ref());
|
||||
} else {
|
||||
$h.update(&[0; 32]);
|
||||
}
|
||||
@@ -67,47 +67,51 @@ impl SigHashVersion {
|
||||
}
|
||||
}
|
||||
|
||||
fn prevout_hash(tx: &TransactionData) -> Vec<u8> {
|
||||
fn prevout_hash(tx: &TransactionData) -> Blake2bHash {
|
||||
let mut data = Vec::with_capacity(tx.vin.len() * 36);
|
||||
for t_in in &tx.vin {
|
||||
t_in.prevout.write(&mut data).unwrap();
|
||||
}
|
||||
let mut h = Blake2b::with_params(32, &[], &[], ZCASH_PREVOUTS_HASH_PERSONALIZATION);
|
||||
h.update(&data);
|
||||
h.finalize().as_ref().to_vec()
|
||||
Blake2bParams::new()
|
||||
.hash_length(32)
|
||||
.personal(ZCASH_PREVOUTS_HASH_PERSONALIZATION)
|
||||
.hash(&data)
|
||||
}
|
||||
|
||||
fn sequence_hash(tx: &TransactionData) -> Vec<u8> {
|
||||
fn sequence_hash(tx: &TransactionData) -> Blake2bHash {
|
||||
let mut data = Vec::with_capacity(tx.vin.len() * 4);
|
||||
for t_in in &tx.vin {
|
||||
(&mut data)
|
||||
.write_u32::<LittleEndian>(t_in.sequence)
|
||||
.unwrap();
|
||||
}
|
||||
let mut h = Blake2b::with_params(32, &[], &[], ZCASH_SEQUENCE_HASH_PERSONALIZATION);
|
||||
h.update(&data);
|
||||
h.finalize().as_ref().to_vec()
|
||||
Blake2bParams::new()
|
||||
.hash_length(32)
|
||||
.personal(ZCASH_SEQUENCE_HASH_PERSONALIZATION)
|
||||
.hash(&data)
|
||||
}
|
||||
|
||||
fn outputs_hash(tx: &TransactionData) -> Vec<u8> {
|
||||
fn outputs_hash(tx: &TransactionData) -> Blake2bHash {
|
||||
let mut data = Vec::with_capacity(tx.vout.len() * (4 + 1));
|
||||
for t_out in &tx.vout {
|
||||
t_out.write(&mut data).unwrap();
|
||||
}
|
||||
let mut h = Blake2b::with_params(32, &[], &[], ZCASH_OUTPUTS_HASH_PERSONALIZATION);
|
||||
h.update(&data);
|
||||
h.finalize().as_ref().to_vec()
|
||||
Blake2bParams::new()
|
||||
.hash_length(32)
|
||||
.personal(ZCASH_OUTPUTS_HASH_PERSONALIZATION)
|
||||
.hash(&data)
|
||||
}
|
||||
|
||||
fn single_output_hash(tx_out: &TxOut) -> Vec<u8> {
|
||||
fn single_output_hash(tx_out: &TxOut) -> Blake2bHash {
|
||||
let mut data = vec![];
|
||||
tx_out.write(&mut data).unwrap();
|
||||
let mut h = Blake2b::with_params(32, &[], &[], ZCASH_OUTPUTS_HASH_PERSONALIZATION);
|
||||
h.update(&data);
|
||||
h.finalize().as_ref().to_vec()
|
||||
Blake2bParams::new()
|
||||
.hash_length(32)
|
||||
.personal(ZCASH_OUTPUTS_HASH_PERSONALIZATION)
|
||||
.hash(&data)
|
||||
}
|
||||
|
||||
fn joinsplits_hash(tx: &TransactionData) -> Vec<u8> {
|
||||
fn joinsplits_hash(tx: &TransactionData) -> Blake2bHash {
|
||||
let mut data = Vec::with_capacity(
|
||||
tx.joinsplits.len()
|
||||
* if tx.version < SAPLING_TX_VERSION {
|
||||
@@ -120,12 +124,13 @@ fn joinsplits_hash(tx: &TransactionData) -> Vec<u8> {
|
||||
js.write(&mut data).unwrap();
|
||||
}
|
||||
data.extend_from_slice(&tx.joinsplit_pubkey.unwrap());
|
||||
let mut h = Blake2b::with_params(32, &[], &[], ZCASH_JOINSPLITS_HASH_PERSONALIZATION);
|
||||
h.update(&data);
|
||||
h.finalize().as_ref().to_vec()
|
||||
Blake2bParams::new()
|
||||
.hash_length(32)
|
||||
.personal(ZCASH_JOINSPLITS_HASH_PERSONALIZATION)
|
||||
.hash(&data)
|
||||
}
|
||||
|
||||
fn shielded_spends_hash(tx: &TransactionData) -> Vec<u8> {
|
||||
fn shielded_spends_hash(tx: &TransactionData) -> Blake2bHash {
|
||||
let mut data = Vec::with_capacity(tx.shielded_spends.len() * 384);
|
||||
for s_spend in &tx.shielded_spends {
|
||||
s_spend.cv.write(&mut data).unwrap();
|
||||
@@ -134,19 +139,21 @@ fn shielded_spends_hash(tx: &TransactionData) -> Vec<u8> {
|
||||
s_spend.rk.write(&mut data).unwrap();
|
||||
data.extend_from_slice(&s_spend.zkproof);
|
||||
}
|
||||
let mut h = Blake2b::with_params(32, &[], &[], ZCASH_SHIELDED_SPENDS_HASH_PERSONALIZATION);
|
||||
h.update(&data);
|
||||
h.finalize().as_ref().to_vec()
|
||||
Blake2bParams::new()
|
||||
.hash_length(32)
|
||||
.personal(ZCASH_SHIELDED_SPENDS_HASH_PERSONALIZATION)
|
||||
.hash(&data)
|
||||
}
|
||||
|
||||
fn shielded_outputs_hash(tx: &TransactionData) -> Vec<u8> {
|
||||
fn shielded_outputs_hash(tx: &TransactionData) -> Blake2bHash {
|
||||
let mut data = Vec::with_capacity(tx.shielded_outputs.len() * 948);
|
||||
for s_out in &tx.shielded_outputs {
|
||||
s_out.write(&mut data).unwrap();
|
||||
}
|
||||
let mut h = Blake2b::with_params(32, &[], &[], ZCASH_SHIELDED_OUTPUTS_HASH_PERSONALIZATION);
|
||||
h.update(&data);
|
||||
h.finalize().as_ref().to_vec()
|
||||
Blake2bParams::new()
|
||||
.hash_length(32)
|
||||
.personal(ZCASH_SHIELDED_OUTPUTS_HASH_PERSONALIZATION)
|
||||
.hash(&data)
|
||||
}
|
||||
|
||||
pub fn signature_hash_data(
|
||||
@@ -158,26 +165,16 @@ pub fn signature_hash_data(
|
||||
let sigversion = SigHashVersion::from_tx(tx);
|
||||
match sigversion {
|
||||
SigHashVersion::Overwinter | SigHashVersion::Sapling => {
|
||||
let hash_outputs = if (hash_type & SIGHASH_MASK) != SIGHASH_SINGLE
|
||||
&& (hash_type & SIGHASH_MASK) != SIGHASH_NONE
|
||||
{
|
||||
outputs_hash(tx)
|
||||
} else if (hash_type & SIGHASH_MASK) == SIGHASH_SINGLE
|
||||
&& transparent_input.is_some()
|
||||
&& transparent_input.as_ref().unwrap().0 < tx.vout.len()
|
||||
{
|
||||
single_output_hash(&tx.vout[transparent_input.as_ref().unwrap().0])
|
||||
} else {
|
||||
vec![0; 32]
|
||||
};
|
||||
|
||||
let mut personal = [0; 16];
|
||||
(&mut personal[..12]).copy_from_slice(ZCASH_SIGHASH_PERSONALIZATION_PREFIX);
|
||||
(&mut personal[12..])
|
||||
.write_u32::<LittleEndian>(consensus_branch_id)
|
||||
.unwrap();
|
||||
|
||||
let mut h = Blake2b::with_params(32, &[], &[], &personal);
|
||||
let mut h = Blake2bParams::new()
|
||||
.hash_length(32)
|
||||
.personal(&personal)
|
||||
.to_state();
|
||||
let mut tmp = [0; 8];
|
||||
|
||||
update_u32!(h, tx.header(), tmp);
|
||||
@@ -190,7 +187,20 @@ pub fn signature_hash_data(
|
||||
&& (hash_type & SIGHASH_MASK) != SIGHASH_NONE,
|
||||
sequence_hash(tx)
|
||||
);
|
||||
h.update(&hash_outputs);
|
||||
if (hash_type & SIGHASH_MASK) != SIGHASH_SINGLE
|
||||
&& (hash_type & SIGHASH_MASK) != SIGHASH_NONE
|
||||
{
|
||||
h.update(outputs_hash(tx).as_ref());
|
||||
} else if (hash_type & SIGHASH_MASK) == SIGHASH_SINGLE
|
||||
&& transparent_input.is_some()
|
||||
&& transparent_input.as_ref().unwrap().0 < tx.vout.len()
|
||||
{
|
||||
h.update(
|
||||
single_output_hash(&tx.vout[transparent_input.as_ref().unwrap().0]).as_ref(),
|
||||
);
|
||||
} else {
|
||||
h.update(&[0; 32]);
|
||||
};
|
||||
update_hash!(h, !tx.joinsplits.is_empty(), joinsplits_hash(tx));
|
||||
if sigversion == SigHashVersion::Sapling {
|
||||
update_hash!(h, !tx.shielded_spends.is_empty(), shielded_spends_hash(tx));
|
||||
|
||||
Reference in New Issue
Block a user