@@ -73,6 +73,8 @@ pub enum ProofError {
7373 InvalidOutput ,
7474 /// Input and output values are not equal, implying a miner fee
7575 InAndOutValueNotEqual ,
76+ /// No matching outpoing found
77+ OutpointNotFound ( usize ) ,
7678}
7779
7880impl < B , D > ProofOfReserves for Wallet < B , D >
@@ -115,7 +117,7 @@ where
115117 let outpoints = self
116118 . list_unspent ( ) ?
117119 . iter ( )
118- . map ( |utxo| utxo. outpoint )
120+ . map ( |utxo| ( utxo. outpoint , utxo . txout . clone ( ) ) )
119121 . collect ( ) ;
120122
121123 verify_proof ( psbt, message, outpoints, self . network )
@@ -131,7 +133,7 @@ where
131133pub fn verify_proof (
132134 psbt : & PSBT ,
133135 message : & str ,
134- outpoints : Vec < OutPoint > ,
136+ outpoints : Vec < ( OutPoint , TxOut ) > ,
135137 network : Network ,
136138) -> Result < u64 , Error > {
137139 let tx = psbt. clone ( ) . extract_tx ( ) ;
@@ -155,7 +157,7 @@ pub fn verify_proof(
155157 . iter ( )
156158 . enumerate ( )
157159 . skip ( 1 )
158- . find ( |( _i, inp) | outpoints. iter ( ) . find ( |op| * * op == inp. previous_output ) == None )
160+ . find ( |( _i, inp) | outpoints. iter ( ) . find ( |op| op . 0 == inp. previous_output ) == None )
159161 {
160162 return Err ( Error :: Proof ( ProofError :: NonSpendableInput ( i) ) ) ;
161163 }
@@ -178,29 +180,45 @@ pub fn verify_proof(
178180 return Err ( Error :: Proof ( ProofError :: UnsupportedSighashType ( i) ) ) ;
179181 }
180182
181- // Verify other inputs against prevouts and calculate the amount.
182183 let serialized_tx = serialize ( & tx) ;
183- if let Some ( ( i, res) ) = psbt
184- . inputs
184+ // Verify the challenge input
185+ if let Some ( utxo) = & psbt. inputs [ 0 ] . witness_utxo {
186+ if let Err ( err) = bitcoinconsensus:: verify (
187+ utxo. script_pubkey . to_bytes ( ) . as_slice ( ) ,
188+ utxo. value ,
189+ & serialized_tx,
190+ 0 ,
191+ ) {
192+ return Err ( Error :: Proof ( ProofError :: SignatureValidation (
193+ 0 ,
194+ format ! ( "{:?}" , err) ,
195+ ) ) ) ;
196+ }
197+ } else {
198+ return Err ( Error :: Proof ( ProofError :: SignatureValidation (
199+ 0 ,
200+ "witness_utxo not found for challenge input" . to_string ( ) ,
201+ ) ) ) ;
202+ }
203+ // Verify other inputs against prevouts.
204+ if let Some ( ( i, res) ) = tx
205+ . input
185206 . iter ( )
186- . zip ( tx. input . iter ( ) )
187207 . enumerate ( )
188- . map ( |( i, ( psbt_in, tx_in) ) | {
189- if let Some ( utxo) = & psbt_in. witness_utxo {
190- ( i, Ok ( ( & utxo. script_pubkey , utxo. value ) ) )
191- } else if let Some ( nwtx) = & psbt_in. non_witness_utxo {
192- let outp = & nwtx. output [ tx_in. previous_output . vout as usize ] ;
193- ( i, Ok ( ( & outp. script_pubkey , outp. value ) ) )
208+ . skip ( 1 )
209+ . map ( |( i, tx_in) | {
210+ if let Some ( op) = outpoints. iter ( ) . find ( |op| op. 0 == tx_in. previous_output ) {
211+ ( i, Ok ( op. 1 . clone ( ) ) )
194212 } else {
195- ( i, Err ( Error :: Proof ( ProofError :: NeitherWitnessNorLegacy ( i) ) ) )
213+ ( i, Err ( Error :: Proof ( ProofError :: OutpointNotFound ( i) ) ) )
196214 }
197215 } )
198216 . map ( |( i, res) | match res {
199- Ok ( ( script , value ) ) => (
217+ Ok ( txout ) => (
200218 i,
201219 Ok ( bitcoinconsensus:: verify (
202- script . to_bytes ( ) . as_slice ( ) ,
203- value,
220+ txout . script_pubkey . to_bytes ( ) . as_slice ( ) ,
221+ txout . value ,
204222 & serialized_tx,
205223 i,
206224 ) ) ,
@@ -219,12 +237,9 @@ pub fn verify_proof(
219237 let sum = tx
220238 . input
221239 . iter ( )
222- . zip ( psbt. inputs . iter ( ) )
223- . map ( |( tx_in, psbt_in) | {
224- if let Some ( utxo) = & psbt_in. witness_utxo {
225- utxo. value
226- } else if let Some ( nwtx) = & psbt_in. non_witness_utxo {
227- nwtx. output [ tx_in. previous_output . vout as usize ] . value
240+ . map ( |tx_in| {
241+ if let Some ( op) = outpoints. iter ( ) . find ( |op| op. 0 == tx_in. previous_output ) {
242+ op. 1 . value
228243 } else {
229244 0
230245 }
0 commit comments