示例#1
0
    def tx_decb(self, block_id, vk_p):
        txs_hashes = self.get_block_txs(
            block_id)  # Get the hash of transactions inside this block
        for tx_hash in txs_hashes:
            raw_tx = self.proxy.getrawtransaction(
                tx_hash)  # get the raw transaction from the hash of the tx
            decoded_tx = self.proxy.decoderawtransaction(
                raw_tx)  # decode the raw transaction and get the json format

            # check to see if the tx has 1 input and two outputs and is of type pay2pubkeyhash
            if len(decoded_tx['vin']) != 1 or len(decoded_tx['vout']) != 2:
                continue
            if decoded_tx['vout'][0]['scriptPubKey'][
                    'hex'][:6] != '76a914' or decoded_tx['vout'][0][
                        'scriptPubKey']['hex'][-4:] != '88ac':  # pay2pubkeyhash
                continue
            if decoded_tx['vout'][1]['scriptPubKey'][
                    'hex'][:4] != 'a914' or decoded_tx['vout'][1][
                        'scriptPubKey']['hex'][-2:] != '87':  # pay2scripthash
                continue

            try:
                vk_p_compressed = decoded_tx['vin'][0]['scriptSig']['hex'][
                    -66:]
                ct_r1 = decoded_tx['vout'][0]['scriptPubKey']['hex'][6:-4]
                ct_r2 = decoded_tx['vout'][1]['scriptPubKey']['hex'][4:-2]
                if vk_p_compressed == PublicKey('04' +
                                                vk_p).to_hex(compressed=True):
                    print("Found the transaction with response message")
                    return ct_r1 + ct_r2
            except:
                continue

        return None
示例#2
0
    def tx_decf(self, tx_hash):
        raw_tx = self.proxy.getrawtransaction(
            tx_hash)  # get the raw transaction from the hash of the tx
        decoded_tx = self.proxy.decoderawtransaction(
            raw_tx)  # decode the raw transaction and get the json format

        # check to see if the tx has 1 input and two outputs and is of type pay2pubkeyhash and pay2scripthash
        if len(decoded_tx['vin']) != 1 or len(decoded_tx['vout']) != 2:
            return -1, -1
        if decoded_tx['vout'][0]['scriptPubKey'][
                'hex'][:6] != '76a914' or decoded_tx['vout'][0][
                    'scriptPubKey']['hex'][-4:] != '88ac':  #pay2pubkeyhash
            return -1, -1
        if decoded_tx['vout'][1]['scriptPubKey'][
                'hex'][:4] != 'a914' or decoded_tx['vout'][1]['scriptPubKey'][
                    'hex'][-2:] != '87':  #pay2scripthash
            return -1, -1

        try:
            vk_u_compressed = decoded_tx['vin'][0]['scriptSig']['hex'][-66:]
            vk_u = PublicKey(vk_u_compressed).to_hex(compressed=False)[2:]
            ct_c = decoded_tx['vout'][1]['scriptPubKey']['hex'][4:-2]
            return vk_u, ct_c
        except:
            return -1, -1
示例#3
0
def create_HODL_address(key, lock, is_priv=False):
    setup(os.getenv("BUY_LAMBO_BTC_NET", "regtest"))

    # Get public key (given or found from private key)
    public_key = PrivateKey(key).get_public_key() if is_priv else PublicKey(key)

    # Get address from public key
    address_from_key = public_key.get_address()

    # Set lock sequence prefix
    seq = Sequence(TYPE_ABSOLUTE_TIMELOCK, lock)

    # create the redeem script - needed to sign the transaction
    redeem_script = Script(
        [
            seq.for_script(),
            "OP_CHECKLOCKTIMEVERIFY",
            "OP_DROP",
            "OP_DUP",
            "OP_HASH160",
            address_from_key.to_hash160(),
            "OP_EQUALVERIFY",
            "OP_CHECKSIG",
        ]
    )

    # create a P2SH address from a redeem script
    addr = P2shAddress.from_script(redeem_script)
    print("Time-locked address: {}".format(addr.to_string()))
