Пример #1
0
    def test_everything(self):
        version = utils.i2le_padded(1, 4)
        outpoint_index = utils.i2le_padded(0, 4)
        outpoint_tx_id = bytearray(
            bytearray.fromhex('10399b3f20cbdd4b5ac3f823afdba28b'
                              '9f70e21437a59b312a1b62c42c5cd101'))[::-1]
        outpoint = tx.Outpoint(outpoint_tx_id, outpoint_index)

        sequence = utils.i2le_padded(0, 4)

        script = bytearray(
            bytearray.fromhex(
                '473044022000e02ea97289a35181a9bfabd324f12439410db11c4e94978cdade6a665bf1840220458b87c34d8bb5e4d70d01041c7c2d714ea8bfaca2c2d2b1f9e5749c3ee17e3d012102ed0851f0b4c4458f80e0310e57d20e12a84642b8e097fe82be229edbd7dbd53920f6665740b1f950eb58d646b1fae9be28cef842da5e51dc78459ad2b092e7fd6e514c5163a914bb408296de2420403aa79eb61426bb588a08691f8876a91431b31321831520e346b069feebe6e9cf3dd7239c670400925e5ab17576a9140d22433293fe9652ea00d21c5061697aef5ddb296888ac'
            ))  # noqa: E501

        tx_in = tx.TxIn(outpoint, script, bytearray(), sequence)
        tx_ins = [tx_in]

        tx_outs = [
            tx.TxOut(
                value=bytearray(utils.i2le_padded(2000, 8)),
                output_script=bytearray(
                    bytearray.fromhex(
                        '76a914f2539f42058da784a9d54615ad074436cf3eb85188ac')
                ))  # noqa: E501
        ]

        lock_time = utils.i2le_padded(0, 4)

        res = tx.Tx(version, None, tx_ins, tx_outs, None, lock_time)

        self.assertEqual(res, helpers.RAW_P2SH_TO_P2PKH)
Пример #2
0
    def test_txhash(self):
        '''
        https://github.com/decred/dcrd/blob/master/wire/msgtx_test.go#L139-L140
        '''
        outpoint = tx.DecredOutpoint(tx_id=b'\x00' * 32,
                                     index=b'\xff' * 4,
                                     tree=b'\x00')
        tx_ins = [tx.DecredTxIn(outpoint=outpoint, sequence=b'\xff' * 4)]
        tx_outs = [
            tx.DecredTxOut(value=utils.i2le_padded(5000000000, 8),
                           version=b'\xf0\xf0',
                           output_script=helpers.DCR['ser']['hash_pk'])
        ]
        tx_witnesses = [
            tx.DecredInputWitness(
                value=utils.i2le_padded(5000000000, 8),
                height=b'\x34' * 4,
                index=b'\x2E' * 4,
                stack_script=bytes([0x04, 0x31, 0xdc, 0x00, 0x1b, 0x01, 0x62]),
                redeem_script=b'')
        ]
        version = helpers.DCR['ser']['version']
        t = tx.DecredTx(version=version,
                        tx_ins=tx_ins,
                        tx_outs=tx_outs,
                        lock_time=b'\x00' * 4,
                        expiry=b'\x00' * 4,
                        tx_witnesses=tx_witnesses)

        self.assertEqual(t.tx_id, helpers.DCR['ser']['tx']['expected_hash'])
Пример #3
0
def make_tx(version, tx_ins, tx_outs, lock_time,
            expiry=None, value_balance=None, tx_shielded_spends=None,
            tx_shielded_outputs=None, tx_witnesses=None, tx_joinsplits=None,
            joinsplit_pubkey=None, joinsplit_sig=None, binding_sig=None):
    '''
    int, list(TxIn), list(TxOut), int, list(InputWitness) -> Tx
    '''
    n = riemann.get_current_network_name()
    if 'decred' in n:
        return tx.DecredTx(
            version=utils.i2le_padded(version, 4),
            tx_ins=tx_ins,
            tx_outs=tx_outs,
            lock_time=utils.i2le_padded(lock_time, 4),
            expiry=utils.i2le_padded(expiry, 4),
            tx_witnesses=[tx_witnesses])
    if 'sprout' in n and tx_joinsplits is not None:
        return tx.SproutTx(
            version=version,
            tx_ins=tx_ins,
            tx_outs=tx_outs,
            lock_time=utils.i2le_padded(lock_time, 4),
            tx_joinsplits=tx_joinsplits if tx_joinsplits is not None else [],
            joinsplit_pubkey=joinsplit_pubkey,
            joinsplit_sig=joinsplit_sig)
    if 'overwinter' in n:
        return tx.OverwinterTx(
            tx_ins=tx_ins,
            tx_outs=tx_outs,
            lock_time=utils.i2le_padded(lock_time, 4),
            expiry_height=utils.i2le_padded(expiry, 4),
            tx_joinsplits=tx_joinsplits if tx_joinsplits is not None else [],
            joinsplit_pubkey=joinsplit_pubkey,
            joinsplit_sig=joinsplit_sig)
    if 'sapling' in n:
        return tx.SaplingTx(
            tx_ins=tx_ins,
            tx_outs=tx_outs,
            lock_time=utils.i2le_padded(lock_time, 4),
            expiry_height=utils.i2le_padded(expiry, 4),
            value_balance=utils.i2le_padded[value_balance],
            tx_shielded_spends=(tx_shielded_spends
                                if tx_shielded_spends is not None else []),
            tx_shielded_outputs=(tx_shielded_outputs
                                 if tx_shielded_outputs is not None else []),
            tx_joinsplits=tx_joinsplits if tx_joinsplits is not None else [],
            joinsplit_pubkey=joinsplit_pubkey,
            joinsplit_sig=joinsplit_sig,
            binding_sig=binding_sig)
    flag = riemann.network.SEGWIT_TX_FLAG \
        if tx_witnesses is not None else None
    return tx.Tx(version=utils.i2le_padded(version, 4),
                 flag=flag,
                 tx_ins=tx_ins,
                 tx_outs=tx_outs,
                 tx_witnesses=tx_witnesses,
                 lock_time=utils.i2le_padded(lock_time, 4))
