@@ -143,53 +143,48 @@ def __repr__(self):
143143 @staticmethod
144144 def from_raw (txinputrawhex : str , cursor : int = 0 , has_segwit : bool = False ):
145145 """
146- Imports a TxInput from a Transaction's hexadecimal data using struct for parsing.
146+ Imports a TxInput from a Transaction's hexadecimal data
147147
148- Args:
149- txinputrawhex (str): The hexadecimal raw string of the Transaction.
150- cursor (int): The position at which the algorithm will start to read the data.
151- has_segwit (bool): Indicates if the Tx Input is SegWit enabled.
152-
153- Returns:
154- tuple: (TxInput object, new cursor position)
155-
156- Raises:
157- Exception: If the transaction hash or script is malformed.
148+ Attributes
149+ ----------
150+ txinputrawhex : string (hex)
151+ The hexadecimal raw string of the Transaction
152+ cursor : int
153+ The cursor of which the algorithm will start to read the data
154+ has_segwit : boolean
155+ Is the Tx Input segwit or not
158156 """
159157 txinputraw = h_to_b (txinputrawhex )
160158
161- # Unpack transaction ID (hash) and output index
162- txid_format = "<32s4s"
163- txid , vout = struct .unpack_from (txid_format , txinputraw , cursor )
164- txid = txid [::- 1 ].hex () # Reverse to match usual hexadecimal order
165- cursor += 36 # Advance cursor by 32 bytes for txid and 4 bytes for vout
159+ # Unpack transaction ID (hash) in bytes and output index
160+ txid , vout = struct .unpack_from ('<32sI' , txinputraw , cursor )
161+ txid = txid [::- 1 ] # Reverse to match usual hexadecimal order
162+ cursor += 36 # 32 bytes for txid and 4 bytes for vout
166163
167164 # Read the unlocking script size using parse_compact_size
168- unlocking_script_size , size = vi_to_int (txinputraw [cursor : cursor + 8 ])
165+ unlocking_script_size , size = parse_compact_size (txinputraw [cursor : ])
169166 cursor += size
170167
171- # Read the unlocking script, keeping it in bytes
172- script_format = f"{ unlocking_script_size } s"
173- unlocking_script , = struct .unpack_from (script_format , txinputraw , cursor )
168+ # Read the unlocking script in bytes
169+ unlocking_script = struct .unpack_from (f'{ unlocking_script_size } s' , txinputraw , cursor )[0 ]
174170 cursor += unlocking_script_size
175171
176- # Read the sequence number, maintaining byte format
177- sequence_format = "<4s"
178- sequence , = struct .unpack_from (sequence_format , txinputraw , cursor )
172+ # Read the sequence number in bytes
173+ sequence , = struct .unpack_from ('<4s' , txinputraw , cursor )
179174 cursor += 4
180175
181- # If coinbase input, handle differently
182- if txid == 64 * '0' :
176+ # If coinbase input (utxo will be all zeros) , handle script differently
177+ if txid . hex () == '00' * 32 :
183178 script_sig = Script ([unlocking_script .hex ()]) # Treat as single element for coinbase
184179 else :
185180 script_sig = Script .from_raw (unlocking_script .hex (), has_segwit = has_segwit )
186181
187182 # Create the TxInput instance
188183 tx_input = TxInput (
189- txid = txid ,
190- txout_index = int . from_bytes ( vout , 'little' ), # Convert vout from bytes to integer when needed
184+ txid = txid . hex () ,
185+ txout_index = vout ,
191186 script_sig = script_sig ,
192- sequence = sequence # Keep sequence as bytes
187+ sequence = sequence
193188 )
194189
195190 return tx_input , cursor
@@ -293,43 +288,42 @@ def to_bytes(self) -> bytes:
293288 @staticmethod
294289 def from_raw (txoutputrawhex : str , cursor : int = 0 , has_segwit : bool = False ):
295290 """
296- Imports a TxOutput from a Transaction's hexadecimal data using struct for parsing.
291+ Imports a TxOutput from a Transaction's hexadecimal data
297292
298- Args:
299- txoutputrawhex (str): The hexadecimal raw string of the Transaction.
300- cursor (int): The position at which the algorithm will start to read the data.
301- has_segwit (bool): Indicates if the Tx Output is SegWit enabled.
302-
303- Returns:
304- tuple: (TxOutput object, new cursor position)
305-
306- Raises:
307- Exception: If the amount or script is malformed.
293+ Attributes
294+ ----------
295+ txoutputrawhex : string (hex)
296+ The hexadecimal raw string of the Transaction
297+ cursor : int
298+ The cursor of which the algorithm will start to read the data
299+ has_segwit : boolean
300+ Is the Tx Output segwit or not
308301 """
309302 txoutputraw = h_to_b (txoutputrawhex )
310303
311- # Unpack the output value (amount) keeping it in bytes
312- amount_format = "<8s " # Little-endian unsigned long long (8 bytes)
313- amount_bytes , = struct .unpack_from (amount_format , txoutputraw , cursor )
304+ # Unpack the amount of the TxOutput directly in bytes
305+ amount_format = "<Q " # Little-endian unsigned long long (8 bytes)
306+ amount , = struct .unpack_from (amount_format , txoutputraw , cursor )
314307 cursor += struct .calcsize (amount_format )
315308
316- # Read the locking script size using parse_compact_size, assuming it returns bytes length in int
317- lock_script_size , size = vi_to_int (txoutputraw [cursor : cursor + 9 ])
309+ # Read the locking script size using parse_compact_size
310+ lock_script_size , size = parse_compact_size (txoutputraw [cursor : ])
318311 cursor += size
319312
320- # Read the locking script, maintaining it in bytes
313+ # Read the locking script
321314 script_format = f"{ lock_script_size } s"
322315 lock_script , = struct .unpack_from (script_format , txoutputraw , cursor )
323316 cursor += lock_script_size
324317
325318 # Create the TxOutput instance
326319 tx_output = TxOutput (
327- amount = int . from_bytes ( amount_bytes , 'little' ), # Convert amount from bytes to integer when needed
320+ amount = amount ,
328321 script_pubkey = Script .from_raw (lock_script .hex (), has_segwit = has_segwit )
329322 )
330323
331324 return tx_output , cursor
332325
326+
333327 def __str__ (self ) -> str :
334328 return str ({"amount" : self .amount , "script_pubkey" : self .script_pubkey })
335329
@@ -534,34 +528,27 @@ def __init__(
534528 @staticmethod
535529 def from_raw (rawtxhex : str ):
536530 """
537- Imports a Transaction from hexadecimal data using struct for parsing.
538-
539- Args:
540- rawtxhex (str): The hexadecimal raw string of the Transaction.
531+ Imports a Transaction from hexadecimal data.
541532
542- Returns:
543- Transaction: A fully parsed Transaction object.
544-
545- Raises:
546- Exception: If the transaction data is malformed.
533+ Attributes
534+ ----------
535+ rawtxhex : string (hex)
536+ The hexadecimal raw string of the Transaction.
547537 """
548538 rawtx = h_to_b (rawtxhex )
549- cursor = 0
550539
551- # Unpack version (4 bytes) and keep it in bytes
552- version , = struct . unpack_from ( '<4s' , rawtx , cursor )
553- cursor + = 4
540+ # Read version (4 bytes)
541+ version = rawtx [ 0 : 4 ]
542+ cursor = 4
554543
555544 # Detect and handle SegWit
556- flag = None
557545 has_segwit = False
558- if rawtx [cursor ] == 0x00 and rawtx [cursor + 1 ] == 0x01 :
559- flag = rawtx [cursor + 1 ]
546+ if rawtx [cursor :cursor + 2 ] == b'\x00 \x01 ' :
560547 has_segwit = True
561- cursor += 2 # Skip past the marker and flag bytes
548+ cursor += 2 # Skipping past the marker and flag bytes
562549
563550 # Read the number of inputs
564- n_inputs , size = vi_to_int (rawtx [cursor : cursor + 9 ])
551+ n_inputs , size = parse_compact_size (rawtx [cursor : ])
565552 cursor += size
566553 inputs = []
567554
@@ -570,8 +557,8 @@ def from_raw(rawtxhex: str):
570557 inp , cursor = TxInput .from_raw (rawtx .hex (), cursor , has_segwit )
571558 inputs .append (inp )
572559
573- # Read the number of outputs
574- n_outputs , size = vi_to_int (rawtx [cursor : cursor + 9 ])
560+ # Read the number of outputs using parse_compact_size
561+ n_outputs , size = parse_compact_size (rawtx [cursor : ])
575562 cursor += size
576563 outputs = []
577564
@@ -584,32 +571,31 @@ def from_raw(rawtxhex: str):
584571 witnesses = []
585572 if has_segwit :
586573 for _ in range (n_inputs ):
587- n_items , size = vi_to_int (rawtx [cursor : cursor + 9 ])
574+ n_items , size = parse_compact_size (rawtx [cursor : ])
588575 cursor += size
589- witness_stack = []
590- for __ in range (n_items ):
591- item_size , size = vi_to_int (rawtx [cursor : cursor + 9 ])
576+ witnesses_tmp = []
577+ for _ in range (n_items ):
578+ item_size , size = parse_compact_size (rawtx [cursor : ])
592579 cursor += size
593580 witness_data = rawtx [cursor :cursor + item_size ]
594581 cursor += item_size
595- witness_stack .append (witness_data .hex ())
596- witnesses .append (TxWitnessInput (stack = witness_stack ))
582+ witnesses_tmp .append (witness_data .hex ())
583+ if witnesses_tmp :
584+ witnesses .append (TxWitnessInput (stack = witnesses_tmp ))
597585
598- # Unpack locktime (4 bytes) and keep it in bytes
599- locktime , = struct .unpack_from ('<4s' , rawtx , cursor )
600- cursor += 4
586+ # Read locktime (4 bytes)
587+ locktime = rawtx [cursor :cursor + 4 ]
601588
602- # Construct and return the Transaction object
589+ #Returning the Transaction object
603590 return Transaction (
604591 inputs = inputs ,
605592 outputs = outputs ,
606593 version = version ,
607594 locktime = locktime ,
608595 has_segwit = has_segwit ,
609- witnesses = witnesses
596+ witnesses = witnesses ,
610597 )
611598
612-
613599 def __str__ (self ) -> str :
614600 return str (
615601 {
0 commit comments