示例#4
0
    def _tx_encf(self, vk_p, ct_c, sk_u, txin_id, txin_index):
        # create transaction input from tx id of UTXO
        txin = TxInput(txin_id, txin_index)

        # having the vk_p from the shared key generate the corresponding address for decoder to use to respond
        vk_p = PublicKey(vk_p)
        addr_p = vk_p.get_address().to_string()

        # create transaction output using P2PKH scriptPubKey for paying address
        paying_addr = P2pkhAddress(addr_p)
        paying_txout = TxOutput(0.00002, paying_addr.to_script_pub_key())

        # create an output where the address is the ciphertext
        cipher_txout = TxOutput(0.00001,
                                Script(['OP_HASH160', ct_c, 'OP_EQUAL']))

        # create transaction from inputs/outputs -- default locktime is used
        tx = Transaction([txin], [paying_txout, cipher_txout])
        #print("\nRaw unsigned transaction:\n" + tx.serialize())

        # use private key corresponding to the address that contains the UTXO we are trying to spend to sign the input
        vk_u = sk_u.get_public_key()
        addr_u = vk_u.get_address().to_string()

        # note that we pass the scriptPubkey as one of the inputs of sign_input because it is used to replace
        # the scriptSig of the UTXO we are trying to spend when creating the transaction digest
        from_addr = P2pkhAddress(addr_u)
        sig = sk_u.sign_input(
            tx, 0,
            from_addr.to_script_pub_key())  # 0 is for the index of the input

        # set the scriptSig (unlocking script)
        vk_u = vk_u.to_hex()
        txin.script_sig = Script([sig, vk_u])
        signed_tx = tx.serialize()

        print("Users input address: ", addr_u)
        print("Decoder paying address: ", addr_p)
        print("\nRaw signed transaction:\n" + signed_tx)

        return signed_tx
 def tx_decf(self, tx_hash):
     decoded_tx = self.get_tx(tx_hash)
     #--------------------get the public key of the user------------------------------
     if len(decoded_tx['vin']) != 1 or len(
             decoded_tx['vShieldedOutput']) != 2:
         return -1, -1
     try:
         vk_u_compressed = decoded_tx['vin'][0]['scriptSig']['hex'][-66:]
         vk_u = PublicKey(vk_u_compressed).to_hex(compressed=False)[2:]
     except:
         return -1, -1
     #--------------------get the ciphertext------------------------------------------
     cmd = os.popen(zcash_cli + " " + conf_file +
                    ' z_listreceivedbyaddress ' +
                    public_address_decoder_shielded)
     tx_json = json.loads(cmd.read())[-1]
     ct_c = tx_json['memo'][:self.challenge_len * 2]
     self.tx_addr_dict[tx_hash] = bytes.fromhex(
         tx_json['memo'][self.challenge_len * 2:self.challenge_len * 2 +
                         self.address_len]).decode()
     return vk_u, ct_c
def main():
    # always remember to setup the network
    setup('regtest')

    #
    # This script creates a P2SH address containing a CHECKLOCKTIMEVERIFY plus a P2PKH locking funds with a key as 
    # well as for an absolute amount of blocks or an absolute amount of seconds since the transaction. 
    #

    parser = argparse.ArgumentParser(
        description='Give the public key, a future time expressed either in block height or in UNIX Epoch time and '
                    'the P2SH address will be displayed') 
    parser.add_argument('pubkey', help="Add the public key.")
    parser.add_argument('-param', type=int, help="Add the number of blocks or the time expressed in seconds.")
    args = parser.parse_args()

    # set values
    key = args.pubkey
    absolute_param = args.param

    p2pkh_pk = PublicKey(key)

    # set Locktime
    seq = Sequence(TYPE_ABSOLUTE_TIMELOCK, absolute_param)
    locktime = Locktime(absolute_param)

    # get the address (from the public key)
    p2pkh_addr = p2pkh_pk.get_address()

    # print("Public key: " + p2pkh_pk.to_hex(compressed=True))
    # print("P2PKH Address: " + p2pkh_addr.to_string())

    # create the redeem script
    redeem_script = Script(
        [seq.for_script(), 'OP_CHECKLOCKTIMEVERIFY', 'OP_DROP', 'OP_DUP', 'OP_HASH160', p2pkh_addr.to_hash160(),
         'OP_EQUALVERIFY', 'OP_CHECKSIG'])

    # create a P2SH address from a redeem script
    addr = P2shAddress.from_script(redeem_script)
    print("The P2SH address is : " + addr.to_string())
示例#7
0
def create_p2sh(proxy, block_height=10, address_pubk=None):
    """
    Creates a P2SH address with an absolute block locktime.

        :param proxy: JSON RPC proxy for connecting to the network.
        :param block_height: Block height the lock is valid for. Default value is 10.
        :param address_pubk: Public key of the address locking the funds. If None, a new address will be created.
    """

    # if a public key is not specified, create a new address and display its keys for future use
    if not address_pubk:
        print('Public key not provided. Created a new address.')
        address = proxy.getnewaddress()
        print('Address:', address)
        address_privk = proxy.dumpprivkey(address)
        print('Private key:', address_privk)
        address_pubk = proxy.getaddressinfo(address)['pubkey']
        print('Public key:', address_pubk)
    # create the public key object
    p2pkh_pk = PublicKey(address_pubk)

    # create sequence for the redeem script
    seq = Sequence(TYPE_ABSOLUTE_TIMELOCK, block_height)
    # create the redeem script
    redeem_script = Script([
        seq.for_script(), 'OP_CHECKLOCKTIMEVERIFY', 'OP_DROP', 'OP_DUP',
        'OP_HASH160',
        p2pkh_pk.to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG'
    ])

    # create the P2SH address from the redeem script
    p2sh_addr = P2shAddress.from_script(redeem_script)
    # insert the P2SH address into the wallet
    proxy.importaddress(p2sh_addr.to_string())

    # display the P2SH address
    print('Created P2SH address:', p2sh_addr.to_string())
 def test_pubkey_to_hash160(self):
     pub = PublicKey(self.public_key_hex)
     self.assertEqual(pub.get_address().to_hash160(), pub.to_hash160())
 def test_get_uncompressed_address(self):
     pub = PublicKey(self.public_key_hex)
     self.assertEqual(
         pub.get_address(compressed=False).to_string(), self.address)
