Exemple #1
0
    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)
Exemple #2
0
    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)
Exemple #3
0
 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])
Exemple #4
0
 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)
Exemple #5
0
    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)
Exemple #6
0
 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.')
Exemple #7
0
 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)
Exemple #8
0
 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.')
Exemple #9
0
    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)
Exemple #10
0
    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)
Exemple #11
0
 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])