def from_bytes(Tx, byte_string: bytes) -> 'Tx': '''Instantiate a Tx object from a bytestring''' # Get the version number version = byte_string[0:4] # Check if this is a witness tx if byte_string[4:6] == riemann.network.SEGWIT_TX_FLAG: tx_ins_num_loc = 6 flag = riemann.network.SEGWIT_TX_FLAG else: tx_ins_num_loc = 4 flag = None # Get the length of the tx_in vector tx_ins = [] tx_ins_num = VarInt.from_bytes(byte_string[tx_ins_num_loc:]) # `current` is the index of next read current = tx_ins_num_loc + len(tx_ins_num) # Deserialize all tx_ins for _ in range(tx_ins_num.number): tx_in = TxIn.from_bytes(byte_string[current:]) current += len(tx_in) tx_ins.append(tx_in) # Get the length of the tx_out vector tx_outs = [] tx_outs_num = VarInt.from_bytes(byte_string[current:]) # Deserialize all outputs current += len(tx_outs_num) for _ in range(tx_outs_num.number): tx_out = TxOut.from_bytes(byte_string[current:]) current += len(tx_out) tx_outs.append(tx_out) # Deserialize all witnesses if necessary tx_witnesses: List[InputWitness] = [] if flag and len(byte_string[current:]) > 4: tx_witnesses_num = tx_ins_num for _ in range(tx_witnesses_num.number): tx_witness = InputWitness.from_bytes(byte_string[current:]) current += len(tx_witness) tx_witnesses.append(tx_witness) # Get the lock time and return a complete tx lock_time = byte_string[current:current + 4] return Tx( version=version, flag=flag, tx_ins=tx_ins, tx_outs=tx_outs, tx_witnesses=tx_witnesses, lock_time=lock_time)
def from_bytes(TxIn, byte_string: bytes) -> 'TxIn': ''' Parse a TxIn from a bytestring. Also available as from_hex ''' outpoint = Outpoint.from_bytes(byte_string[:36]) # Extract the script sig length script_sig_len = VarInt.from_bytes(byte_string[36:45]) # Extract the script sig script_start = 36 + len(script_sig_len) script_end = script_start + script_sig_len.number script_sig = byte_string[script_start:script_end] sequence = byte_string[script_end:script_end + 4] # If the script-sig is blank, both stack and redeem are blank if script_sig == b'': stack_script = b'' redeem_script = b'' # If the outpoint is null (coinbase), don't try parsing the script sig elif outpoint == Outpoint.null(): stack_script = script_sig redeem_script = b'' # Parse the script sig into stack and redeem else: stack_script, redeem_script = TxIn._parse_script_sig(script_sig) return TxIn( outpoint=outpoint, stack_script=stack_script, redeem_script=redeem_script, sequence=sequence)
def from_bytes(WitnessStackItem, byte_string: bytes) -> 'WitnessStackItem': ''' Parse a WitnessStackItem from a bytestring. Also available as from_hex ''' n = VarInt.from_bytes(byte_string) item_start = len(n) item_end = item_start + n.number return WitnessStackItem(byte_string[item_start:item_end])
def from_bytes(InputWitness, byte_string): stack_items = VarInt.from_bytes(byte_string) item_start = len(stack_items) items = [] while len(items) < stack_items.number: item = WitnessStackItem.from_bytes(byte_string[item_start:]) item_start += len(item) items.append(item) return InputWitness(items)
def from_bytes(Tx, byte_string): version = byte_string[0:4] if byte_string[4:6] == riemann.network.SEGWIT_TX_FLAG: tx_ins_num_loc = 6 flag = riemann.network.SEGWIT_TX_FLAG else: tx_ins_num_loc = 4 flag = None tx_ins = [] tx_ins_num = VarInt.from_bytes(byte_string[tx_ins_num_loc:]) current = tx_ins_num_loc + len(tx_ins_num) for _ in range(tx_ins_num.number): tx_in = TxIn.from_bytes(byte_string[current:]) current += len(tx_in) tx_ins.append(tx_in) tx_outs = [] tx_outs_num = VarInt.from_bytes(byte_string[current:]) current += len(tx_outs_num) for _ in range(tx_outs_num.number): tx_out = TxOut.from_bytes(byte_string[current:]) current += len(tx_out) tx_outs.append(tx_out) if flag and len(byte_string[current:]) > 4: tx_witnesses = [] tx_witnesses_num = tx_ins_num for _ in range(tx_witnesses_num.number): tx_witness = InputWitness.from_bytes(byte_string[current:]) current += len(tx_witness) tx_witnesses.append(tx_witness) else: tx_witnesses = None lock_time = byte_string[current:current + 4] return Tx(version=version, flag=flag, tx_ins=tx_ins, tx_outs=tx_outs, tx_witnesses=tx_witnesses, lock_time=lock_time)
def from_bytes(TxOut, byte_string): n = VarInt.from_bytes(byte_string[8:]) script_start = 8 + len(n) script_end = script_start + n.number if n.number < 0xfc: return TxOut(value=byte_string[:8], output_script=byte_string[script_start:script_end]) else: raise NotImplementedError( 'No support for abnormally long pk_scripts.')
def from_bytes(InputWitness, byte_string: bytes) -> 'InputWitness': ''' Parse an InputWitness from a bytestring. Also available as from_hex ''' stack_items = VarInt.from_bytes(byte_string) item_start = len(stack_items) items: List[WitnessStackItem] = [] while len(items) < stack_items.number: item = WitnessStackItem.from_bytes(byte_string[item_start:]) item_start += len(item) items.append(item) return InputWitness(items)
def from_bytes(TxOut, byte_string: bytes) -> 'TxOut': ''' Parse a TxOut from a bytestring. Also available as from_hex ''' n = VarInt.from_bytes(byte_string[8:]) script_start = 8 + len(n) script_end = script_start + n.number if n.number < 0xfc: return TxOut( value=byte_string[:8], output_script=byte_string[script_start:script_end]) else: raise NotImplementedError( 'No support for abnormally long pk_scripts.')
def _sighash_prep(self, index: int, script: bytes) -> 'Tx': ''' Sighashes suck Performs the sighash setup described here: https://en.bitcoin.it/wiki/OP_CHECKSIG#How_it_works https://bitcoin.stackexchange.com/questions/3374/how-to-redeem-a-basic-tx We save on complexity by refusing to support OP_CODESEPARATOR ''' # 0 out scripts in tx_ins copy_tx_ins = [tx_in.copy(stack_script=b'', redeem_script=b'') for tx_in in self.tx_ins] # NB: The script for the current transaction input in txCopy is set to # subScript (lead in by its length as a var-integer encoded!) to_strip = VarInt.from_bytes(script) copy_tx_ins[index] = \ copy_tx_ins[index].copy(redeem_script=script[len(to_strip):]) return self.copy(tx_ins=copy_tx_ins)
def from_bytes(TxIn, byte_string): ''' byte_string -> TxIn parses a TxIn from a byte-like object ''' outpoint = Outpoint.from_bytes(byte_string[:36]) script_sig_len = VarInt.from_bytes(byte_string[36:45]) script_start = 36 + len(script_sig_len) script_end = script_start + script_sig_len.number script_sig = byte_string[script_start:script_end] sequence = byte_string[script_end:script_end + 4] if script_sig == b'': stack_script = b'' redeem_script = b'' else: stack_script, redeem_script = TxIn._parse_script_sig(script_sig) return TxIn(outpoint=outpoint, stack_script=stack_script, redeem_script=redeem_script, sequence=sequence)
def from_bytes(WitnessStackItem, byte_string): n = VarInt.from_bytes(byte_string) item_start = len(n) item_end = item_start + n.number return WitnessStackItem(byte_string[item_start:item_end])