示例#10
0
 def test_pubkey_uncompressed(self):
     pub = PublicKey(self.public_key_hex)
     self.assertEqual(pub.to_hex(compressed=False), self.public_key_hex)
示例#11
0
 def test_pubkey_creation(self):
     pub1 = PublicKey(self.public_key_hex)
     self.assertEqual(pub1.to_bytes(), self.public_key_bytes)
     pub2 = PublicKey(self.public_key_hexc)
     self.assertEqual(pub2.to_bytes(), self.public_key_bytes)
def _fill_pdf_metadata(out_file,
                       issuer,
                       issuer_address,
                       column_fields,
                       data,
                       global_columns,
                       verify_issuer,
                       conf,
                       interactive=False):

    # create version
    version = 2

    # create issuer object (json)
    issuer = {
        "name": issuer,
        "identity": {
            "address": issuer_address,
            "verification": json.loads(verify_issuer)['methods']
        }
    }

    # create metadata object (json) and add metadata
    metadata = {}

    # add custom metadata
    if column_fields:
        metadata_fields = json.loads(column_fields)['columns']
        for f in metadata_fields:
            key = list(f)[0]
            if key in data:
                field_properties = f[key]
                field_properties['value'] = data[key]
                metadata[key] = field_properties

    # add global field metadata
    if global_columns:
        global_fields = json.loads(global_columns)['fields']
        for g in global_fields:
            key = list(g)[0]
            # note that global fields override column data
            metadata[key] = g[key]

    # now look at special owner name/pubkey columns explicitly in code
    # TODO we should probably check if the public key is valid
    owner = None
    owner_address = None
    owner_pk = None
    if '__OWNER_PK__' in data and data[
            '__OWNER_PK__'] and '__OWNER_ADDRESS__' in data and data[
                '__OWNER_ADDRESS__']:
        # TODO maybe just calculate address from public key?
        owner_address = data['__OWNER_ADDRESS__']
        owner_pk = data['__OWNER_PK__']

        owner = {
            "name": data['__OWNER_NAME__'],
            "owner_address":
            data['__OWNER_ADDRESS__'],  # TODO needed? - can be derived
            "pk": owner_pk
        }

        # add the metadata
        pdf_metadata = PdfDict(version=version,
                               issuer=json.dumps(issuer),
                               metadata=json.dumps(metadata),
                               owner=json.dumps(owner),
                               owner_proof='',
                               chainpoint_proof='')
    else:
        # add the metadata (without dumps(owner) to keep owner empty)
        pdf_metadata = PdfDict(version=version,
                               issuer=json.dumps(issuer),
                               metadata=json.dumps(metadata),
                               owner='',
                               owner_proof='',
                               chainpoint_proof='')

    pdf = PdfReader(out_file)
    if pdf.Info:
        pdf.Info.update(pdf_metadata)
    else:
        pdf.Info = pdf_metadata
    PdfWriter().write(out_file, pdf)

    # if owner exists then need to add owner_proof
    # hash pdf, sign hash message using node and add in owner_proof
    if owner:
        ##import time
        ##start = time.time()
        sha256_hash = None
        with open(out_file, 'rb') as pdf:
            sha256_hash = hashlib.sha256(pdf.read()).hexdigest()
        if (conf.testnet):
            setup('testnet')
        else:
            setup('mainnet')

        host, port = conf.full_node_url.split(
            ':')  #TODO: update when NodeProxy accepts full url!
        proxy = NodeProxy(conf.full_node_rpc_user, conf.full_node_rpc_password,
                          host, port).get_proxy()

        # Due to an old unresolved issue still pending in Bitcoin v0.20.0
        # signmessage does not support signing with bech32 key.
        # To resolve we use the public key to get the base58check encoding that
        # signmessage is happy with so that we can sign!
        if (owner_address.startswith('bc') or owner_address.startswith('tb')):
            owner_address = PublicKey(owner_pk).get_address().to_string()

        # NOTE that address (the encoding) might have changed here from bech32
        # to legacy... take care if you use it again in this function!

        sig = proxy.signmessage(owner_address, sha256_hash)

        # add owner_proof to metadata
        pdf_metadata = PdfDict(owner_proof=sig)
        pdf = PdfReader(out_file)
        pdf.Info.update(pdf_metadata)
        PdfWriter().write(out_file, pdf)
        ##end = time.time()
        ##print(end-start, " seconds")
        ##exit()

    if interactive:
        # print progress
        print('.', end="", flush=True)
