Пример #1
0
    def test_parse_hash(self):
        self.assertEqual(addr.parse_hash(helpers.OP_IF['p2sh']),
                         helpers.OP_IF['script_hash'])
        self.assertEqual(addr.parse_hash(helpers.MSIG_2_2['p2sh']),
                         helpers.MSIG_2_2['script_hash'])
        self.assertEqual(
            addr.parse_hash(
                helpers.P2WSH['human']['ins'][0]['addr']),
            helpers.P2WSH['ser']['ins'][0]['pk_script'][2:])
        self.assertEqual(addr.parse_hash(helpers.P2WPKH_ADDR['address']),
                         helpers.P2WPKH_ADDR['pkh'])
        self.assertEqual(addr.parse_hash(helpers.ADDR[0]['p2pkh']),
                         helpers.PK['ser'][0]['pkh'])

        with self.assertRaises(ValueError) as context:
            addr.parse('bc1blahblahblah')

        self.assertIn('Unsupported address format. Got: ',
                      str(context.exception))

        # Test cash addr code
        riemann.select_network('bitcoin_cash_main')
        self.assertEqual(
            addr.parse_hash(helpers.OP_IF['p2sh']),
            helpers.OP_IF['script_hash'])

        self.assertEqual(
            addr.parse_hash(helpers.OP_IF['cashaddr']),
            helpers.OP_IF['script_hash'])

        self.assertEqual(
            addr.parse_hash(helpers.CASHADDR['p2pkh']),
            utils.hash160(helpers.CASHADDR['pubkey']))
Пример #2
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])
Пример #3
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
Пример #4
0
def make_pkh_output_script(pubkey: bytes, witness: bool = False) -> bytes:
    '''
    Makes a P2PKH or P2WPKH script pubkey from a raw public key. Does not
    support Compatibility p2wpkh-via-p2sh output scripts.

    Args:
        pubkey: The 33- or 65-byte public key.
        witness: Pass True to make a P2WSH script pubkey.
    Returns:
        The script pubkey containing the hash of the pubkey.
    '''
    if witness and not riemann.network.SEGWIT:
        raise ValueError('Network {} does not support witness scripts.'.format(
            riemann.get_current_network_name()))

    output_script = bytearray()

    if type(pubkey) is not bytearray and type(pubkey) is not bytes:
        raise ValueError('Unknown pubkey format. '
                         'Expected bytes. Got: {}'.format(type(pubkey)))

    pubkey_hash = utils.hash160(pubkey)

    if witness:
        output_script.extend(riemann.network.P2WPKH_PREFIX)
        output_script.extend(pubkey_hash)
    else:
        output_script.extend(b'\x76\xa9\x14')  # OP_DUP OP_HASH160 PUSH14
        output_script.extend(pubkey_hash)
        output_script.extend(b'\x88\xac')  # OP_EQUALVERIFY OP_CHECKSIG
    return bytes(output_script)
Пример #5
0
def make_pkh_output_script(pubkey, witness=False):
    '''
    bytearray -> bytearray
    '''
    if witness and not riemann.network.SEGWIT:
        raise ValueError(
            'Network {} does not support witness scripts.'
            .format(riemann.get_current_network_name()))

    output_script = bytearray()

    if type(pubkey) is not bytearray and type(pubkey) is not bytes:
        raise ValueError('Unknown pubkey format. '
                         'Expected bytes. Got: {}'.format(type(pubkey)))

    pubkey_hash = utils.hash160(pubkey)

    if witness:
        output_script.extend(riemann.network.P2WPKH_PREFIX)
        output_script.extend(pubkey_hash)
    else:
        output_script.extend(b'\x76\xa9\x14')  # OP_DUP OP_HASH160 PUSH14
        output_script.extend(pubkey_hash)
        output_script.extend(b'\x88\xac')  # OP_EQUALVERIFY OP_CHECKSIG
    return output_script
