zcash_transparent/pczt/
spend_finalizer.rs1use ripemd::Ripemd160;
2use sha2::{Digest, Sha256};
3
4use crate::address::{Script, TransparentAddress};
5
6impl super::Bundle {
7 pub fn finalize_spends(&mut self) -> Result<(), SpendFinalizerError> {
9 for input in &mut self.inputs {
14 match input.script_pubkey.address() {
15 Some(TransparentAddress::PublicKeyHash(hash)) => {
16 let (pubkey, sig_bytes) = {
17 let mut iter = input.partial_signatures.iter();
18 match (iter.next(), iter.next()) {
19 (Some(entry), None) => Ok(entry),
20 (None, _) => Err(SpendFinalizerError::MissingSignature),
21 (Some(_), Some(_)) => Err(SpendFinalizerError::UnexpectedSignatures),
22 }
23 }?;
24
25 if hash[..] != Ripemd160::digest(Sha256::digest(pubkey))[..] {
27 return Err(SpendFinalizerError::UnexpectedSignatures);
28 }
29
30 input.script_sig = Some(Script::default() << &sig_bytes[..] << &pubkey[..]);
32 }
33 Some(TransparentAddress::ScriptHash(_)) => {
34 return Err(SpendFinalizerError::UnsupportedScriptPubkey)
35 }
36 None => return Err(SpendFinalizerError::UnsupportedScriptPubkey),
37 }
38 }
39
40 for input in &mut self.inputs {
44 input.required_time_lock_time = None;
45 input.required_height_lock_time = None;
46 input.redeem_script = None;
47 input.partial_signatures.clear();
48 input.bip32_derivation.clear();
49 input.ripemd160_preimages.clear();
50 input.sha256_preimages.clear();
51 input.hash160_preimages.clear();
52 input.hash256_preimages.clear();
53 }
54
55 Ok(())
56 }
57}
58
59#[derive(Debug)]
61pub enum SpendFinalizerError {
62 MissingSignature,
64 UnexpectedSignatures,
66 UnsupportedScriptPubkey,
68}