The Ultimate Guide on Python-Bitcoinlib

We’re all familiar with the powerful network of Bitcoin and the way it utilizes transactions. Each of these transactions has a different hash that can be used to verify these transactions. Even though there are multiple ways of using blockchain development and smart contracts (by using solidarity), if you’re trying to make a system on bitcoin data structure and protocol, then python-bitcoinlib is the best way to use it.

python-bitcoinlib is a python library created by Peter Todd to support the bitcoin data structure and use the workflow in the same way as bitcoin. This module has different classes to handle the data structures and validation processes. In this post, we’ll look at some examples in this library and try to understand them.

How to Install python-bitcoinlib?

If you’re working on Linux, then open up your terminal and enter the following commands to install python-bitcoinlib –

sudo apt-get install libssl-dev
pip install python-bitcoinlib

To install the latest version from GitHub –

sudo apt-get install libssl-dev
pip install git+https://github.com/petertodd/python-bitcoinlib

Make sure that you install libssl-dev. Otherwise, your SSL and TLS protocols won’t work correctly as intended.

Operating Chain

Currently, the module operates on the ‘mainnet’ chain of bitcoin. This chain is used by most of the applications built on the network. But if you want to change the chain, you can do it by using the following command –

import bitcoin
bitcoin.SelectParams('testnet')

‘mainnet’, ‘testnet’, and ‘regtest’ are the available chains from which you can select.

Examples of python-bitcoinlib

1. Create a SSL RPC Connection

Code:

import bitcoin.rpc

proxy = bitcoin.rpc.Proxy()
print(proxy.getnewaddress())

Output:

$.$.$.$

Explanation:

We first start by importing the bitcoin RPC support. This way, we can handle the proxy connections and SSL over them. python-bitcoinlib handles this easily by using a global proxy setup. By calling bitcoin.rpc.Proxy() we can set a proxy over module usage. Make sure that you have the .conf file setup on /root/.bitcoin/bitcoin.conf.

If not, then you’ll not be able to use it. Also, make sure that you have set the RPC password correctly.

2. Verify Base58 Hash

Code:

from bitcoin.wallet import CBitcoinSecret
from bitcoin.base58 import Base58ChecksumError

key = "5J3mBbAH58CpQ3Y5RNJpUKPE62SQ5tfcvU2JpbnkeyhfsYB1Jcn"
key2 = "5J3mBbAH58CpQ3Y5RNJpUKPE62SQ5tfcvU2JpbnkeyhfsYB1Jcnada"
try:
    secret = CBitcoinSecret(key)
    print(secret)
    secret2 = CBitcoinSecret(key2)
except Base58ChecksumError:
    print("Invalid Base 58 Key")

Output:

5J3mBbAH58CpQ3Y5RNJpUKPE62SQ5tfcvU2JpbnkeyhfsYB1Jcn
Invalid Base 58 Key

Explanation:

We start by importing the main class to hold the key, i.e., CBitcoinSecret. Also, import the Base58ChecksumError exception from python-bitcoinlib so that we can handle the conditions properly.

In the above example, “key” is a correct Base 58 key whereas, “key2” is an incorrect Base 58 key. We’ll use the try-except block to handle the Invalid Base 58 condition. As we can see in the output, key1 is correctly parsed, whereas while parsing the key2, we get the desired exception output.

3. Sign A Message Using Python-Bitcoinlib

Sign A Message Using Python-Bitcoinlib

Code:

from bitcoin.wallet import CBitcoinSecret, P2PKHBitcoinAddress
from bitcoin.signmessage import BitcoinMessage, VerifyMessage, SignMessage

key = "5J3mBbAH58CpQ3Y5RNJpUKPE62SQ5tfcvU2JpbnkeyhfsYB1Jcn"
msg = "message to sign"

secret = CBitcoinSecret(key)
message = BitcoinMessage(msg)
signature = SignMessage(secret, message)

address = P2PKHBitcoinAddress.from_pubkey(secret.pub)
message = BitcoinMessage(msg)
verify = VerifyMessage(address, message, signature)
print('Address: %s' % address)
print('Message: %s' % msg)
print('Signature: %s' % signature)
print('Verified: %s' % verify)
print("\n")
print('Verify using bitcoin core this command:')
print('\n`bitcoin-cli verifymessage %s \'%s\' \'%s\'`\n' % (address, signature.decode('ascii'), msg))

Output:

Address: 1424C2F4bC9JidNjjTUZCbUxv6Sa1Mt62x
Message: message to sign
Signature: b'HPNSvmhhD+h/myKkU+2yCuPNzGwio8A+n0rUKYxU3m6FSDyOPWTttlN7ATpr/5O5ibraZsB9J/qX7oxXkFpgtpw='
Verified: True


Verify using bitcoin core this command:

`bitcoin-cli verifymessage 1424C2F4bC9JidNjjTUZCbUxv6Sa1Mt62x 'HPNSvmhhD+h/myKkU+2yCuPNzGwio8A+n0rUKYxU3m6FSDyOPWTttlN7ATpr/5O5ibraZsB9J/qX7oxXkFpgtpw=' 'message to sign'`

Explanation:

We start by creating a secret of the key by using CBitcoinSecret. Next, the message has to be created as an object of BitcoinMessage. Then, every message has to be signed with the help of the secret. This can be done by using the SignMessage() object. Now the basic signing of the message is completed.

