Merge pull request #316 from nuttycom/sighash_components

Make the functions which produce the components of the sighash reusable.
This commit is contained in:
str4d 2020-11-19 22:21:41 +00:00 committed by GitHub
commit 97ef1592bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 35 deletions

View File

@ -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

View File

@ -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::<LittleEndian>(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);