Пример #6
0
    def test_parse_hash(self):
        self.assertEqual(addr.parse_hash(helpers.OP_IF_P2SH),
                         helpers.OP_IF_SCRIPT_HASH)
        self.assertEqual(addr.parse_hash(helpers.MSIG_TWO_TWO_P2SH),
                         helpers.MSIG_TWO_TWO_SCRIPT_HASH)
        self.assertEqual(addr.parse_hash(helpers.P2WSH_ADDRESS),
                         helpers.P2WSH_SCRIPT_HASH)
        self.assertEqual(addr.parse_hash(helpers.P2WPKH_ADDRESS),
                         helpers.P2WPKH_PKH)
        self.assertEqual(addr.parse_hash(helpers.P2PKH_0), helpers.PKH_0)

        with self.assertRaises(ValueError) as context:
            addr.parse('bc1blahblahblah')

        self.assertIn('Unsupported address format. Got: ',
                      str(context.exception))

        # Test cash addr code
        riemann.select_network('bitcoin_cash_main')
        self.assertEqual(addr.parse_hash(helpers.OP_IF_P2SH),
                         helpers.OP_IF_SCRIPT_HASH)

        self.assertEqual(addr.parse_hash(helpers.OP_IF_CASHADDR),
                         helpers.OP_IF_SCRIPT_HASH)

        self.assertEqual(addr.parse_hash(helpers.CASHADDR_P2PKH_ADDRESS),
                         utils.hash160(helpers.CASHADDR_PUBKEY))
Пример #7
0
def make_pkh_address(pubkey: bytes,
                     witness: bool = False,
                     cashaddr: bool = True) -> str:
    '''Turns a pubkey into an address'''
    pubkey_hash = utils.hash160(pubkey)
    return _make_pkh_address(pubkey_hash=pubkey_hash,
                             witness=witness,
                             cashaddr=cashaddr)
Пример #8
0
def _ser_script_to_sh_address(script_bytes: bytes,
                              witness: bool = False,
                              cashaddr: bool = True) -> str:
    '''makes a p2sh address from a serialized script'''
    if witness:
        script_hash = utils.sha256(script_bytes)
    else:
        script_hash = utils.hash160(script_bytes)
    return _hash_to_sh_address(script_hash=script_hash,
                               witness=witness,
                               cashaddr=cashaddr)
Пример #9
0
def make_sh_script_pubkey(script_bytes: bytes, witness: bool = False) -> bytes:
    output_script = bytearray()
    if witness:
        script_hash = utils.sha256(script_bytes)
        output_script.extend(riemann.network.P2WSH_PREFIX)
        output_script.extend(script_hash)
    else:
        script_hash = utils.hash160(script_bytes)
        output_script.extend(b'\xa9\x14')  # OP_HASH160 PUSH0x14
        output_script.extend(script_hash)
        output_script.extend(b'\x87')  # OP_EQUAL

    return bytes(output_script)
Пример #10
0
def make_and_sign_split_tx(tx_id: str, index: int, prevout_value: int,
                           control_addr: str, control_addr_keypair: Tuple[str,
                                                                          str],
                           num_auctions: int, change_addr: str) -> tx.Tx:
    '''
    Makes and signs a transaction with several small outputs
    Args:
        tx_id: the input prevout's txid
        index: the input prevout's index
        prevout_value: the input prevout's value
        control_addr: the input prevout's controlling address
        control_addr_keypair: the priv/pub keypair as a tuple of hex
        num_auctions: how many outputs to make
        change_addr: where to send leftover funds
    '''
    # Split in 10, send SUMMA change
    split_tx = us.generate_small_utxos(tx_id=tx_id,
                                       index=index,
                                       prevout_value=prevout_value,
                                       recipient_addr=control_addr,
                                       num_outputs=num_auctions,
                                       change_addr=change_addr,
                                       fee=8000,
                                       size=550)

    pubkeyhash = rutils.hash160(bytes.fromhex(control_addr_keypair[1]))
    prevout_script = b'\x19\x76\xa9\x14' + pubkeyhash + b'\x88\xac'

    sighash_bytes = split_tx.sighash_single(index=0,
                                            script=prevout_script,
                                            prevout_value=rutils.i2le_padded(
                                                prevout_value, 8),
                                            anyone_can_pay=True)
    sig = utils.sign_hash(sighash_bytes, control_addr_keypair[0])
    sig = '{}{}'.format(sig, '83')

    # Build the witness
    wit = tx.make_witness(
        [bytes.fromhex(sig),
         bytes.fromhex(control_addr_keypair[1])])
    tx_witnesses = [wit]

    split_tx = split_tx.copy(tx_witnesses=tx_witnesses)

    return split_tx
