88use core:: fmt;
99
1010use super :: {
11- AssetIssuance , OutPoint , Script , Sequence , TxIn , TxInWitness , TxOut , TxOutWitness , Txid ,
11+ AssetIssuance , OutPoint , Script , Sequence , Transaction , TxIn , TxInWitness , TxOut , TxOutWitness ,
12+ Txid ,
1213} ;
1314use crate :: confidential:: { RangeProofDecoder , RangeProofDecoderError } ;
1415use crate :: encoding:: {
1516 ArrayDecoder , Decode , Decoder , Decoder2 , Decoder2Error , Decoder3 , Decoder4 , Decoder4Error ,
16- DecoderStatus , UnexpectedEofError ,
17+ DecoderStatus , UnexpectedEofError , VecDecoder ,
1718} ;
19+ use crate :: locktime:: { LockTime , LockTimeDecoder } ;
1820use crate :: { PeginWitnessDecoder , PeginWitnessDecoderError , WitnessDecoder , WitnessDecoderError } ;
1921
2022/// Decoder for the [`OutPoint`] type.
@@ -130,9 +132,6 @@ impl std::error::Error for AssetIssuanceDecoderError {
130132 }
131133}
132134
133- fn vout_is_pegin ( vout : u32 ) -> bool { vout != 0xffff_ffff && vout & ( 1 << 30 ) != 0 }
134- fn vout_has_issuance ( vout : u32 ) -> bool { vout != 0xffff_ffff && vout & ( 1 << 31 ) != 0 }
135-
136135decoder_state_machine ! {
137136 /// Decoder for the [`TxIn`] type.
138137 pub struct TxInDecoder ( enum TxInDecoderInner {
@@ -146,17 +145,25 @@ decoder_state_machine! {
146145 >,
147146 => transition_initial( output, ...) -> Result {
148147 let ( mut outpoint, script_sig, sequence) = output;
149- if vout_has_issuance( outpoint. vout) {
148+ let ( is_pegin, has_issuance) = if outpoint. vout == 0xffff_ffff {
149+ ( false , false )
150+ } else {
151+ let vout = outpoint. vout;
152+ outpoint. vout &= !( ( 1 << 30 ) | ( 1 << 31 ) ) ;
153+ ( vout & ( 1 << 30 ) != 0 , vout & ( 1 << 31 ) != 0 )
154+ } ;
155+ if has_issuance {
150156 Ok ( TxInDecoderInner :: AssetIssuance {
151157 decoder: AssetIssuanceDecoder :: default ( ) ,
152- outpoint, script_sig, sequence,
158+ outpoint, script_sig, sequence, is_pegin ,
153159 } )
154160 } else {
155- let orig_vout = outpoint. vout;
156- outpoint. vout &= !( ( 1 << 30 ) | ( 1 << 31 ) ) ;
161+ if outpoint. vout != 0xffff_ffff {
162+ outpoint. vout &= !( ( 1 << 30 ) | ( 1 << 31 ) ) ;
163+ }
157164 Ok ( TxInDecoderInner :: Done ( TxIn {
158165 previous_output: outpoint,
159- is_pegin: vout_is_pegin ( orig_vout ) ,
166+ is_pegin,
160167 script_sig,
161168 sequence,
162169 asset_issuance: AssetIssuance :: null( ) ,
@@ -169,18 +176,16 @@ decoder_state_machine! {
169176 decoder: AssetIssuanceDecoder ,
170177 outpoint: OutPoint ,
171178 script_sig: Script ,
172- sequence: Sequence
179+ sequence: Sequence ,
180+ is_pegin: bool
173181 => transition_asset_issuance( asset_issuance, ...) -> Result {
174182 if asset_issuance. is_null( ) {
175183 return Err ( TxInDecoderErrorInner :: SuperfluousIssuance ) ;
176184 }
177185
178- let orig_vout = outpoint. vout;
179- let mut outpoint = outpoint;
180- outpoint. vout &= !( ( 1 << 30 ) | ( 1 << 31 ) ) ;
181186 Ok ( TxInDecoderInner :: Done ( TxIn {
182187 previous_output: outpoint,
183- is_pegin: vout_is_pegin ( orig_vout ) ,
188+ is_pegin,
184189 script_sig,
185190 sequence,
186191 asset_issuance,
@@ -292,7 +297,6 @@ struct TxInWitnessesDecoder {
292297}
293298
294299impl TxInWitnessesDecoder {
295- #[ allow( dead_code) ] // will be used in the Transaction Encode/Decode commit
296300 fn new ( txins : Vec < TxIn > ) -> Self { Self { txins, index : 0 , decoder : None } }
297301}
298302
@@ -369,7 +373,6 @@ struct TxOutWitnessesDecoder {
369373}
370374
371375impl TxOutWitnessesDecoder {
372- #[ allow( dead_code) ] // will be used in the Transaction Encode/Decode commit
373376 fn new ( txouts : Vec < TxOut > ) -> Self { Self { txouts, index : 0 , decoder : None } }
374377}
375378
@@ -437,3 +440,107 @@ decoder_newtype! {
437440 }
438441 }
439442}
443+
444+ decoder_state_machine ! {
445+ /// Decoder for the [`Transaction`] type.
446+ pub struct TransactionDecoder ( enum TransactionDecoderInner {
447+ Done ( Transaction ) ,
448+ Errored ,
449+ DecodingNonWitness {
450+ decoder: Decoder4 <
451+ ArrayDecoder <4 >,
452+ ArrayDecoder <1 >,
453+ Decoder2 <
454+ VecDecoder <TxIn >,
455+ VecDecoder <TxOut >,
456+ >,
457+ LockTimeDecoder ,
458+ >,
459+ => transition_non_witness( output, ...) -> Result {
460+ let ( version, wit_flag, ( input, output) , lock_time) = output;
461+ match wit_flag {
462+ [ 0 ] => Ok ( TransactionDecoderInner :: Done ( Transaction {
463+ version: u32 :: from_le_bytes( version) ,
464+ lock_time,
465+ input,
466+ output,
467+ } ) ) ,
468+ [ 1 ] => Ok ( TransactionDecoderInner :: DecodingWitnesses {
469+ decoder: Decoder2 :: new(
470+ TxInWitnessesDecoder :: new( input) ,
471+ TxOutWitnessesDecoder :: new( output) ,
472+ ) ,
473+ version: u32 :: from_le_bytes( version) ,
474+ lock_time,
475+ } ) ,
476+ [ x] => Err ( TransactionDecoderErrorInner :: InvalidWitnessFlag ( x) ) ,
477+ }
478+ }
479+ } ,
480+ DecodingWitnesses {
481+ decoder: Decoder2 <
482+ TxInWitnessesDecoder ,
483+ TxOutWitnessesDecoder ,
484+ >,
485+ version: u32 ,
486+ lock_time: LockTime
487+ => transition_witnesses( output, ...) -> Result {
488+ let ( input, output) = output;
489+ if input. iter( ) . all( |input| input. witness. is_empty( ) ) &&
490+ output. iter( ) . all( |output| output. witness. is_empty( ) ) {
491+ Err ( TransactionDecoderErrorInner :: NoWitnesses )
492+ } else {
493+ Ok ( TransactionDecoderInner :: Done ( Transaction {
494+ version,
495+ lock_time,
496+ input,
497+ output,
498+ } ) )
499+ }
500+ }
501+ } ,
502+ } ) ;
503+
504+ /// Decoder error for the [`Transaction`] type.
505+ #[ derive( Clone , PartialEq , Eq , Debug ) ]
506+ pub struct TransactionDecoderError ( enum TransactionDecoderErrorInner {
507+ [ macro-inserted decoder variants]
508+ InvalidWitnessFlag ( u8 ) ,
509+ NoWitnesses ,
510+ } ) ;
511+ }
512+
513+ impl Default for TransactionDecoder {
514+ fn default ( ) -> Self {
515+ Self ( TransactionDecoderInner :: DecodingNonWitness { decoder : Decoder4 :: default ( ) } )
516+ }
517+ }
518+
519+ impl fmt:: Display for TransactionDecoderError {
520+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
521+ use TransactionDecoderErrorInner as Inner ;
522+
523+ match self . 0 {
524+ Inner :: DecodingNonWitness ( ..) =>
525+ f. write_str ( "failed to decode non-witness part of transaction" ) ,
526+ Inner :: DecodingWitnesses ( ..) => f. write_str ( "failed to decode transaction witnesses" ) ,
527+ Inner :: InvalidWitnessFlag ( flag) => {
528+ write ! ( f, "invalid witness flag {flag} (must be 0 or 1)" )
529+ }
530+ Inner :: NoWitnesses => f. write_str ( "witness flag set but all witnesses were empty" ) ,
531+ }
532+ }
533+ }
534+
535+ impl std:: error:: Error for TransactionDecoderError {
536+ fn source ( & self ) -> Option < & ( dyn std:: error:: Error + ' static ) > {
537+ use TransactionDecoderErrorInner as Inner ;
538+
539+ match self . 0 {
540+ Inner :: DecodingNonWitness ( ref e) => Some ( e) ,
541+ Inner :: DecodingWitnesses ( ref e) => Some ( e) ,
542+ Inner :: InvalidWitnessFlag ( _) => None ,
543+ Inner :: NoWitnesses => None ,
544+ }
545+ }
546+ }
0 commit comments