Пример #4
0
def make_outpoint(tx_id_le, index, tree=None):
    '''
    byte-like, int, int -> Outpoint
    '''
    if 'decred' in riemann.get_current_network_name():
        return tx.DecredOutpoint(tx_id=tx_id_le,
                                 index=utils.i2le_padded(index, 4),
                                 tree=utils.i2le_padded(tree, 1))
    return tx.Outpoint(tx_id=tx_id_le,
                       index=utils.i2le_padded(index, 4))
Пример #5
0
def make_legacy_input(outpoint, stack_script, redeem_script, sequence):
    '''
    Outpoint, byte-like, byte-like, int -> TxIn
    '''
    if 'decred' in riemann.get_current_network_name():
        return tx.DecredTxIn(
            outpoint=outpoint,
            sequence=utils.i2le_padded(sequence, 4))
    return tx.TxIn(outpoint=outpoint,
                   stack_script=stack_script,
                   redeem_script=redeem_script,
                   sequence=utils.i2le_padded(sequence, 4))
Пример #6
0
def make_wpkh_witness(
    t: tx.Tx,
    input_index: int,
    prevout_value: int,
    privkey: bytes
) -> tx.InputWitness:
    '''
    Make a witness for a transaction spending a native-Segwith WPKH output.

    Args:
        t: A transaction. You can use the output of `spend_utxo_to_address`
        input_index: Which input should this function sign?
        prevout_value: What is the size of the UTXO being spent?
        privkey: The 32-byte private key to sign with

    Return:
        A SegWit witness signing `t`
    '''
    pubkey = crypto.priv_to_pub(privkey)

    sighash = t.sighash_all(
        index=input_index,
        script=b'\x16\x00\x14' + rutils.hash160(pubkey),
        prevout_value=rutils.i2le_padded(prevout_value, 8))

    signature = crypto.sign_digest(sighash, privkey)

    return tx_builder.make_witness([signature, pubkey])
Пример #7
0
def partial(tx_id: str, index: int, prevout_value: int, recipient_addr: str,
            output_value: int, lock_time: int, keypair: KeyPair) -> Tx:
    '''
    Makes a partial_tx from human readable information

    Args:
        tx_id                (str): txid of parent tx
        index                (int): index of input in parent tx
        prevout_value        (int): value in satoshi of the input
        recipient_addr       (str): address of the recipient
        output_value         (int): value in satoshi of the output
        lock_time            (int): desired lock_time in bitcoin format
        keypair  (tuple(str, str)): privkey as hex, pubkey as hex
    Returns:
        (riemann.tx.Tx): The signed transaction
    '''
    outpoint = simple.outpoint(tx_id, index)
    pub = bytes.fromhex(keypair[1])
    pkh = rutils.hash160(pub)
    output_script = b'\x19\x76\xa9\x14' + pkh + b'\x88\xac'  # Assume PKH

    unsigned = make_partial_tx(outpoint=outpoint,
                               output_value=output_value,
                               output_address=recipient_addr,
                               lock_time=lock_time)

    signed = sign_partial_tx(partial_tx=unsigned,
                             keypair=keypair,
                             prevout_script=output_script,
                             prevout_value=rutils.i2le_padded(
                                 prevout_value, 8))
    return signed