示例#13
0
def spend_p2sh_cltv_p2pkh(proxy, block_height, sender_priv_key, p2sh_addr,
                          rec_addr):
    """
    Spends funds from a P2SH address with an absolute locktime to a P2PKH receiver address.
    :param proxy: JSON RPC proxy for connecting to the network.
    :param block_height: Block height the lock is valid for.
    :param sender_priv_key: Private key of the address locking the funds.
    :param p2sh_addr: P2SH address containing the funds.
    :param rec_addr: P2PKH address receiving the funds.
    """

    # mine 100 blocks and send bitcoin to the P2SH address
    proxy.generatetoaddress(100, p2sh_addr)
    # mine 100 blocks to make mined bitcoin spendable, emulates 'bitcoin-cli -generate 100'
    for _ in range(100):
        proxy.generatetoaddress(1, proxy.getnewaddress())

    # retrieve unspent UTXOs for the P2SH address
    p2sh_addr_unspent = proxy.listunspent(0, 99999999, [p2sh_addr])

    # create absolute-block locking sequence for the transaction inputs
    seq = Sequence(TYPE_ABSOLUTE_TIMELOCK, block_height)

    # create transaction inputs for unspent UTXOs
    # and calculate the total unspent bitcoins they contain
    tx_inputs = []
    total_unspent = 0
    for utxo in p2sh_addr_unspent:
        tx_inputs.append(
            TxInput(utxo['txid'],
                    utxo['vout'],
                    sequence=seq.for_input_sequence()))
        total_unspent += utxo['amount']
    print("Unspent bitcoin in address {} : {}".format(p2sh_addr,
                                                      total_unspent))

    # get the public key of the receiving address for the funds to be sent to
    rec_pub_key = proxy.getaddressinfo(rec_addr)['pubkey']
    rec_pk = PublicKey(rec_pub_key)

    # calculate fee
    satoshis_per_kb = requests \
        .get('https://api.blockcypher.com/v1/btc/test3') \
        .json()['medium_fee_per_kb']
    # formula: |inputs| * 180 + 34 * |outputs| +- |inputs|
    tx_size = len(tx_inputs) * 180 + 34 * 1 + 10 + len(tx_inputs)
    # we calculate fees in terms of bitcoin
    fee = (tx_size / 1024) * (satoshis_per_kb / 10e8)

    # create the transaction output
    tx_output = TxOutput(to_satoshis(Decimal(total_unspent) - Decimal(fee)),
                         rec_pk.get_address().to_script_pub_key())
    # set a lock time in blocks for the transaction
    lock = Locktime(block_height)
    # create the transaction
    tx = Transaction(tx_inputs, [tx_output], lock.for_transaction())
    unsigned_tx = tx.serialize()
    print('Raw unsigned transaction:', unsigned_tx)

    # we need to rebuild the redeem script from the P2SH private key
    # make the locking P2PKH address private key
    sender_sk = PrivateKey(sender_priv_key)
    # retrieve the public key of the locking address
    sender_pk = sender_sk.get_public_key()
    # rebuild the redeem script
    redeem_script = Script([
        seq.for_script(), 'OP_CHECKLOCKTIMEVERIFY', 'OP_DROP', 'OP_DUP',
        'OP_HASH160',
        sender_pk.get_address().to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG'
    ])

    # for every input of the transaction
    for i, txin in enumerate(tx.inputs):
        # create the signature for redeeming the funds
        sig = sender_sk.sign_input(tx, i, redeem_script)
        # and sign the input
        txin.script_sig = Script(
            [sig, sender_pk.to_hex(),
             redeem_script.to_hex()])

    signed_tx = tx.serialize()
    print('Raw signed transaction:', signed_tx)
    print('Transaction ID:', tx.get_txid())

    # verify that the transaction is valid
    ver = proxy.testmempoolaccept([signed_tx])
    if ver[0]['allowed']:
        # if the transaction is valid send the transaction to the blockchain
        print('Transaction is valid.')
        proxy.sendrawtransaction(signed_tx)
        print('{} Bitcoin sent to address {}'.format(
            Decimal(total_unspent) - Decimal(fee), rec_addr))
    else:
        # otherwise, display the reason the transaction failed
        print('Transaction rejected. Reason:', ver[0]['reject-reason'])