Apply suggestions from code review

Co-authored-by: Daira Hopwood <daira@jacaranda.org>
This commit is contained in:
Kris Nuttycombe 2022-01-18 14:48:57 -07:00 committed by Kris Nuttycombe
parent 7b2f9e27ae
commit eaa3ec56d0
3 changed files with 27 additions and 33 deletions

View File

@ -928,7 +928,7 @@ impl Transaction {
#[derive(Clone)] #[derive(Clone)]
pub struct TransparentDigests<A> { pub struct TransparentDigests<A> {
pub prevout_digest: A, pub prevouts_digest: A,
pub sequence_digest: A, pub sequence_digest: A,
pub outputs_digest: A, pub outputs_digest: A,
} }

View File

@ -38,6 +38,7 @@ fn hasher(personal: &[u8; 16]) -> State {
} }
/// Implements [ZIP 244 section S.2](https://zips.z.cash/zip-0244#s-2-transparent-sig-digest) /// Implements [ZIP 244 section S.2](https://zips.z.cash/zip-0244#s-2-transparent-sig-digest)
/// but only when used to produce the hash for a signature over a transparent input.
fn transparent_sig_digest<A: TransparentAuthorizingContext>( fn transparent_sig_digest<A: TransparentAuthorizingContext>(
txid_digests: &TransparentDigests<Blake2bHash>, txid_digests: &TransparentDigests<Blake2bHash>,
bundle: &transparent::Bundle<A>, bundle: &transparent::Bundle<A>,
@ -48,39 +49,33 @@ fn transparent_sig_digest<A: TransparentAuthorizingContext>(
let flag_single = hash_type & SIGHASH_MASK == SIGHASH_SINGLE; let flag_single = hash_type & SIGHASH_MASK == SIGHASH_SINGLE;
let flag_none = hash_type & SIGHASH_MASK == SIGHASH_NONE; let flag_none = hash_type & SIGHASH_MASK == SIGHASH_NONE;
let prevout_digest = if flag_anyonecanpay { let prevouts_digest = if flag_anyonecanpay {
transparent_prevout_hash::<A>(&[]) transparent_prevout_hash::<A>(&[])
} else { } else {
txid_digests.prevout_digest txid_digests.prevouts_digest
}; };
let amounts_digest = { let amounts_digest = {
let mut h = hasher(ZCASH_TRANSPARENT_AMOUNTS_HASH_PERSONALIZATION); let mut h = hasher(ZCASH_TRANSPARENT_AMOUNTS_HASH_PERSONALIZATION);
Array::write( if !flag_anyonecanpay {
&mut h, Array::write(&mut h, bundle.authorization.input_amounts(), |w, amount| {
if flag_anyonecanpay { w.write_all(&amount.to_i64_le_bytes())
vec![] })
} else { .unwrap();
bundle.authorization.input_amounts() }
},
|w, amount| w.write_all(&amount.to_i64_le_bytes()),
)
.unwrap();
h.finalize() h.finalize()
}; };
let scripts_digest = { let scripts_digest = {
let mut h = hasher(ZCASH_TRANSPARENT_SCRIPTS_HASH_PERSONALIZATION); let mut h = hasher(ZCASH_TRANSPARENT_SCRIPTS_HASH_PERSONALIZATION);
Array::write( if !flag_anyonecanpay {
&mut h, Array::write(
if flag_anyonecanpay { &mut h,
vec![] bundle.authorization.input_scriptpubkeys(),
} else { |w, script| script.write(w),
bundle.authorization.input_scriptpubkeys() )
}, .unwrap();
|w, script| script.write(w), }
)
.unwrap();
h.finalize() h.finalize()
}; };
@ -106,11 +101,10 @@ fn transparent_sig_digest<A: TransparentAuthorizingContext>(
txid_digests.outputs_digest txid_digests.outputs_digest
}; };
// If we are serializing an input (i.e. this is not a JoinSplit signature hash): //S.2g.i: prevout (field encoding)
// a. outpoint (32-byte hash + 4-byte little endian) //S.2g.ii: value (8-byte signed little-endian)
// b. scriptCode of the input (serialized as scripts inside CTxOuts) //S.2g.iii: scriptPubKey (field encoding)
// c. value of the output spent by this input (8-byte little endian) //S.2g.iv: nSequence (4-byte unsigned little-endian)
// d. nSequence of the input (4-byte little endian)
let mut ch = hasher(ZCASH_TRANSPARENT_INPUT_HASH_PERSONALIZATION); let mut ch = hasher(ZCASH_TRANSPARENT_INPUT_HASH_PERSONALIZATION);
if let SignableInput::Transparent { if let SignableInput::Transparent {
index, index,
@ -125,16 +119,16 @@ fn transparent_sig_digest<A: TransparentAuthorizingContext>(
script_pubkey.write(&mut ch).unwrap(); script_pubkey.write(&mut ch).unwrap();
ch.write_u32::<LittleEndian>(txin.sequence).unwrap(); ch.write_u32::<LittleEndian>(txin.sequence).unwrap();
} }
let per_input_digest = ch.finalize(); let txin_sig_digest = ch.finalize();
let mut h = hasher(ZCASH_TRANSPARENT_HASH_PERSONALIZATION); let mut h = hasher(ZCASH_TRANSPARENT_HASH_PERSONALIZATION);
h.write_all(&[hash_type]).unwrap(); h.write_all(&[hash_type]).unwrap();
h.write_all(prevout_digest.as_bytes()).unwrap(); h.write_all(prevouts_digest.as_bytes()).unwrap();
h.write_all(amounts_digest.as_bytes()).unwrap(); h.write_all(amounts_digest.as_bytes()).unwrap();
h.write_all(scripts_digest.as_bytes()).unwrap(); h.write_all(scripts_digest.as_bytes()).unwrap();
h.write_all(sequence_digest.as_bytes()).unwrap(); h.write_all(sequence_digest.as_bytes()).unwrap();
h.write_all(outputs_digest.as_bytes()).unwrap(); h.write_all(outputs_digest.as_bytes()).unwrap();
h.write_all(per_input_digest.as_bytes()).unwrap(); h.write_all(txin_sig_digest.as_bytes()).unwrap();
h.finalize() h.finalize()
} }

View File

@ -200,7 +200,7 @@ fn transparent_digests<A: transparent::Authorization>(
bundle: &transparent::Bundle<A>, bundle: &transparent::Bundle<A>,
) -> TransparentDigests<Blake2bHash> { ) -> TransparentDigests<Blake2bHash> {
TransparentDigests { TransparentDigests {
prevout_digest: transparent_prevout_hash(&bundle.vin), prevouts_digest: transparent_prevout_hash(&bundle.vin),
sequence_digest: transparent_sequence_hash(&bundle.vin), sequence_digest: transparent_sequence_hash(&bundle.vin),
outputs_digest: transparent_outputs_hash(&bundle.vout), outputs_digest: transparent_outputs_hash(&bundle.vout),
} }
@ -243,7 +243,7 @@ pub(crate) fn hash_transparent_txid_data(
) -> Blake2bHash { ) -> Blake2bHash {
let mut h = hasher(ZCASH_TRANSPARENT_HASH_PERSONALIZATION); let mut h = hasher(ZCASH_TRANSPARENT_HASH_PERSONALIZATION);
if let Some(d) = t_digests { if let Some(d) = t_digests {
h.write_all(d.prevout_digest.as_bytes()).unwrap(); h.write_all(d.prevouts_digest.as_bytes()).unwrap();
h.write_all(d.sequence_digest.as_bytes()).unwrap(); h.write_all(d.sequence_digest.as_bytes()).unwrap();
h.write_all(d.outputs_digest.as_bytes()).unwrap(); h.write_all(d.outputs_digest.as_bytes()).unwrap();
} }