Пример #8
0
def create_dummy_transaction(prev_tx_id=None, prev_out_index=None):
    """
    Creates a 1-1 transaction that is structurally correct, but spends from probably not valid outputs.

    If ``prev_tx_id`` is passed, the previous transaction id is set to the received value, otherwise it it randomly
    generated. In a similar way, if ``prev_out_index`` is passed, the previous index is set to it, otherwise it it
    set to ``0``.

    Args:
        prev_tx_id (:obj:`str`): the previous transaction id from where the new transaction will spend. If ``None``,
            a random one is generated.
        prev_out_index (:obj:`int`): the previous output index from where the new transaction will spend. If ``None``,
            ``0`` is set.

    Returns:
        :obj:`Tx <riemann.tx.tx.Tx>`: a ``Tx`` object representing the new generated transaction.
    """

    if prev_tx_id is None or len(prev_tx_id) != 64:
        prev_tx_id = utils.get_random_value_hex(32)

    idx = prev_out_index if prev_out_index is not None else 0
    prev_out_index_bytes = rutils.i2le_padded(idx, 4).hex()

    dummy_hex = f"0100000001{prev_tx_id}{prev_out_index_bytes}4847304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901ffffffff0100f2052a01000000434104ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84cac00000000"

    return tx.Tx.from_hex(dummy_hex)
Пример #9
0
def make_sh_output(value, output_script, witness=False):
    '''
    int, str -> TxOut
    '''
    return _make_output(
        value=utils.i2le_padded(value, 8),
        output_script=make_sh_output_script(output_script, witness))
Пример #10
0
def make_pkh_output(value, pubkey, witness=False):
    '''
    int, bytearray -> TxOut
    '''
    return _make_output(
        value=utils.i2le_padded(value, 8),
        output_script=make_pkh_output_script(pubkey, witness))
Пример #11
0
    def createFundingTx(self, funder_amount, funder_pubkey, fundee_pubkey, change_address=None):
        if not self.input_utxo_specified:
            sys.exit("Did not specify source of funds.")
        msig_addr, funding_redeem_script = createMultiSigAddress(funder_pubkey, fundee_pubkey, verbose=self.verbose)
        # create tx input
        tx_ins = [tb.make_legacy_input(outpoint=self.outpoint, stack_script=b"", redeem_script=self.scriptsig,
                                       sequence=0xFFFFFFFF)]
        if self.verbose: print("Input: ", tx_ins)
        tx_outs = [simple.output(address=msig_addr, value=funder_amount)]
        if self.verbose: print("Output: ", tx_outs)

        need_change_output = True if self.utxo_amount > funder_amount else False
        if need_change_output:
            change_output_amount = self.utxo_amount - funder_amount - self.network_fee
            tx_outs += [simple.output(address=self.change_address, value=change_output_amount)]

        if BITCOIN in self.network:
            unsigned_tx = simple.unsigned_legacy_tx(tx_ins, tx_outs)
        elif ZCASH in self.network:
            unsigned_tx = simple.unsigned_legacy_tx(tx_ins, tx_outs)

        script_code1 = b'\x19' + addresses.to_output_script(msig_addr)

        # TODO: computing sighash_all => verify that this is done correctly
        sighash = unsigned_tx.sighash_all(index=0, script=script_code1,
                                          prevout_value=utils.i2le_padded(funder_amount, 8))
        # NOTE: for dual-funded channel, funder_bal = funder_amount + fundee_amount
        funding_tx = {'funding_tx_id': unsigned_tx.tx_id.hex(), 'funding_bal': funder_amount,
                      'funding_address': str(msig_addr), 'funding_witness_script': funding_redeem_script}

        return funding_tx, unsigned_tx.hex()
Пример #12
0
def signed_refund_htlc_transaction(secret_hash: bytes,
                                   redeemer_pkh: bytes,
                                   timeout: int,
                                   funder_pkh: bytes,
                                   tx_id: str,
                                   index: int,
                                   prevout_value: int,
                                   address: str,
                                   privkey: bytes,
                                   fee: int = 0) -> tx.Tx:
    '''
    Builds an entire Refund HTLC spend from scratch.
    '''
    # build the unsigned version of the transaction
    t = spend_htlc_transaction(tx_id, index, prevout_value - fee, address,
                               timeout)

    # Prep the witness program
    s = build_htlc_script(secret_hash, redeemer_pkh, timeout, funder_pkh)
    serialized_script = script.serialize(s)
    script_len = len(serialized_script)
    prepended_script = tx.VarInt(script_len).to_bytes() + serialized_script

    # calculate sighash using the witness program
    sighash = t.sighash_all(index=index,
                            script=prepended_script,
                            prevout_value=rutils.i2le_padded(prevout_value, 8))

    # sign it and make the witness
    signature = crypto.sign_digest(sighash, privkey)
    witness = htlc_refund_witness(s, signature, crypto.priv_to_pub(privkey))

    # insert the witness into the tx
    return t.copy(tx_witnesses=[witness])
