Thursday 16 November 2017

Bitcoin core tutorial & code walk through (Part 9) - P2PKH/P2SH

In part 9 of the tutorial, the Bitcoin transaction will be analysed. Specifically, we will look at two types of transaction.
  • Pay to Public Key Hash (P2PKH)
  • Pay to Script Hash (P2SH)
As an example, a typical Bitcoin transaction is shown below:
Input:
Previous tx: f5d8ee39a430901c91a5917b9f2dc19d6d1a0e9cea205b009ca73dd04470b9a6
Index: 0
scriptSig: 304502206e21798a42fae0e854281abd38bacd1aeed3ee3738d9e1446618c4571d10
90db022100e2ac980643b0b82c0e88ffdfec6b64e3e6ba35e7ba5fdd7d5d6cc8d25c6b241501

Output:
Value: 100000000
scriptPubKey: OP_DUP OP_HASH160 404371705fa9bd789a2fcd52d2c580b65d35549d
OP_EQUALVERIFY OP_CHECKSIG
In input field, previous tx is the hash of the previous transaction. Index chooses the specific output in the transaction. ScriptSig contains the signature to satisfy the transaction conditions, for the recipient who is spending the bitcoin. This input uses the previous transaction of f5d8... and chooses output 0 of that transaction (as seen in Index: 0). 
In output field, scriptPubKey defines the conditions to spend the bitcoins. Value is the satoshi to be sent. One BTC is 100,000,000 satoshi. This output sends 1 BTC, it is sent to Bitcoin address 4043... 

P2PKH

scriptPubKey: OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
scriptSig: <sig> <pubKey>
As seen above, the scriptSig contains sender public key and signature of the sender. The scriptPubKey contains the hash of the receiver's public key. The recipient of P2PKH Bitcoin transaction, checks the signature and the public key hash. The public key must generate the hash that matches the pubKeyHash. The sender signature can be verified using the sender's public key.

The scriptSig part is what the receiver uses to spend the money that they got from P2PKH. Because they are spending the money, at that point they would be the new sender. The <pubKey> for this new transaction hashes to the receiver's <pubKeyHash> from the old transaction when they first got the money.
The checking process is as below:
StackScriptDescription
Empty.<sig> <pubKey> OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIGscriptSig and scriptPubKey are combined.
<sig> <pubKey>OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIGConstants are added to the stack.
<sig> <pubKey> <pubKey>OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIGTop stack item is duplicated.
<sig> <pubKey> <pubHashA><pubKeyHash> OP_EQUALVERIFY OP_CHECKSIGTop stack item is hashed.
<sig> <pubKey> <pubHashA> <pubKeyHash>OP_EQUALVERIFY OP_CHECKSIGConstant added.
<sig> <pubKey>OP_CHECKSIGEquality is checked between the top two stack items.
trueEmpty.Signature is checked for top two stack items.
For the source code, in the bitcoin-tx.cpp, there is a separate main() function that calls CommandLineRawTx(), which in turn calls MutateTx(). MutateTx() handles adding key and value to CMutableTransaction. The key and value are declare as std::string key, valueThe bitcoin-tx.cpp is compiled into bitcoin-tx binary.

In MutateTx(), depending on the command line option, MutateTxAddOutPubKey() adds value and scriptPubKey to the output, using public key from command line input. MutateTxAddOutAddr() adds value and scriptPubKey to the output, using address from command line input.

For bitcoind binary, in rest.cpp, the rest_getutxos(HTTPRequest *, std::string &) finds the txid of the UTXO, and calls ScriptPubKeyToUniv() to include the scriptPubKey in output.

In rest.cpp, the rest_tx(HTTPRequest*, std::string &) prepares the transaction with CTransactionRef class, then for JSON format, calls TxToUniv() to write the HTTP request.

In core_write.cpp, the TxToUniv(CTransaction&, uint256&, UniValue&) pushes scriptSig to vin and scriptPubKey to vout. For vout, it calls ScriptPubKeyToUniv() to include the scriptPubKey in vout.

The rest_tx() and rest_getutxos() are in uri_prefixes structure. This structure is registered in HTTP handler in StartREST().  StartREST() is called by AppInitServers() in init.cpp.
P2SH
P2SH lets the sender funds a transaction using 20 byte hash. The script supplied to redeem must hash to the scriptHash. 
Without P2SH, the scripts are shown below:
locking script: 2 <pubKey1> <pubKey2> <pubKey3> 3 OP_CHECKMULTISIG
unlocking script: <sig1> <sig2>
With P2SH, the scripts become:

redeem script: 2 <pubKey1> <pubKey2> <pubKey3> 3 OP_CHECKMULTISIG 
locking script: OP_HASH160 <redeem script Hash> OP_EQUAL
unlocking script: <sig1> <sig2>

So with P2SH, the locking script is simplified. The actual scripts in transactions are as below:

scriptPubKey: OP_HASH160 <scriptHash> OP_EQUAL 
scriptSig: <sig1> <sig2> OP_m <pubKey1> ... OP_n OP_CHECKMULTISIG
The locking script is OP_HASH160 <scriptHash> OP_EQUAL. The locking script is a simplified form of multisig script. From multisig script: 2 <pubKey1> <pubKey2> <pubKey3> 3 OP_CHECKMULTISIG, the mutisig script hashes to 20 byte value of 8ac1d7a2fa204a16dc984fa81cfdf86a2a4e1731. Therefore, the locking script becomes OP_HASH160 8ac1d7a2fa204a16dc984fa81cfdf86a2a4e1731 OP_EQUAL.
The scriptSig <sig1> <sig2> OP_2 <pubKey1> <pubKey2> <pubKey3> OP_3 OP_CHECKMULTISIG, is presented when recipient wants to spend the bitcoins.

The checking process:
StackScriptDescription
Empty.OP_2 <pubKey1> <pubKey2> <pubKey3> OP_3 OP_CHECKMULTISIG OP_HASH160 <scriptHash> OP_EQUALredeem script checked with locking script, to make sure scriptHash matches
true<sig1> <sig2> OP_2 <pubKey1> <pubKey2> <pubKey3> OP_3 OP_CHECKMULTISIGunlocking script executed to unlock redeem script
trueEmpty.Signatures validated in the order of the keys in the script.
For the source code, to be continued...

No comments:

Post a Comment