コード例 #1
0
ファイル: merkle.py プロジェクト: ctebbe/bitcoin-spv
def verify_proof(proof, index):
    index = index  # This is 1 indexed
    # TODO: making creating and verifying indexes the same
    root = proof[-32:]
    current = proof[0:32]

    # For all hashes between first and last
    for i in range(1, len(proof) // 32 - 1):
        # If the current index is even,
        # The next hash goes before the current one
        if index % 2 == 0:
            current = utils.hash256(
                proof[i * 32: (i + 1) * 32] +
                current
            )
            # Halve and floor the index
            index = index // 2
        else:
            # The next hash goes after the current one
            current = utils.hash256(
                current +
                proof[i * 32: (i + 1) * 32]
            )
            # Halve and ceil the index
            index = index // 2 + 1
    # At the end we should have made the root
    if current != root:
        return False
    return True
コード例 #2
0
def verify_proof(proof: bytes, index: int) -> bool:
    '''
    Verifies a hash256 merkle proof.
    The proof is encoded as a bytestring. The first 32 bytes are the leaf hash,
    the last 32 bytes are the roothash.
    Args:
        proof (bytes): The merkle proof as a bytestring
        index   (int): The 0-indexed position of the leaf in the leafset
    Returns:
        (bool): True if valid proof, else False
    '''
    idx = index
    length = (len(proof) // 32) - 1

    if len(proof) % 32 != 0:
        return False

    if len(proof) == 32:
        return True

    # Should never occur
    if len(proof) == 64:
        return False

    current = proof[:32]
    root = proof[-32:]
    # For all hashes between first and last
    for i in range(1, length):
        next = proof[i * 32:i * 32 + 32]
        if idx % 2 == 1:
            current = rutils.hash256(next + current)
        else:
            current = rutils.hash256(current + next)
        idx = idx >> 1
    return current == root
コード例 #3
0
    def _hash_outputs(self, index, sighash_type):
        '''BIP143 hashOutputs implementation

        Args:
            index        (int): index of input being signed
            sighash_type (int): SIGHASH_SINGLE or SIGHASH_ALL
        Returns:
            (bytes): the hashOutputs, a 32 byte hash
        '''
        if sighash_type == shared.SIGHASH_ALL:
            # If the sighash type is ALL,
            # hashOutputs is the double SHA256 of all output amounts
            # paired up with their scriptPubKey;
            outputs = ByteData()
            for tx_out in self.tx_outs:
                outputs += tx_out.to_bytes()
            return utils.hash256(outputs.to_bytes())
        elif (sighash_type == shared.SIGHASH_SINGLE
              and index < len(self.tx_outs)):
            # if sighash type is SINGLE
            # and the input index is smaller than the number of outputs,
            # hashOutputs is the double SHA256 of the output at the same index
            return utils.hash256(self.tx_outs[index].to_bytes())
        else:
            # Otherwise, hashOutputs is a uint256 of 0x0000......0000
            raise NotImplementedError(
                'I refuse to implement the SIGHASH_SINGLE bug.')
コード例 #4
0
def verify_proof(proof: bytes, index: int) -> bool:
    '''
    verifies a merkle leaf occurs at a specified index given a merkle proof
    '''
    index = index  # This is 1 indexed
    # TODO: making creating and verifying indexes the same
    root = proof[-32:]
    current = proof[0:32]

    # For all hashes between first and last
    for i in range(1, len(proof) // 32 - 1):
        # If the current index is even,
        # The next hash goes before the current one
        if index % 2 == 0:
            current = rutils.hash256(proof[i * 32:(i + 1) * 32] + current)
            # Halve and floor the index
            index = index // 2
        else:
            # The next hash goes after the current one
            current = rutils.hash256(current + proof[i * 32:(i + 1) * 32])
            # Halve and ceil the index
            index = index // 2 + 1
        print(current.hex())
    # At the end we should have made the root
    if current != root:
        return False
    return True
コード例 #5
0
ファイル: merkle.py プロジェクト: ctebbe/bitcoin-spv
def create_proof(tx_hashes, index):
    idx = index - 1  # This is 0-indexed
    # TODO: making creating and verifying indexes the same
    hashes = [h for h in tx_hashes]  # copy the list
    proof = bytearray(hashes[idx])

    while len(hashes) > 1:
        next_tree_row = []

        # if length is odd, duplicate last entry
        if len(hashes) % 2 != 0:
            hashes.append(hashes[-1])

        # Append next hash to proof
        proof += hashes[idx + (1 if idx % 2 == 0 else -1)]

        # Half the index
        idx = idx // 2

        # Take each pair in order, and hash them
        for i in range(0, len(hashes), 2):
            next_tree_row.append(utils.hash256(hashes[i] + hashes[i + 1]))

        # update tx_hashes
        hashes = next_tree_row

    # Put the root on the end
    proof.extend(hashes[0])
    return proof
コード例 #6
0
ファイル: validate_spv.py プロジェクト: xuyp1991/bitcoin-spv
def validate_header(header: RelayHeader) -> bool:
    '''
    Verifies a bitcoin header
    Args:
        header (RelayHeader): The header as an object

    Returns:
        (bool): True if valid header, else False
    '''
    # Check that HashLE is the correct hash of the raw header
    header_hash = rutils.hash256(header['raw'])
    if header_hash != header['hash']:
        return False

    # Check that the MerkleRootLE is the correct MerkleRoot for the header
    extracted_merkle_root = extract_merkle_root_le(header['raw'])
    if extracted_merkle_root != header['merkle_root']:
        return False

    # Check that PrevHash is the correct PrevHash for the header
    extracted_prevhash = extract_prev_block_le(header['raw'])
    if extracted_prevhash != header['prevhash']:
        return False

    return True
コード例 #7
0
def parse_header(header: str) -> Header:
    '''
    Parses a header to a dict
    Args:
        header (str): hex formatted 80 byte header
    Returns:
        dict:
            hash        (str): the header hash 0000-first
            version     (int): the block version as an int
            prev_block  (str): the previous block hash 0000-first
            merkle_root (str): the block transaction merkle tree root
            timestamp   (int): the block header timestamp
            nbits       (str): the difficulty bits
            nonce       (str): the nonce
            difficulty  (int): the difficulty as an int
            hex         (str): the full header as hex
            height      (int): the block height (always 0)
    '''
    if len(header) != 160:
        raise ValueError('Invalid header received')
    as_bytes = bytes.fromhex(header)
    nbits = as_bytes[72:76]
    return {
        'hash': rutils.hash256(bytes.fromhex(header))[::-1].hex(),
        'version': rutils.le2i(as_bytes[0:4]),
        'prev_block': as_bytes[4:36][::-1].hex(),
        'merkle_root': as_bytes[36:68].hex(),
        'timestamp': rutils.le2i(as_bytes[68:72]),
        'nbits': nbits.hex(),
        'nonce': as_bytes[76:80].hex(),
        'difficulty': parse_difficulty(nbits),
        'hex': header,
        'height': 0,
        'accumulated_work': 0
    }
コード例 #8
0
def validate_spvproof(proof: SPVProof) -> bool:
    '''
    Verifies an SPV proof object
    Args:
        proof (SPVProof): The SPV Proof as an object
    Returns:
        (bool): True if valid proof, else False
    '''
    if not validate_vin(proof['vin']):
        return False

    if not validate_vout(proof['vout']):
        return False

    tx_id = rutils.hash256(proof['version'] + proof['vin'] + proof['vout'] +
                           proof['locktime'])
    if tx_id != proof['tx_id_le']:
        return False

    if not validate_header(proof['confirming_header']):
        return False

    valid_proof = prove(proof['tx_id_le'],
                        proof['confirming_header']['merkle_root_le'],
                        proof['intermediate_nodes'], proof['index'])
    if not valid_proof:
        return False
    return True
コード例 #9
0
def encode(data: bytes, checksum: bool = True) -> str:
    '''Convert binary to base58 using BASE58_ALPHABET.'''

    if checksum:
        data = data + utils.hash256(data)[:4]
    v, prefix = to_long(256, lambda x: x, data)
    data = from_long(v, prefix, BASE58_BASE, lambda v: BASE58_ALPHABET[v])
    return data.decode("utf8")
コード例 #10
0
 def _sighash_final_hashing(self, copy_tx, sighash_type):
     '''
     SproutTx, int -> bytes
     Returns the hash that should be signed
     https://en.bitcoin.it/wiki/OP_CHECKSIG#Procedure_for_Hashtype_SIGHASH_ANYONECANPAY
     '''
     sighash = z.ZcashByteData()
     sighash += copy_tx.to_bytes()
     sighash += utils.i2le_padded(sighash_type, 4)
     return utils.hash256(sighash.to_bytes())
コード例 #11
0
 def _hash_prevouts(self, anyone_can_pay):
     if anyone_can_pay:
         # If the ANYONECANPAY flag is set,
         # hashPrevouts is a uint256 of 0x0000......0000.
         hash_prevouts = b'\x00' * 32
     else:
         # hashPrevouts is the double SHA256 of all outpoints;
         outpoints = ByteData()
         for tx_in in self.tx_ins:
             outpoints += tx_in.outpoint
         hash_prevouts = utils.hash256(outpoints.to_bytes())
     return hash_prevouts
コード例 #12
0
ファイル: tx.py プロジェクト: summa-tx/riemann
    def segwit_sighash(self,
                       index: int,
                       sighash_type: int,
                       prevout_value: bytes,
                       script: bytes,
                       anyone_can_pay: bool = False) -> bytes:
        '''
        Implements bip143 (witness) sighash. Prefer calling `sighash_all` or
        `sighash_single`.

        For documentation see here:
        https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki

        For an excellent pasta dinner, see here:
        https://ricette.giallozafferano.it/Spaghetti-alla-Norma.html
        '''
        data = ByteData()

        # 1. nVersion of the transaction (4-byte little endian)
        data += self.version

        # 2. hashPrevouts (32-byte hash)
        data += self._hash_prevouts(anyone_can_pay=anyone_can_pay)

        # 3. hashSequence (32-byte hash)
        data += self._hash_sequence(sighash_type=sighash_type,
                                    anyone_can_pay=anyone_can_pay)

        # 4. outpoint (32-byte hash + 4-byte little endian)
        data += self.tx_ins[index].outpoint

        # 5. scriptCode of the input (serialized as scripts inside CTxOuts)
        data += script

        # 6. value of the output spent by this input (8-byte little endian)
        data += prevout_value

        # 7. nSequence of the input (4-byte little endian)
        data += self.tx_ins[index].sequence

        # 8. hashOutputs (32-byte hash)
        data += self._hash_outputs(index=index, sighash_type=sighash_type)

        # 9. nLocktime of the transaction (4-byte little endian)
        data += self.lock_time

        # 10. sighash type of the signature (4-byte little endian)
        data += self._segwit_sighash_adjustment(sighash_type=sighash_type,
                                                anyone_can_pay=anyone_can_pay)

        return utils.hash256(data.to_bytes())
コード例 #13
0
def decode(s: str, checksum: bool = True) -> bytes:
    '''Convert base58 to binary using BASE58_ALPHABET.'''
    v, prefix = to_long(
        BASE58_BASE, lambda c: BASE58_LOOKUP[c], s.encode("utf8"))

    data = from_long(v, prefix, 256, lambda x: x)

    if checksum:
        data, the_hash = data[:-4], data[-4:]
        if utils.hash256(data)[:4] == the_hash:
            return data
        raise ValueError("hashed base58 has bad checksum %s" % s)

    return data
コード例 #14
0
ファイル: header_chain.py プロジェクト: thontron/bitcoin-spv
def do_work(prev_block_hash_be, merkle_root, nbits):
    nonce = 0
    b_header = make_header(bytes.fromhex(prev_block_hash_be),
                           bytes.fromhex(merkle_root), bytes.fromhex(nbits))

    target = parse_nbits(nbits)

    while True:
        print("Checking nonce {}".format(nonce), end='\r')  # noqa: E999
        b_header_nonced = b_header + rutils.i2le_padded(nonce, 4)
        b_header_digest = rutils.hash256(b_header_nonced)
        if rutils.be2i(b_header_digest[::-1]) < target:
            return b_header_nonced, b_header_digest
        nonce = nonce + 1
コード例 #15
0
ファイル: tx.py プロジェクト: prestwich/riemann
    def _sighash_forkid(
            self,
            index: int,
            script: bytes,
            prevout_value: bytes,
            sighash_type: int,
            anyone_can_pay: bool = False):
        '''
        Tx, int, byte-like, byte-like, int, bool -> bytes
        https://github.com/bitcoincashorg/spec/blob/master/replay-protected-sighash.md
        '''
        self.validate_bytes(prevout_value, 8)

        data = ByteData()

        # 1. nVersion of the transaction (4-byte little endian)
        data += self.version

        # 2. hashPrevouts (32-byte hash)
        data += self._hash_prevouts(anyone_can_pay=anyone_can_pay)

        # 3. hashSequence (32-byte hash)
        data += self._hash_sequence(sighash_type=sighash_type,
                                    anyone_can_pay=anyone_can_pay)

        # 4. outpoint (32-byte hash + 4-byte little endian)
        data += self.tx_ins[index].outpoint

        # 5. scriptCode of the input (serialized as scripts inside CTxOuts)
        data += script

        # 6. value of the output spent by this input (8-byte little endian)
        data += prevout_value

        # 7. nSequence of the input (4-byte little endian)
        data += self.tx_ins[index].sequence

        # 8. hashOutputs (32-byte hash)
        data += self._hash_outputs(index=index, sighash_type=sighash_type)

        # 9. nLocktime of the transaction (4-byte little endian)
        data += self.lock_time

        # 10. sighash type of the signature (4-byte little endian)
        data += self._forkid_sighash_adjustment(sighash_type=sighash_type,
                                                anyone_can_pay=anyone_can_pay)

        return utils.hash256(data.to_bytes())
コード例 #16
0
    def segwit_sighash(self,
                       index,
                       script,
                       prevout_value=None,
                       sighash_type=None,
                       anyone_can_pay=False):
        '''
        this function sets up sighash in BIP143 style
        https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki
        https://ricette.giallozafferano.it/Spaghetti-alla-Norma.html
        '''
        data = ByteData()

        # 1. nVersion of the transaction (4-byte little endian)
        data += self.version

        # 2. hashPrevouts (32-byte hash)
        data += self._hash_prevouts(anyone_can_pay=anyone_can_pay)

        # 3. hashSequence (32-byte hash)
        data += self._hash_sequence(sighash_type=sighash_type,
                                    anyone_can_pay=anyone_can_pay)

        # 4. outpoint (32-byte hash + 4-byte little endian)
        data += self.tx_ins[index].outpoint

        # 5. scriptCode of the input (serialized as scripts inside CTxOuts)
        data += self._adjusted_script_code(script=script)

        # 6. value of the output spent by this input (8-byte little endian)
        data += prevout_value

        # 7. nSequence of the input (4-byte little endian)
        data += self.tx_ins[index].sequence

        # 8. hashOutputs (32-byte hash)
        data += self._hash_outputs(index=index, sighash_type=sighash_type)

        # 9. nLocktime of the transaction (4-byte little endian)
        data += self.lock_time

        # 10. sighash type of the signature (4-byte little endian)
        data += self._segwit_sighash_adjustment(sighash_type=sighash_type,
                                                anyone_can_pay=anyone_can_pay)

        return utils.hash256(data.to_bytes())
コード例 #17
0
    def _hash_sequence(self, sighash_type, anyone_can_pay):
        '''BIP143 hashSequence implementation

        Args:
            sighash_type    (int): SIGHASH_SINGLE or SIGHASH_ALL
            anyone_can_pay (bool): true if ANYONECANPAY should be set
        Returns:
            (bytes): the hashSequence, a 32 byte hash
        '''
        if anyone_can_pay or sighash_type == shared.SIGHASH_SINGLE:
            # If any of ANYONECANPAY, SINGLE sighash type is set,
            # hashSequence is a uint256 of 0x0000......0000.
            return b'\x00' * 32
        else:
            # hashSequence is the double SHA256 of nSequence of all inputs;
            sequences = ByteData()
            for tx_in in self.tx_ins:
                sequences += tx_in.sequence
            return utils.hash256(sequences.to_bytes())
コード例 #18
0
ファイル: sapling.py プロジェクト: rrybarczyk/riemann
    def __init__(self, tx_ins, tx_outs, lock_time, expiry_height,
                 value_balance, tx_shielded_spends, tx_shielded_outputs,
                 tx_joinsplits, joinsplit_pubkey, joinsplit_sig, binding_sig):
        super().__init__()

        if 'sapling' not in riemann.get_current_network_name():
            raise ValueError(
                'SaplingTx not supported by network {}.'
                .format(riemann.get_current_network_name()))

        self.validate_bytes(lock_time, 4)
        self.validate_bytes(expiry_height, 4)
        self.validate_bytes(value_balance, 8)

        if utils.le2i(expiry_height) > 499999999:
            raise ValueError('Expiry time too high.'
                             'Expected <= 499999999. Got {}'
                             .format(utils.le2i(expiry_height)))

        if (len(tx_shielded_spends) + len(tx_shielded_outputs) == 0
                and value_balance != b'\x00' * 8):
            raise ValueError('If no shielded inputs or outputs, value balance '
                             'must be 8 0-bytes. Got {}'
                             .format(value_balance.hex()))
        elif binding_sig is not None:
            self.validate_bytes(binding_sig, 64)

        for tx_in in tx_ins:
            if not isinstance(tx_in, TxIn):
                raise ValueError(
                    'Invalid TxIn. '
                    'Expected instance of TxOut. Got {}'
                    .format(type(tx_in).__name__))

        for tx_out in tx_outs:
            if not isinstance(tx_out, TxOut):
                raise ValueError(
                    'Invalid TxOut. '
                    'Expected instance of TxOut. Got {}'
                    .format(type(tx_out).__name__))

        if len(tx_joinsplits) > 5:
            raise ValueError('Too many joinsplits. Stop that.')

        for shielded_spend in tx_shielded_spends:
            if not isinstance(shielded_spend, SaplingShieldedSpend):
                raise ValueError(
                    'Invalid shielded spend. '
                    'Expected instance of SaplingShieldedSpend. Got {}'
                    .format(type(shielded_spend).__name__))

        for shielded_output in tx_shielded_outputs:
            if not isinstance(shielded_output, SaplingShieldedOutput):
                raise ValueError(
                    'Invalid shielded output. '
                    'Expected instance of SaplingShieldedOutput. Got {}'
                    .format(type(shielded_output).__name__))

        for tx_joinsplit in tx_joinsplits:
            if not isinstance(tx_joinsplit, SaplingJoinsplit):
                raise ValueError(
                    'Invalid Joinsplit. '
                    'Expected instance of SaplingJoinsplit. Got {}'
                    .format(type(tx_joinsplit).__name__))

        if len(tx_joinsplits) != 0:
            self.validate_bytes(joinsplit_pubkey, 32)
            self.validate_bytes(joinsplit_sig, 64)

        if len(tx_joinsplits) + len(tx_ins) + len(tx_shielded_spends) == 0:
            raise ValueError('Transaction must have some input value.')

        self += b'\x04\x00\x00\x00'  # Sapling is always v4
        self += b'\x85\x20\x2f\x89'  # Sapling version group id
        self += shared.VarInt(len(tx_ins))
        for tx_in in tx_ins:
            self += tx_in
        self += shared.VarInt(len(tx_outs))
        for tx_out in tx_outs:
            self += tx_out
        self += lock_time
        self += expiry_height
        self += value_balance

        self += shared.VarInt(len(tx_shielded_spends))
        if len(tx_shielded_spends) != 0:
            for shielded_spend in tx_shielded_spends:
                self += shielded_spend

        self += shared.VarInt(len(tx_shielded_outputs))
        if len(tx_shielded_outputs) != 0:
            for shielded_output in tx_shielded_outputs:
                self += shielded_output

        self += shared.VarInt(len(tx_joinsplits))
        if len(tx_joinsplits) != 0:
            for tx_joinsplit in tx_joinsplits:
                self += tx_joinsplit
            self += joinsplit_pubkey
            self += joinsplit_sig

        if len(tx_shielded_outputs) + len(tx_shielded_spends) != 0:
            self += binding_sig
            self.binding_sig = binding_sig

        self.header = b'\x04\x00\x00\x80'  # Sapling is always v4
        self.group_id = b'\x85\x20\x2f\x89'  # Sapling version group id
        self.tx_ins = tuple(tx_in for tx_in in tx_ins)
        self.tx_outs = tuple(tx_out for tx_out in tx_outs)
        self.lock_time = lock_time
        self.expiry_height = expiry_height
        self.value_balance = value_balance

        if len(tx_shielded_spends) != 0:
            self.tx_shielded_spends = tuple(ss for ss in tx_shielded_spends)
        else:
            self.tx_shielded_spends = tuple()

        if len(tx_shielded_outputs) != 0:
            self.tx_shielded_outputs = tuple(so for so in tx_shielded_outputs)
        else:
            self.tx_shielded_outputs = tuple()

        if len(tx_joinsplits) != 0:
            self.tx_joinsplits = tuple(js for js in tx_joinsplits)
            self.joinsplit_pubkey = joinsplit_pubkey
            self.joinsplit_sig = joinsplit_sig
            # Zcash spec 5.4.1.4 Hsig hash function
            self.hsigs = (tuple(self._hsig(i)
                          for i in range(len(self.tx_joinsplits))))
            self.primary_inputs = (tuple(self._primary_input(i)
                                   for i in range(len(self.tx_joinsplits))))
        else:
            self.tx_joinsplits = tuple()
            self.joinsplit_pubkey = None
            self.joinsplit_sig = None
            self.hsigs = tuple()
            self.primary_inputs = tuple()

        if len(tx_shielded_outputs) + len(tx_shielded_spends) != 0:
            self.binding_sig = binding_sig
        else:
            self.binding_sig = None

        self.tx_id_le = self.tx_id_le = utils.hash256(self.to_bytes())
        self.tx_id = self.tx_id_le[::-1]

        self._make_immutable()

        if len(self) > 100000:
            raise ValueError(  # pragma: no cover
                'Tx is too large. '
                'Expect less than 100kB. Got: {} bytes'.format(len(self)))
コード例 #19
0
    def __init__(self, version, flag, tx_ins, tx_outs, tx_witnesses,
                 lock_time):

        super().__init__()

        self.validate_bytes(version, 4)
        self.validate_bytes(lock_time, 4)

        if flag is not None:
            if flag != riemann.network.SEGWIT_TX_FLAG:
                raise ValueError('Invald segwit flag. '
                                 'Expected None or {}. Got: {}'.format(
                                     riemann.network.SEGWIT_TX_FLAG, flag))

        if tx_witnesses is not None:
            if flag is None:
                raise ValueError('Got witnesses but no segwit flag.')
            if len(tx_witnesses) != len(tx_ins):
                raise ValueError('Witness and TxIn lists must be same length. '
                                 'Got {} inputs and {} witnesses.'.format(
                                     len(tx_ins), len(tx_witnesses)))
            for witness in tx_witnesses:
                if not isinstance(witness, InputWitness):
                    raise ValueError(
                        'Invalid InputWitness. '
                        'Expected instance of InputWitness. Got {}'.format(
                            type(witness)))

        if min(len(tx_ins), len(tx_outs)) == 0:
            raise ValueError('Too few inputs or outputs. Stop that.')

        for tx_in in tx_ins:
            if not isinstance(tx_in, TxIn):
                raise ValueError('Invalid TxIn. '
                                 'Expected instance of TxIn. Got {}'.format(
                                     type(tx_in).__name__))

        for tx_out in tx_outs:
            if not isinstance(tx_out, TxOut):
                raise ValueError('Invalid TxOut. '
                                 'Expected instance of TxOut. Got {}'.format(
                                     type(tx_out).__name__))

        self += version
        if flag is not None:
            self += flag
        self += VarInt(len(tx_ins))
        for tx_in in tx_ins:
            self += tx_in
        self += VarInt(len(tx_outs))
        for tx_out in tx_outs:
            self += tx_out
        if tx_witnesses is not None:
            for witness in tx_witnesses:
                self += witness
        self += lock_time

        self.version = version
        self.flag = flag
        self.tx_ins_len = len(tx_ins)
        self.tx_ins = tuple(tx_in for tx_in in tx_ins)
        self.tx_outs_len = len(tx_outs)
        self.tx_outs = tuple(tx_out for tx_out in tx_outs)
        self.tx_witnesses_len = self.tx_ins_len
        self.tx_witnesses = \
            tuple(wit for wit in tx_witnesses) if tx_witnesses is not None \
            else None
        self.lock_time = lock_time

        if flag is not None:
            self.tx_id_le = utils.hash256(self.no_witness())
            self.wtx_id_le = utils.hash256(self.to_bytes())
            self.tx_id = utils.change_endianness(self.tx_id_le)
            self.wtx_id = utils.change_endianness(self.wtx_id_le)

        else:
            self.tx_id_le = utils.hash256(self.to_bytes())
            self.tx_id = utils.change_endianness(self.tx_id_le)
            self.wtx_id = None
            self.wtx_le = None

        self._make_immutable()
コード例 #20
0
    def __init__(self, version, tx_ins, tx_outs, lock_time, tx_joinsplits,
                 joinsplit_pubkey, joinsplit_sig):

        super().__init__()

        if 'sprout' not in riemann.get_current_network_name():
            raise ValueError('SproutTx not supported by network {}.'.format(
                riemann.get_current_network_name()))

        self.validate_bytes(version, 4)
        self.validate_bytes(lock_time, 4)

        for tx_in in tx_ins:
            if not isinstance(tx_in, TxIn):
                raise ValueError('Invalid TxIn. '
                                 'Expected instance of TxOut. Got {}'.format(
                                     type(tx_in).__name__))

        for tx_out in tx_outs:
            if not isinstance(tx_out, TxOut):
                raise ValueError('Invalid TxOut. '
                                 'Expected instance of TxOut. Got {}'.format(
                                     type(tx_out).__name__))

        if utils.le2i(version) == 1:
            if tx_joinsplits is not None and len(tx_joinsplits) != 0:
                raise ValueError('Joinsplits not allowed in version 1 txns.')
            if tx_ins is None or len(tx_ins) == 0:
                raise ValueError('Version 1 txns must have at least 1 input.')

        if utils.le2i(version) == 2:
            if len(tx_joinsplits) > 5:
                raise ValueError('Too many joinsplits. Stop that.')
            for tx_joinsplit in tx_joinsplits:
                if not isinstance(tx_joinsplit, z.SproutJoinsplit):
                    raise ValueError(
                        'Invalid Joinsplit. '
                        'Expected instance of SproutJoinsplit. Got {}'.format(
                            type(tx_joinsplit).__name__))
            self.validate_bytes(joinsplit_pubkey, 32)
            if joinsplit_sig is not None and joinsplit_sig != b'':
                self.validate_bytes(joinsplit_sig, 64)

        if utils.le2i(version) not in [1, 2]:
            raise ValueError('Version must be 1 or 2. '
                             'Got: {}'.format(utils.le2i(version)))

        self += version
        self += shared.VarInt(len(tx_ins))
        for tx_in in tx_ins:
            self += tx_in
        self += shared.VarInt(len(tx_outs))
        for tx_out in tx_outs:
            self += tx_out
        self += lock_time

        if version == utils.i2le_padded(2, 4):
            self += shared.VarInt(len(tx_joinsplits))
            for tx_joinsplit in tx_joinsplits:
                self += tx_joinsplit
            self += joinsplit_pubkey
            self += joinsplit_sig

        self.version = version
        self.tx_ins = tuple(tx_in for tx_in in tx_ins)
        self.tx_outs = tuple(tx_out for tx_out in tx_outs)
        self.tx_joinsplits = tuple(js for js in tx_joinsplits)
        self.lock_time = lock_time

        if version == utils.i2le_padded(2, 4):
            self.joinsplit_pubkey = joinsplit_pubkey
            self.joinsplit_sig = joinsplit_sig
            # Zcash spec 5.4.1.4 Hsig hash function
            self.hsigs = (tuple(
                self._hsig(i) for i in range(len(self.tx_joinsplits))))
            self.primary_inputs = (tuple(
                self._primary_input(i)
                for i in range(len(self.tx_joinsplits))))
        else:
            self.joinsplit_pubkey = None
            self.joinsplit_sig = None
            self.hsigs = None
            self.primary_inputs = None

        self.tx_id_le = utils.hash256(self.to_bytes()).hex()
        self.tx_id = utils.hash256(self.to_bytes())[::-1].hex()

        self._make_immutable()

        if len(self) > 100000:
            raise ValueError(  # pragma: no cover
                'Tx is too large. '
                'Expect less than 100kB. Got: {} bytes'.format(len(self)))
コード例 #21
0
    def __init__(self, tx_ins, tx_outs, lock_time, expiry_height,
                 tx_joinsplits, joinsplit_pubkey, joinsplit_sig):
        super().__init__()

        if 'overwinter' not in riemann.get_current_network_name():
            raise ValueError(
                'OverwinterTx not supported by network {}.'
                .format(riemann.get_current_network_name()))

        self.validate_bytes(lock_time, 4)
        self.validate_bytes(expiry_height, 4)

        if utils.le2i(expiry_height) > 499999999:
            raise ValueError('Expiry time too high.'
                             'Expected <= 499999999. Got {}'
                             .format(utils.le2i(expiry_height)))

        for tx_in in tx_ins:
            if not isinstance(tx_in, TxIn):
                raise ValueError(
                    'Invalid TxIn. '
                    'Expected instance of TxIn. Got {}'
                    .format(type(tx_in).__name__))

        for tx_out in tx_outs:
            if not isinstance(tx_out, TxOut):
                raise ValueError(
                    'Invalid TxOut. '
                    'Expected instance of TxOut. Got {}'
                    .format(type(tx_out).__name__))

        if len(tx_joinsplits) > 5:
            raise ValueError('Too many joinsplits. Stop that.')

        for tx_joinsplit in tx_joinsplits:
            if not isinstance(tx_joinsplit, z.SproutJoinsplit):
                raise ValueError(
                    'Invalid Joinsplit. '
                    'Expected instance of SproutJoinsplit. Got {}'
                    .format(type(tx_joinsplit).__name__))
        if len(tx_joinsplits) != 0:
            self.validate_bytes(joinsplit_pubkey, 32)
            self.validate_bytes(joinsplit_sig, 64)

        if len(tx_joinsplits) == 0 and len(tx_ins) == 0:
            raise ValueError('Transaction must have tx_ins or joinsplits.')

        self += b'\x03\x00\x00\x80'  # Version 3 + fOverwintered
        self += b'\x70\x82\xc4\x03'  # Overwinter Group ID
        self += shared.VarInt(len(tx_ins))
        for tx_in in tx_ins:
            self += tx_in
        self += shared.VarInt(len(tx_outs))
        for tx_out in tx_outs:
            self += tx_out
        self += lock_time
        self += expiry_height

        self += shared.VarInt(len(tx_joinsplits))
        if len(tx_joinsplits) != 0:
            for tx_joinsplit in tx_joinsplits:
                self += tx_joinsplit
            self += joinsplit_pubkey
            self += joinsplit_sig

        self.header = b'\x03\x00\x00\x80'
        self.group_id = b'\x70\x82\xc4\x03'
        self.version = b'\x03\x00'
        self.tx_ins = tuple(tx_in for tx_in in tx_ins)
        self.tx_outs = tuple(tx_out for tx_out in tx_outs)
        self.lock_time = lock_time
        self.expiry_height = expiry_height

        if len(tx_joinsplits) != 0:
            self.tx_joinsplits = tuple(js for js in tx_joinsplits)
            self.joinsplit_pubkey = joinsplit_pubkey
            self.joinsplit_sig = joinsplit_sig
            # Zcash spec 5.4.1.4 Hsig hash function
            self.hsigs = (tuple(self._hsig(i)
                          for i in range(len(self.tx_joinsplits))))
            self.primary_inputs = (tuple(self._primary_input(i)
                                   for i in range(len(self.tx_joinsplits))))
        else:
            self.tx_joinsplits = tuple()
            self.joinsplit_pubkey = None
            self.joinsplit_sig = None
            self.hsigs = tuple()
            self.primary_inputs = tuple()

        self.tx_id_le = self.tx_id_le = utils.hash256(self.to_bytes())
        self.tx_id = self.tx_id_le[::-1]

        self._make_immutable()

        if len(self) > 100000:
            raise ValueError(  # pragma: no cover
                'Tx is too large. '
                'Expect less than 100kB. Got: {} bytes'.format(len(self)))