Furthermore, we verify the information by printing it in the desired format and using the VerifyMessage().

4. Generate Signature Hash For a Transaction

Code:

<pre class="wp-block-syntaxhighlighter-code">import hashlib

import bitcoin 
from bitcoin.core import Hash160
from bitcoin.core.script import CScript, OP_DUP, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG, SignatureHash, SIGHASH_ALL
from bitcoin.wallet import CBitcoinSecret

bitcoin.SelectParams('mainnet')

h = hashlib.sha256(b'wallet secret key').digest()
seckey = CBitcoinSecret.from_secret_bytes(h)

# Creating Script Pub Key
txin_scriptPubKey = CScript([OP_DUP, OP_HASH160, Hash160(seckey.pub), OP_EQUALVERIFY, OP_CHECKSIG])

# Create the unsigned transaction.
tx = CMutableTransaction([txin], [txout])

# Calculate the signature <a href="https://www.pythonpool.com/python-oshash-module/" target="_blank" rel="noopener">hash</a> for that transaction
sighash = SignatureHash(txin_scriptPubKey, tx, 0, SIGHASH_ALL)
print(sighash)</pre>

Output:

b'\x9eD\xb6-\x80o\xc7\x87\x0c+Q*]z{\xcd\xa8\x90.\x13\x01\x17\xc1\xf5\xa4\x0e\xb0\x13\x11S\x9e\x13'

Explanation:

Signature Hash is necessary to initiate any transaction. Unfortunately, there is no single-step process to generate the signature hash.

Firstly, we import all the necessary functions and set the chain to ‘mainnet’. Then we generate a secret key by using a wallet secret key. Make sure that you create a SHA256 of the wallet secret key. In this example, we used hashlib for this purpose.

Next, we have to generate a Script Pub key by using the CScript method. And finally, you can use this script pub key to generate a signature hash by using SignatureHash() from python-bitcoinlib.

4. Spend P2PKH Transaction

Code:

import hashlib

import bitcoin, bitcoin.core, bitcoin.core.script, bitcoin.core.scripteval, bitcoin.wallet

bitcoin.SelectParams('mainnet')

h = hashlib.sha256(b'wallet secret key').digest()
seckey = CBitcoinSecret.from_secret_bytes(h)

# lx corresponds to little endian hex
txid = lx('010862f9588f760b4a007cc316baa38890d5e102dc8cee923aae396260e13cb1')
vout = 0

# Create the txin structure, which includes the outpoint
txin = CMutableTxIn(COutPoint(txid, vout))
print(txin)

# Creating Script Pub Key
param = [OP_DUP, OP_HASH160, Hash160(seckey.pub), OP_EQUALVERIFY, OP_CHECKSIG]
txin_scriptPubKey = CScript(param)

# Create txout object
txout = CMutableTxOut(0.001*COIN, CBitcoinAddress('1CaJbGDKkk2DzWNAgHs6sgMdMJZ9eXvCs7').to_scriptPubKey())

# Create unsigned transaction
tx = CMutableTransaction([txin], [txout])

sighash = SignatureHash(txin_scriptPubKey, tx, 0, SIGHASH_ALL)

sig = seckey.sign(sighash) + bytes([SIGHASH_ALL])

txin.scriptSig = CScript([sig, seckey.pub])

VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH,))

print(bitcoin.core.b2x(tx.serialize()))

Output:

CTxIn(COutPoint(lx('010862f9588f760b4a007cc316baa38890d5e102dc8cee923aae396260e13cb1'), 0), CScript([]), 0xffffffff)
0100000001b13ce1606239ae3a92ee8cdc02e1d59088a3ba16c37c004a0b768f58f9620801000000006b483045022100c3e51dd0bdc949c99933aa2cadf7e7e3cfd3c4c717eee676c54d8bb01343b91e02203f0db8003d8c9fb09b6e8d35bb6ee93eec1d90b87ca6b0563295720c02bb38c5012103abb2ba802645d29cba4e1485b9458964f25b2bd5dc899e7cff2ba6db4e58e38bffffffff01a0860100000000001976a9147ef5cb5b4a195abc9acb97afaa70dcf8e594e49188ac00000000

Explanation:

P2PKH is one of the ways to transact over the network. Using the Signature Hash that we generated in the previous example, we can easily carry out the transaction.

Firstly, we create a little-endian hex by using lx(). This txid, txin, and txout will togetherly carry out the transaction as mentioned in the example. In the end, VerifyScript() helps to check the transaction status.

Final Words

Blockchain Programming is one of the tricky and hard to understand things. But by useful modules and Python, you can carry out the transactions on Bitcoin data structure and protocol with ease. python-bitcoinlib has provided a good API for signing, transacting, and validating over the chain.

Please let us know in the comments if you have more doubts regarding the library/module.

Subscribe
Notify of
guest
2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Izzy
Izzy
2 years ago

In step 3 i get an error

sighash = SignatureHash(txin_scriptPubKey, tx, 0, SIGHASH_ALL)
NameError: name ‘tx’ is not defined

Pratik Kinage
Admin
1 year ago
Reply to  Izzy

You need to create Unsigned Transaction first by – tx = CMutableTransaction([txin], [txout])