@@ -399,13 +399,19 @@ def __init__(self, vin=(), vout=(), nLockTime=0, nVersion=1, witness=CTxWitness(
399399
400400 @classmethod
401401 def stream_deserialize (cls , f ):
402+ """Deserialize a transaction. This implementation corresponds to
403+ Bitcoin's SerializeTransaction() and consensus behavior. Note that
404+ Bitcoin's DecodeHexTx() also has the option to attempt deserializing
405+ as a non-witness transaction first, falling back to the consensus
406+ behavior if it fails. The difference lies in transactions which
407+ have zero inputs: they are invalid but may be (de-)serialized anyway
408+ for the purpose of signing them and adding inputs. If the behavior
409+ of DecodeHexTx() is needed it could be added, but not here. """
402410 nVersion = struct .unpack (b"<i" , ser_read (f ,4 ))[0 ]
403411 pos = f .tell ()
404412 markerbyte = struct .unpack (b'B' , ser_read (f , 1 ))[0 ]
405- if markerbyte == 0 :
406- flagbyte = struct .unpack (b'B' , ser_read (f , 1 ))[0 ]
407- if flagbyte != 1 :
408- raise DeserializationFormatError
413+ flagbyte = struct .unpack (b'B' , ser_read (f , 1 ))[0 ]
414+ if markerbyte == 0 and flagbyte == 1 :
409415 vin = VectorSerializer .stream_deserialize (CTxIn , f )
410416 vout = VectorSerializer .stream_deserialize (CTxOut , f )
411417 wit = CTxWitness (tuple (0 for dummy in range (len (vin ))))
@@ -421,21 +427,18 @@ def stream_deserialize(cls, f):
421427
422428
423429 def stream_serialize (self , f ):
430+ f .write (struct .pack (b"<i" , self .nVersion ))
424431 if not self .wit .is_null ():
425- if len (self .wit .vtxinwit ) != len (self .vin ):
426- raise SerializationMissingWitnessError
427- f .write (struct .pack (b"<i" , self .nVersion ))
432+ assert (len (self .wit .vtxinwit ) <= len (self .vin ))
428433 f .write (b'\x00 ' ) # Marker
429434 f .write (b'\x01 ' ) # Flag
430435 VectorSerializer .stream_serialize (CTxIn , self .vin , f )
431436 VectorSerializer .stream_serialize (CTxOut , self .vout , f )
432437 self .wit .stream_serialize (f )
433- f .write (struct .pack (b"<I" , self .nLockTime ))
434438 else :
435- f .write (struct .pack (b"<i" , self .nVersion ))
436439 VectorSerializer .stream_serialize (CTxIn , self .vin , f )
437440 VectorSerializer .stream_serialize (CTxOut , self .vout , f )
438- f .write (struct .pack (b"<I" , self .nLockTime ))
441+ f .write (struct .pack (b"<I" , self .nLockTime ))
439442
440443 def is_coinbase (self ):
441444 return len (self .vin ) == 1 and self .vin [0 ].prevout .is_null ()
0 commit comments