Пример #13
0
def check_for_known_outpoints(outpoint_list: List[Outpoint]) -> List[Outpoint]:
    '''
    Finds all prevouts we know of from a list of outpoints
    Useful for checking whether the DB already knows about specific prevouts
    '''
    # NB: We want to flatten the outpoint to look it up in the DB
    flattened_list: List[str] = []
    for o in outpoint_list:
        flat_outpoint = '{tx_id}{index}'.format(
            tx_id=utils.reverse_hex(o['tx_id']),
            index=rutils.i2le_padded(o['index'], 4).hex())
        flattened_list.append(flat_outpoint)

    c = connection.get_cursor()
    try:
        question_marks = ', '.join(['?' for _ in range(len(outpoint_list))])
        cursor = c.execute(
            '''
            SELECT tx_id, idx FROM prevouts
            WHERE outpoint IN ({question_marks})
            '''.format(question_marks=question_marks), flattened_list)
        res = [Outpoint(tx_id=p['tx_id'], index=p['idx']) for p in cursor]
        return res
    finally:
        c.close()
Пример #14
0
def make_op_return_output(data: bytes) -> tx.TxOut:
    '''
    Generates OP_RETURN output for data of up to 77 bytes. OP_RETURN outputs
    are data carriers with no impact on the UTXO set. They are comonly used to
    create on-chain commitments to some off-chain information. There are few
    consensus constraints on their content or structure, however they become
    non-standard above 77 bytes.

    Args:
        data    (bytes):    data to be included in output
    Returns:
        (TxOut):            TxOut object with OP_RETURN output
    '''
    if len(data) > 77:  # 77 bytes is the limit
        raise ValueError('Data is too long. Expected <= 77 bytes')

    pk_script = bytearray()
    pk_script.extend(b'\x6a')  # OP_RETURN

    # OP_PUSHDATA1 only used if data is greater than 75 bytes
    if len(data) in [76, 77]:
        pk_script.extend(b'\x4c')  # OP_PUSHDATA1

    pk_script.extend([len(data)])  # One byte for length of data
    pk_script.extend(data)  # Data
    return _make_output(utils.i2le_padded(0, 8), pk_script)
Пример #15
0
 def _segwit_sighash_adjustment(
         self,
         sighash_type: int,
         anyone_can_pay: bool) -> bytes:
     # sighash type altered to include ANYONECANPAY
     if anyone_can_pay:
         sighash_type = sighash_type | shared.SIGHASH_ANYONECANPAY
     return utils.i2le_padded(sighash_type, 4)
Пример #16
0
def make_witness_input(outpoint, sequence):  # noqa: F811
    '''
    Make a Segwit input. This is clearly superior to `make_legacy_input` and
    you should use witness always.

    Args:
        outpoint: The Outpoint object
        sequence: The 4-byte LE-encoded sequence number
    Returns:
        A Segwit TxIn object.
    '''
    if 'decred' in riemann.get_current_network_name():
        return decred.DecredTxIn(outpoint=outpoint,
                                 sequence=utils.i2le_padded(sequence, 4))
    return tx.TxIn(outpoint=outpoint,
                   stack_script=b'',
                   redeem_script=b'',
                   sequence=utils.i2le_padded(sequence, 4))
Пример #17
0
def make_outpoint(tx_id_le, index, tree=None):  # noqa: F811
    '''
    Instantiate an Outpoint object from a transaction id and an index.

    Args:
        tx_id_le: The 32-byte LE hash of the transaction that created the
                  prevout being referenced.
        index: The index of the TxOut that created the prevout in its
               transaction's output vector
        tree: Only in Decred transactions. Specifies the commitment tree.
    Returns:
        An Outpoint object. If network is set to Decred, a DecredOutpoint
    '''
    if 'decred' in riemann.get_current_network_name():
        tree_bytes = b'\x00' if tree is None else utils.i2le_padded(tree, 1)
        return decred.DecredOutpoint(tx_id=tx_id_le,
                                     index=utils.i2le_padded(index, 4),
                                     tree=tree_bytes)
    return tx.Outpoint(tx_id=tx_id_le, index=utils.i2le_padded(index, 4))
Пример #18
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())
Пример #19
0
def _flatten_prevout(prevout: Prevout) -> PrevoutEntry:
    outpoint = '{tx_id}{index}'.format(
        tx_id=utils.reverse_hex(prevout['outpoint']['tx_id']),
        index=rutils.i2le_padded(prevout['outpoint']['index'], 4).hex())
    return {
        'outpoint': outpoint,
        'tx_id': prevout['outpoint']['tx_id'],
        'idx': prevout['outpoint']['index'],
        'value': prevout['value'],
        'spent_at': prevout['spent_at'],
        'spent_by': prevout['spent_by'],
        'address': prevout['address']
    }