Пример #11
0
def _make_child_xpub(derivation: str,
                     parent_or_none: Optional[LedgerPubkey],
                     child: LedgerPubkey,
                     mainnet: bool = True) -> str:
    '''
    Builds an xpub for a derived child using its parent and path
    Args:
        derivation      (str): the m-prefixed derivation path e.g. m/44h/0h/0h
        parent (LedgerPubkey): the parent public key
        child  (LedgerPubkey): the child public key
        mainnet        (bool): whether to use mainnet prefixes
    '''
    indices = utils.parse_derivation(derivation)

    # determine appropriate xpub version bytes
    if not mainnet:
        prefix = utils.VERSION_BYTES['testnet']['public']
    else:
        prefix = utils.VERSION_BYTES['mainnet']['public']

    if parent_or_none is not None:
        # xpubs include the parent fingerprint
        parent = cast(LedgerPubkey, parent_or_none)
        compressed_parent_key = utils.compress_pubkey(parent['pubkey'])
        parent_fingerprint = rutils.hash160(compressed_parent_key)[:4]
        child_index = indices[-1].to_bytes(4, byteorder='big')
        depth = len(indices)
    else:
        # this means it's a master key
        parent_fingerprint = b'\x00' * 4
        child_index = b'\x00' * 4
        depth = 0

    # xpubs always use compressed pubkeys
    compressed_pubkey = utils.compress_pubkey(child['pubkey'])

    # build the xpub
    xpub = bytearray()
    xpub.extend(prefix)  # xpub prefix
    xpub.extend([depth])  # depth
    xpub.extend(parent_fingerprint)  # paren't fingerprint
    xpub.extend(child_index)  # index
    xpub.extend(child['chain_code'])  # chain_code
    xpub.extend(compressed_pubkey)  # pubkey (comp)
    return base58.encode(xpub)
Пример #12
0
def make_pkh_address(pubkey: bytes,
                     witness: bool = False,
                     cashaddr: bool = True) -> str:
    '''
    Turns a pubkey into an address. Prefers Cashaddrs to legacy addresses
    whenever supported.

    Args:
        pubkey:       The 33 or 65 byte public key
        witness:      Pass True to generate a witness address if supported.
                      Default False.
        cashaddr:     Pass False to prefer legacy to cashaddr. Default True
    Returns:
        The encoded address
    '''
    pubkey_hash = utils.hash160(pubkey)
    return _make_pkh_address(pubkey_hash=pubkey_hash,
                             witness=witness,
                             cashaddr=cashaddr)
Пример #13
0
def validate_address(address: AddressEntry) -> bool:
    '''
    Validates the address data structure
    '''
    try:
        h = addr.parse_hash(address['address'])
        if address['script'] == b'':
            return True

        if address['script_pubkeys'] != pubkeys_from_script(address['script']):
            return False

        if h in [
                rutils.sha256(address['script']),  # p2wsh
                rutils.hash160(address['script'])
        ]:  # p2sh
            return True
    except (ValueError, TypeError, KeyError):
        pass

    return False
