Exploring Bitcoin: signing the P2PKH input

bitaps.com
3 min readJul 8, 2018

--

This article is a detailed description of how P2PKH output works in bitcoin transactions and the step-by-step algorithm for signing this type of output inside transaction input. In the enclosed part is an example of a signing P2PKH input using the Python.

OP_DUP OP_HASH160 <hash> OP_EQUALVERIFY OP_CHECKSIG

Pay to Public Key Hash output script is the most commonly used way to transfer and store bitcoins. At this moment the most substantial number of unspent transaction outputs falls on this type of script. The address of this script is a hash from the public key converted into base58 encoding with the addition of a byte version and a checksum. Visually for the user does not differ from the addresses received from the P2PUBKEY script.

Mainnet address example: 1BsBzuBTT8r4auWrxZr8sGVtoRhGg9ndUC
Testnet address example: mn9QhsFiX2eEXtF6zrGn5N49iS8BHXFjBt

Published public key hash (sha256+ripemd160) in blockchain instead of the public key, protects against attempts of cryptanalysis of the public key. This security model works only in case no address reuse. This type of script is safer then P2PUBKEY because public key not published in blockchain until received first spending transaction from this address. If the address used again after the first outgoing transaction, security level become the same as the P2PUBKEY script, because public key will be published in blockchain inside signature script of first spending transaction.

To create a spending transaction from this type of output, must provide a signature script (unlocking script) for this output. The signature script consists of a signature and public key. Validation of signed transaction input (unspent output from other transaction) starts from execution signature script, then executed P2PKH script.

Signature script: <sig> <pub_key>
P2PKH script: OP_DUP OP_HASH160 <hash> OP_EQUALVERIFY OP_CHECKSIG

Script execution step by step:

Execution completed. In case of the signature was valid in stack pushed 01 this means True, and transaction input validation is passed.

Bitcoin testnet signing P2PKH step by step example:

We have 1.3 tBTC on mvJe9AfPLrxpfHwjLNjDAiVsFSzwBGaMSP and want transfer it to n4AYuETorj4gYKendz2ndm9QhjUuruZnfk

Private Key: cThjSL4HkRECuDxUTnfAmkXFBEg78cufVBy3ZfEhKoxZo6Q38R5L
Address: mvJe9AfPLrxpfHwjLNjDAiVsFSzwBGaMSP
Input transaction: 5e2383defe7efcbdc9fdd6dba55da148b206617bbb49e6bb93fce7bfbb459d44
Input transaction output: 1
Input amount: 1.3000000

Step 1: create unsigned transaction with empty Signature script

{ version: 1
vIn: {0: {scriptSig: ,
sequence: 4294967295,
txId:
5e2383defe7efcbdc9fdd6dba55da148
b206617bbb49e6bb93fce7bfbb459d44,
vOut: 1}},
vOut: {0: {address:
n4AYuETorj4gYKendz2ndm9QhjUuruZnfk,
value: 129000000}},
lockTime: 0}
HEX:0100000001449d45bbbfe7fc93bbe649bb7b6106b248a15da5dbd6fdc9bdfc7efede83235e0100000000ffffffff014062b007000000001976a914f86f0bc0a2232970ccdf4569815db500f126836188ac00000000HEX explained:01000000 [version]01 [inputs count]
449d45bbbfe7fc93bbe649bb7b6106b248a15da5dbd6fdc9bdfc7efede83235e
[input transaction hash in little endian byte order]
01000000 [input transaction output]
00 [signature script len]
ffffffff [sequence]
01 [outputs count]
4062b00700000000 [output amount]
1976a914f86f0bc0a2232970ccdf4569815db500f126836188ac
[locking script]
00000000 [locktime]

Step 2: we should get signature hash from this transaction. ( we will use SIGHASH_ALL type of sighash)

Input 0 SIGHASH_ALL preimage:0100000001449d45bbbfe7fc93bbe649bb7b6106b248a15da5dbd6fdc9bdfc7efede83235e010000001976a914a235bdde3bb2c326f291d9c281fdc3fe1e956fe088acffffffff014062b007000000001976a914f86f0bc0a2232970ccdf4569815db500f126836188ac0000000001000000Sighash: 8e2f535bbaf17d32f784259bede09b7dd27deacca836661f4dde3ba3a440fc63

Step 3: sign sighash with private key

Signature: 3045022100e15a8ead9013d1de55e71f195c9dc613483f07c8a0692a2144ffa90506436822022062bc9466b9e1941037fc23e1cfadf24c8833f96942beb8f4340df60d506f784b

Step 4: insert signature to transaction signature script and sighash type byte

Transaction hex:0100000001449d45bbbfe7fc93bbe649bb7b6106b248a15da5dbd6fdc9bdfc7efede83235e010000006b483045022100e15a8ead9013d1de55e71f195c9dc613483f07c8a0692a2144ffa90506436822022062bc9466b9e1941037fc23e1cfadf24c8833f96942beb8f4340df60d506f784b012103969a4ac9b1521cfae44a929a614193b0467a20e0a15973cae9ba1efb9627d830ffffffff014062b007000000001976a914f86f0bc0a2232970ccdf4569815db500f126836188ac00000000Explained:01000000 [version]01 [inputs count]
449d45bbbfe7fc93bbe649bb7b6106b248a15da5dbd6fdc9bdfc7efede83235e
[input transaction hash in littile endian byte order]
01000000 [input transaction output]
6b [signature script len]
48 [signature push len]
3045022100e15a8ead9013d1de55e71f195c9dc613483f07c8a0692
a2144ffa90506436822022062bc9466b9e1941037fc23e1cfadf24c
8833f96942beb8f4340df60d506f784b
[signature]
01 [sighash type SIGHASH_ALL]
21 [public key push len]
03969a4ac9b1521cfae44a929a614193b0467a20e0a15973cae9ba1
efb9627d830 [public key]
[signature script]
ffffffff [sequence]
01 [outputs count]
4062b00700000000 [output amount]
1976a914f86f0bc0a2232970ccdf4569815db500f126836188ac
[locking script]
00000000 [lock time]

Step 5: broadcast transaction to network

4484ec8b4801ada92fc4d9a90bb7d9336d02058e9547d027fa0a5fc9d2c9cc77

Example with python bitcoin library pybtc:

https://pybtc.readthedocs.io

--

--