diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 79108fc19..8c93184f9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,8 @@ jobs: - name: Fetch path to Zcash parameters working-directory: ./zcash_proofs - run: echo "::set-env name=ZCASH_PARAMS::$(cargo run --release --example get-params-path --features directories)" + shell: bash + run: echo "ZCASH_PARAMS=$(cargo run --release --example get-params-path --features directories)" >> $GITHUB_ENV - name: Cache Zcash parameters id: cache-params uses: actions/cache@v2 @@ -144,7 +145,8 @@ jobs: - name: Fetch path to Zcash parameters working-directory: ./zcash_proofs - run: echo "::set-env name=ZCASH_PARAMS::$(cargo run --release --example get-params-path --features directories)" + shell: bash + run: echo "ZCASH_PARAMS=$(cargo run --release --example get-params-path --features directories)" >> $GITHUB_ENV - name: Cache Zcash parameters id: cache-params uses: actions/cache@v2 diff --git a/zcash_primitives/src/transaction/sighash.rs b/zcash_primitives/src/transaction/sighash.rs index e576d805f..3c98c119c 100644 --- a/zcash_primitives/src/transaction/sighash.rs +++ b/zcash_primitives/src/transaction/sighash.rs @@ -13,7 +13,9 @@ use crate::{ }; use super::{ - components::{Amount, TxOut}, + components::{ + Amount, JSDescription, OutputDescription, SpendDescription, TxIn, TxOut, TzeIn, TzeOut, + }, Transaction, TransactionData, OVERWINTER_VERSION_GROUP_ID, SAPLING_TX_VERSION, SAPLING_VERSION_GROUP_ID, ZFUTURE_VERSION_GROUP_ID, }; @@ -77,9 +79,9 @@ impl SigHashVersion { } } -fn prevout_hash(tx: &TransactionData) -> Blake2bHash { - let mut data = Vec::with_capacity(tx.vin.len() * 36); - for t_in in &tx.vin { +fn prevout_hash(vin: &[TxIn]) -> Blake2bHash { + let mut data = Vec::with_capacity(vin.len() * 36); + for t_in in vin { t_in.prevout.write(&mut data).unwrap(); } Blake2bParams::new() @@ -88,9 +90,9 @@ fn prevout_hash(tx: &TransactionData) -> Blake2bHash { .hash(&data) } -fn sequence_hash(tx: &TransactionData) -> Blake2bHash { - let mut data = Vec::with_capacity(tx.vin.len() * 4); - for t_in in &tx.vin { +fn sequence_hash(vin: &[TxIn]) -> Blake2bHash { + let mut data = Vec::with_capacity(vin.len() * 4); + for t_in in vin { (&mut data) .write_u32::(t_in.sequence) .unwrap(); @@ -101,9 +103,9 @@ fn sequence_hash(tx: &TransactionData) -> Blake2bHash { .hash(&data) } -fn outputs_hash(tx: &TransactionData) -> Blake2bHash { - let mut data = Vec::with_capacity(tx.vout.len() * (4 + 1)); - for t_out in &tx.vout { +fn outputs_hash(vout: &[TxOut]) -> Blake2bHash { + let mut data = Vec::with_capacity(vout.len() * (4 + 1)); + for t_out in vout { t_out.write(&mut data).unwrap(); } Blake2bParams::new() @@ -121,28 +123,32 @@ fn single_output_hash(tx_out: &TxOut) -> Blake2bHash { .hash(&data) } -fn joinsplits_hash(tx: &TransactionData) -> Blake2bHash { +fn joinsplits_hash( + txversion: u32, + joinsplits: &[JSDescription], + joinsplit_pubkey: &[u8; 32], +) -> Blake2bHash { let mut data = Vec::with_capacity( - tx.joinsplits.len() - * if tx.version < SAPLING_TX_VERSION { + joinsplits.len() + * if txversion < SAPLING_TX_VERSION { 1802 // JSDescription with PHGR13 proof } else { 1698 // JSDescription with Groth16 proof }, ); - for js in &tx.joinsplits { + for js in joinsplits { js.write(&mut data).unwrap(); } - data.extend_from_slice(&tx.joinsplit_pubkey.unwrap()); + data.extend_from_slice(joinsplit_pubkey); Blake2bParams::new() .hash_length(32) .personal(ZCASH_JOINSPLITS_HASH_PERSONALIZATION) .hash(&data) } -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 { +fn shielded_spends_hash(shielded_spends: &[SpendDescription]) -> Blake2bHash { + let mut data = Vec::with_capacity(shielded_spends.len() * 384); + for s_spend in shielded_spends { data.extend_from_slice(&s_spend.cv.to_bytes()); data.extend_from_slice(s_spend.anchor.to_repr().as_ref()); data.extend_from_slice(&s_spend.nullifier); @@ -155,9 +161,9 @@ fn shielded_spends_hash(tx: &TransactionData) -> Blake2bHash { .hash(&data) } -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 { +fn shielded_outputs_hash(shielded_outputs: &[OutputDescription]) -> Blake2bHash { + let mut data = Vec::with_capacity(shielded_outputs.len() * 948); + for s_out in shielded_outputs { s_out.write(&mut data).unwrap(); } Blake2bParams::new() @@ -166,9 +172,9 @@ fn shielded_outputs_hash(tx: &TransactionData) -> Blake2bHash { .hash(&data) } -fn tze_inputs_hash(tx: &TransactionData) -> Blake2bHash { +fn tze_inputs_hash(tze_inputs: &[TzeIn]) -> Blake2bHash { let mut data = vec![]; - for tzein in &tx.tze_inputs { + for tzein in tze_inputs { tzein.write_without_witness(&mut data).unwrap(); } Blake2bParams::new() @@ -177,9 +183,9 @@ fn tze_inputs_hash(tx: &TransactionData) -> Blake2bHash { .hash(&data) } -fn tze_outputs_hash(tx: &TransactionData) -> Blake2bHash { +fn tze_outputs_hash(tze_outputs: &[TzeOut]) -> Blake2bHash { let mut data = vec![]; - for tzeout in &tx.tze_outputs { + for tzeout in tze_outputs { tzeout.write(&mut data).unwrap(); } Blake2bParams::new() @@ -243,19 +249,23 @@ pub fn signature_hash_data<'a>( update_u32!(h, tx.header(), tmp); update_u32!(h, tx.version_group_id, tmp); - update_hash!(h, hash_type & SIGHASH_ANYONECANPAY == 0, prevout_hash(tx)); + update_hash!( + h, + hash_type & SIGHASH_ANYONECANPAY == 0, + prevout_hash(&tx.vin) + ); update_hash!( h, hash_type & SIGHASH_ANYONECANPAY == 0 && (hash_type & SIGHASH_MASK) != SIGHASH_SINGLE && (hash_type & SIGHASH_MASK) != SIGHASH_NONE, - sequence_hash(tx) + sequence_hash(&tx.vin) ); if (hash_type & SIGHASH_MASK) != SIGHASH_SINGLE && (hash_type & SIGHASH_MASK) != SIGHASH_NONE { - h.update(outputs_hash(tx).as_ref()); + h.update(outputs_hash(&tx.vout).as_ref()); } else if (hash_type & SIGHASH_MASK) == SIGHASH_SINGLE { match signable_input { SignableInput::Transparent { index, .. } if index < tx.vout.len() => { @@ -267,16 +277,32 @@ pub fn signature_hash_data<'a>( h.update(&[0; 32]); }; if sigversion == SigHashVersion::ZFuture { - update_hash!(h, !tx.tze_inputs.is_empty(), tze_inputs_hash(tx)); - update_hash!(h, !tx.tze_outputs.is_empty(), tze_outputs_hash(tx)); + update_hash!( + h, + !tx.tze_inputs.is_empty(), + tze_inputs_hash(&tx.tze_inputs) + ); + update_hash!( + h, + !tx.tze_outputs.is_empty(), + tze_outputs_hash(&tx.tze_outputs) + ); } - update_hash!(h, !tx.joinsplits.is_empty(), joinsplits_hash(tx)); + update_hash!( + h, + !tx.joinsplits.is_empty(), + joinsplits_hash(tx.version, &tx.joinsplits, &tx.joinsplit_pubkey.unwrap()) + ); if sigversion == SigHashVersion::Sapling || sigversion == SigHashVersion::ZFuture { - update_hash!(h, !tx.shielded_spends.is_empty(), shielded_spends_hash(tx)); + update_hash!( + h, + !tx.shielded_spends.is_empty(), + shielded_spends_hash(&tx.shielded_spends) + ); update_hash!( h, !tx.shielded_outputs.is_empty(), - shielded_outputs_hash(tx) + shielded_outputs_hash(&tx.shielded_outputs) ); } update_u32!(h, tx.lock_time, tmp);