2

I have this function that converts a Bitcoin private key as an integer to a public key and an address.

def get_seg_v1_from_pkey(imported_key):
    imported_key_toint = int(imported_key)
    privKeytoHex = imported_key_toint.to_bytes(32, 'big').hex()
    prv = HDKey(privKeytoHex)
    prv_tnet = TNetHDKey(privKeytoHex)
    pubkey = prv.public_hex
    pub_tnet = prv_tnet.public_hex
    version = 0x01
    address = program_to_witness(version, pubkey[2:], main=True)
    address_testnet = pubkeyhash_to_addr_bech32(pubkeyhash=pub_tnet[2:], prefix='tb', witver=1, separator='1', checksum_xor=0x2bc830a3)
    return pubkey, address, address_testnet  

HDKey imports the integer into a proper private key object like what is used in https://github.com/bitcoinops/taproot-workshop. TNetHDKey is a custom function I wrote that does the same thing as HDKey but it stores the private key in a way that makes it easily convertible to a testnet address.

I want to get the scriptPubKey from an address like in this function in https://github.com/bitcoinops/taproot-workshop:

def create_spending_transaction(self, txid, version=1, nSequence=0):
    """Construct a CTransaction object that spends the first ouput from txid."""
    # Construct transaction
    spending_tx = CTransaction()

    # Populate the transaction version
    spending_tx.nVersion = version

    # Populate the locktime
    spending_tx.nLockTime = 0

    # Populate the transaction inputs
    outpoint = COutPoint(int(txid, 16), 0)
    spending_tx_in = CTxIn(outpoint=outpoint, nSequence=nSequence)
    spending_tx.vin = [spending_tx_in]

    # Generate new Bitcoin Core wallet address
    dest_addr = self.nodes[0].getnewaddress(address_type="bech32")
    scriptpubkey = bytes.fromhex(self.nodes[0].getaddressinfo(dest_addr)['scriptPubKey'])

    # Complete output which returns 0.5 BTC to Bitcoin Core wallet
    amount_sat = int(0.5 * 100_000_000)
    dest_output = CTxOut(nValue=amount_sat, scriptPubKey=scriptpubkey)
    spending_tx.vout = [dest_output]

    return spending_tx  

Notice these lines in the above function:

# Generate new Bitcoin Core wallet address
dest_addr = self.nodes[0].getnewaddress(address_type="bech32")
scriptpubkey = bytes.fromhex(self.nodes[0].getaddressinfo(dest_addr)['scriptPubKey'])  

self.nodes[0] refers to a running instance of bitcoind on your computer. I want to replicate this function without requiring a running instance of bitcoind. In my version of this function I plan on passing in dest_addr because I won't have a bitcoind instance to generate it. Is there a way to get a scriptPubKey from a raw segwit v1 address?

2 Answers 2

2

You can use the reference Python implementation of bech32 / bech32m. Decode the address using bech32_decode and get the human readable part, data encoded (the scriptPubKey you are looking for), and whether this address is bech32 or bech32m.

1

The scriptpubkey for a P2WPKH address is 0x0014{20-byte-key-hash} (from bip141)

You get the keyhash by decoding the address from the bech32 encoding.

You can use this library (I am the author) to do that or to construct the spending output.

>>> from cryptotools import Address

>>> addr = Address('bc1qh2egksgfejqpktc3kkdtuqqrukrpzzp9lr0phn')
>>> addr.type()
<ADDRESS.P2WPKH: 'P2WPKH'>

>>> output = addr._receive(50_000_000)
>>> output.script.hex()
'0014bab28b4109cc801b2f11b59abe0003e586110825'
3
  • Thanks for the answer, my address is a segwit_v1 (bech32m). Will cryptotools work with that? And would the answer need to be modified in that case? May 3, 2023 at 22:58
  • 1
    Oops sorry I missed that, no taproot support yet.
    – Mike D
    May 3, 2023 at 23:02
  • No problem, thanks for trying May 3, 2023 at 23:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.