Пример #14
0
def undo_split(tx_id: str, num_auctions: int, change_addr: str,
               control_addr_keypair: Tuple[str, str]) -> tx.Tx:
    '''
    undoes a split tx. NOT FOR SHUTTING DOWN AUCTIONS
    Args:
        tx_id: the tx_id of the split tx
        num_auctions: the number of non-change outputs of the split tx
        change_addr: the address to send leftovers to
        control_addr_keypair: the keypair of the controlling address
    '''
    tx_ins = [
        simple.unsigned_input(simple.outpoint(tx_id, i))
        for i in range(num_auctions)
    ]
    tx_outs = [simple.output(600, change_addr)]
    unsplit_tx = simple.unsigned_witness_tx(tx_ins, tx_outs)

    pubkeyhash = rutils.hash160(bytes.fromhex(control_addr_keypair[1]))
    prevout_script = b'\x19\x76\xa9\x14' + pubkeyhash + b'\x88\xac'

    tx_witnesses = []
    for i in range(num_auctions):
        sighash_bytes = unsplit_tx.sighash_all(
            index=i,
            script=prevout_script,
            prevout_value=rutils.i2le_padded(550, 8),
            anyone_can_pay=False)

        sig = utils.sign_hash(sighash_bytes, control_addr_keypair[0])
        sig = '{}{}'.format(sig, '01')

        # Build the witness
        wit = tx.make_witness(
            [bytes.fromhex(sig),
             bytes.fromhex(control_addr_keypair[1])])
        tx_witnesses.append(wit)

    return cast(tx.Tx, unsplit_tx.copy(tx_witnesses=tx_witnesses))
Пример #15
0
def _ser_script_to_sh_address(script_bytes: bytes,
                              witness: bool = False,
                              cashaddr: bool = True) -> str:
    '''
    Turns a serialized script into a SH address. Prefers Cashaddrs to legacy
    addresses whenever supported.

    Args:
        script_bytes: The serialized script, as a bytestring
        witness:      Pass True to generate a witness address if supported.
                      Default False.
        cashaddr:     Pass False to prefer legacy to cashaddr. Default True

    Returns:
        The encoded address
    '''
    if witness:
        script_hash = utils.sha256(script_bytes)
    else:
        script_hash = utils.hash160(script_bytes)
    return _hash_to_sh_address(script_hash=script_hash,
                               witness=witness,
                               cashaddr=cashaddr)
Пример #16
0
def make_sh_script_pubkey(script_bytes: bytes, witness: bool = False) -> bytes:
    '''
    Make a P2SH or P2WSH script pubkey from a serialized script. Does not
    support Compatibility p2wsh-via-p2sh output scripts.

    Args:
        script_bytes: The serialized redeem script or witness script.
        witness: Pass True to make a P2WSH script pubkey.
    Returns:
        The script pubkey containing the hash of the serialized script.
    '''
    output_script = bytearray()
    if witness:
        script_hash = utils.sha256(script_bytes)
        output_script.extend(riemann.network.P2WSH_PREFIX)
        output_script.extend(script_hash)
    else:
        script_hash = utils.hash160(script_bytes)
        output_script.extend(b'\xa9\x14')  # OP_HASH160 PUSH0x14
        output_script.extend(script_hash)
        output_script.extend(b'\x87')  # OP_EQUAL

    return bytes(output_script)
Пример #17
0
def _signable(key: bytes, prevout_info: PrevoutInfo) -> bool:
    '''
    Determines if the key or its hash is in the PrevoutInfo
    We use this to determine whether we should get a signature for an input

    Args:
        key                (bytes): the public key
        prevout_info (PrevoutInfo): dict of script and value for the prevout
    Returns:
        (bool): True if signable, false otherwise
    '''
    if len(key) in [64, 65]:
        key = utils.compress_pubkey(key)  # enforce compression

    # if there's no script, it's not signable
    if prevout_info['witness_script'] is None:
        return False

    # if the key is anywhere in the script, it is signable
    script = cast(bytes, prevout_info['witness_script'])
    if (key in script or rutils.hash160(key) in script):
        return True

    return False
Пример #18
0
def compute_pk_hash(pubkey_hex):
    return utils.hash160(bytes.fromhex(pubkey_hex)).hex()
