zcash_transparent/pczt/
updater.rs1use alloc::string::String;
2use alloc::vec::Vec;
3use ripemd::Ripemd160;
4use sha2::{Digest, Sha256};
5
6use crate::address::{Script, TransparentAddress};
7
8use super::{Bip32Derivation, Bundle, Input, Output};
9
10impl Bundle {
11 pub fn update_with<F>(&mut self, f: F) -> Result<(), UpdaterError>
13 where
14 F: FnOnce(Updater<'_>) -> Result<(), UpdaterError>,
15 {
16 f(Updater(self))
17 }
18}
19
20pub struct Updater<'a>(&'a mut Bundle);
22
23impl Updater<'_> {
24 pub fn bundle(&self) -> &Bundle {
26 self.0
27 }
28
29 pub fn update_input_with<F>(&mut self, index: usize, f: F) -> Result<(), UpdaterError>
32 where
33 F: FnOnce(InputUpdater<'_>) -> Result<(), UpdaterError>,
34 {
35 f(InputUpdater(
36 self.0
37 .inputs
38 .get_mut(index)
39 .ok_or(UpdaterError::InvalidIndex)?,
40 ))
41 }
42
43 pub fn update_output_with<F>(&mut self, index: usize, f: F) -> Result<(), UpdaterError>
46 where
47 F: FnOnce(OutputUpdater<'_>) -> Result<(), UpdaterError>,
48 {
49 f(OutputUpdater(
50 self.0
51 .outputs
52 .get_mut(index)
53 .ok_or(UpdaterError::InvalidIndex)?,
54 ))
55 }
56}
57
58pub struct InputUpdater<'a>(&'a mut Input);
60
61impl InputUpdater<'_> {
62 pub fn set_redeem_script(&mut self, redeem_script: Script) -> Result<(), UpdaterError> {
67 if let Some(TransparentAddress::ScriptHash(hash)) = self.0.script_pubkey.address() {
68 if hash[..] == Ripemd160::digest(Sha256::digest(&redeem_script.0))[..] {
69 self.0.redeem_script = Some(redeem_script);
70 Ok(())
71 } else {
72 Err(UpdaterError::WrongRedeemScript)
73 }
74 } else {
75 Err(UpdaterError::NotP2sh)
76 }
77 }
78
79 pub fn set_bip32_derivation(&mut self, pubkey: [u8; 33], derivation: Bip32Derivation) {
81 self.0.bip32_derivation.insert(pubkey, derivation);
82 }
83
84 pub fn set_ripemd160_preimage(&mut self, value: Vec<u8>) {
86 let hash = Ripemd160::digest(&value);
87 self.0.ripemd160_preimages.insert(hash.into(), value);
88 }
89
90 pub fn set_sha256_preimage(&mut self, value: Vec<u8>) {
92 let hash = Sha256::digest(&value);
93 self.0.sha256_preimages.insert(hash.into(), value);
94 }
95
96 pub fn set_hash160_preimage(&mut self, value: Vec<u8>) {
98 let hash = Ripemd160::digest(Sha256::digest(&value));
99 self.0.hash160_preimages.insert(hash.into(), value);
100 }
101
102 pub fn set_hash256_preimage(&mut self, value: Vec<u8>) {
104 let hash = Sha256::digest(Sha256::digest(&value));
105 self.0.hash256_preimages.insert(hash.into(), value);
106 }
107
108 pub fn set_proprietary(&mut self, key: String, value: Vec<u8>) {
110 self.0.proprietary.insert(key, value);
111 }
112}
113
114pub struct OutputUpdater<'a>(&'a mut Output);
116
117impl OutputUpdater<'_> {
118 pub fn set_redeem_script(&mut self, redeem_script: Script) -> Result<(), UpdaterError> {
123 if let Some(TransparentAddress::ScriptHash(hash)) = self.0.script_pubkey.address() {
124 if hash[..] == Ripemd160::digest(Sha256::digest(&redeem_script.0))[..] {
125 self.0.redeem_script = Some(redeem_script);
126 Ok(())
127 } else {
128 Err(UpdaterError::WrongRedeemScript)
129 }
130 } else {
131 Err(UpdaterError::NotP2sh)
132 }
133 }
134
135 pub fn set_bip32_derivation(&mut self, pubkey: [u8; 33], derivation: Bip32Derivation) {
137 self.0.bip32_derivation.insert(pubkey, derivation);
138 }
139
140 pub fn set_user_address(&mut self, user_address: String) {
142 self.0.user_address = Some(user_address);
143 }
144
145 pub fn set_proprietary(&mut self, key: String, value: Vec<u8>) {
147 self.0.proprietary.insert(key, value);
148 }
149}
150
151#[derive(Debug)]
153pub enum UpdaterError {
154 InvalidIndex,
156 NotP2sh,
158 WrongRedeemScript,
160}