Пример #19
0
def make_btc_shutdown_txns(auction_tx_id: str,
                           idxs: List[int],
                           add_funds_tx_id: str,
                           add_funds_idx: int,
                           add_funds_value: int,
                           control_addr: str,
                           control_addr_keypair: Tuple[str, str],
                           change_addr: str,
                           eth_addr: str,
                           fee: int = 7700) -> List[str]:
    '''
    Shuts down an auction by winning them with the owner keypair
    Args:
        tx_id: the split tx for the auction set
        idxs: the unpurchased indexes
        add_funds_tx_id: a prevout tx id to fund these transactions
        add_funds_idx: the prevout index
        add_funds_value: the prevout value
        control_addr: the input prevout's controlling address
        control_addr_keypair: the priv/pub keypair as a tuple of hex
        change_addr: where to send leftover funds
        eth_addr: where to deliver auction proceeds
        fee: the tx fee to pay
    '''
    prev = (add_funds_tx_id, add_funds_idx)
    val = add_funds_value
    shutdown_txns = []

    pubkeyhash = rutils.hash160(bytes.fromhex(control_addr_keypair[1]))
    prevout_script = b'\x19\x76\xa9\x14' + pubkeyhash + b'\x88\xac'

    for i in range(len(idxs)):
        tx_ins = [
            simple.unsigned_input(simple.outpoint(auction_tx_id, idxs[i])),
            simple.unsigned_input(simple.outpoint(*prev))
        ]

        out_val = val + 550 - fee
        addr = control_addr if i < len(idxs) - 1 else change_addr
        tx_outs = [
            simple.output(out_val, addr),
            tx.make_op_return_output(bytes.fromhex(eth_addr[2:]))
        ]

        shutdown_tx = simple.unsigned_witness_tx(tx_ins, tx_outs)

        tx_witnesses = []

        sighash_bytes = shutdown_tx.sighash_all(
            index=0,
            script=prevout_script,
            prevout_value=rutils.i2le_padded(550, 8),
            anyone_can_pay=False)
        sig = utils.sign_hash(sighash_bytes, control_addr_keypair[0])
        sig = '{}{}'.format(sig, '01')

        # Build the witness
        wit = tx.make_witness(
            [bytes.fromhex(sig),
             bytes.fromhex(control_addr_keypair[1])])
        tx_witnesses.append(wit)

        sighash_bytes_2 = shutdown_tx.sighash_all(
            index=1,
            script=prevout_script,
            prevout_value=rutils.i2le_padded(val, 8),
            anyone_can_pay=False)
        sig_2 = utils.sign_hash(sighash_bytes_2, control_addr_keypair[0])
        sig_2 = '{}{}'.format(sig_2, '01')

        # Build the witness
        wit_2 = tx.make_witness(
            [bytes.fromhex(sig_2),
             bytes.fromhex(control_addr_keypair[1])])
        tx_witnesses.append(wit_2)

        prev = (shutdown_tx.tx_id.hex(), 0)
        val = out_val
        shutdown_txns.append(shutdown_tx.copy(tx_witnesses=tx_witnesses).hex())

    return shutdown_txns
Пример #20
0
secret_hash = utils.sha256(bytes.fromhex(secret)).hex()

# Use real pubkeys!
fake_pk_execute = '02' * 32
fake_pk_refund = '03' * 32

# Use a real sig!
fake_sig = '04' * 32

# Use a real timelock!
timeout = 'deadbeef'

# string formatting to fill parameters
filled_in_redeem_script = htlc_redeem_script.format(
    secret_hash=secret_hash,
    pkh0=utils.hash160(bytes.fromhex(fake_pk_execute)).hex(),
    timeout=timeout,
    pkh1=utils.hash160(bytes.fromhex(fake_pk_refund)).hex())

# DON'T SEND MONEY TO THIS EXAMPLE ADDRESS!!!
# t 3fKPy737rsshnQJ7iRoXw3XujCB7tjuiUt
htlc_address = addr.make_sh_address(filled_in_redeem_script)

# how to send money there
output = simple.output(500000, htlc_address)

# --- HOW TO SPEND ---
# fill in the sig/pubkey/secret
filled_in_execute_script = htlc_stack_script_execute.format(
    sig=fake_sig,
    pk=fake_pk_execute,