In Bitcoin, transactions transfer value from the sender to the receiver. They consume unspent transaction outputs (UTXO) and produce new UTXOs. In this article, we will examine how the Bitcoin script's execution engine validates transactions thereby permitting value to be moved from one user to another.
On a high level, transactions are made up of inputs (except coinbase transactions) and outputs. Inputs contain unlocking scripts, transaction id(s), locktime, the recipient address as well as a change address provided there is a change.
As stated earlier, inputs contain transaction id(s) (
txid) and they are references to UTXOs. When referencing a UTXO, their output index(
vout) is also specified. A single transaction can reference more than one
txid which sums up to the amount of bitcoin being sent. The sum of these inputs must be greater than or equal to the sum of output(s) for the transaction to be accepted as valid.
Transaction amounts are represented in units called satoshis and one unit of bitcoin is 100,000,000 satoshis. The difference between the sum of inputs and that of outputs is collected as fees by the miners.
txid is stated alongside its unlocking scripts that must satisfy the locking conditions placed on the output. Depending on the type of output, the unlocking script can be constructed from a pair of private and public keys or it may require more than a pair of keys to construct the unlocking scripts.
Transaction inputs also contain locktime which specifies when the transaction will be valid and can be broadcasted to the network. In most transactions, the locktime is set to zero to indicate immediate validity. However, if the locktime is not zero and is below 500 million, it is interpreted as the block height but if it is above 500 million, it is interpreted as Unix Epoch timestamp (seconds since Jan. 1st, 1970) all stating when the transaction becomes valid.
Outputs on the other hand state the value of bitcoin sent and the locking conditions to spend them. Similar to inputs, a transaction can have more than one output each having a value, an index, and a locking script.
For a transaction to be accepted as valid and mined into a block, it has to conform to the consensus rules. These rules are set out in the Bitcoin node's software. Some of these rules in addition to those stated above are that the UTXOs have not been spent, and the unlocking scripts must satisfy the locking scripts amongst others.
There are many types of Bitcoin transactions: Pay-to-public-key-hash (P2PKH), Pay-to-Script-Hash(P2SH), Pay-to-Witness-public-key-hash(P2WPKH), Pay-to-Witness-Script-Hash(P2WSH) and Pay-to-TapRoot(P2TR). The most common type amongst them is P2PKH, which requires only a pair of keys to sign and unlock outputs.
To spend a P2PKH output, the sender has to present an unlocking script called ScriptSig which comprises the public key and digital signature created from the senders' private key. This is validated by the Bitcoin script execution engine according to the consensus rules.
Let's examine a P2PKH transaction below to understand how the locking and unlocking scripts are evaluated by the stack execution engine.
Below is a deserialized P2PKH transaction output:
Input: Previous tx: f5d8ee39a430901c91a5917b9f2dc19d6d1a0e9cea205b009ca73dd04470b9a6 Index: 0 scriptSig: 304502206e21798a42fae0e854281abd38bacd1aeed3ee3738d9e1446618c4571d10 90db022100e2ac980643b0b82c0e88ffdfec6b64e3e6ba35e7ba5fdd7d5d6cc8d25c6b241501 Output: Value: 5000000000 scriptPubKey: OP_DUP OP_HASH160 404371705fa9bd789a2fcd52d2c580b65d35549d OP_EQUALVERIFY OP_CHECKSIG
Let's consider the locking script in the above output called scriptPubKey.
404371705fa9bd789a2fcd52d2c580b65d35549d is the hexadecimal representation of the hash of the recipient public key without
base58 encoding otherwise called Bitcoin address. For simplicity, let's replace it with the shorthand
Public Key Hash in the scriptPubKey. We, therefore, have the scriptPubKey as:
OP_DUP OP_HASH160 <PKH> OP_EQUALVERIFY OP_CHECKSIG.
Let's assume Bob is the recipient of the above transaction output. To spend this output, he will construct a transaction that references this transaction id, provide a public key and signature (unlocking script), and the address to send to (these are all handled by his wallet application).
When his wallet application broadcasts this new transaction, each full Bitcoin node that receives the transaction will validate it to ensure it is indeed a valid transaction. The below diagram shows how the transaction will be evaluated:
As can be seen in the above diagram, the unlocking (scriptSig) produced by Bob's wallet is first placed on the stack, followed by the locking scripts, and executed on a Last-in-First-Out (LIFO) basis, from left to right.
Bitcoins' script language operators (
OP_HASH160, etc) push or pop one or more parameters from the stack, act on them and push the result onto the stack. If at any point the execution fails, then the transaction is invalid and rejected. However, if at the end of the execution, the result on the stack is TRUE, then the transaction is valid.
Following the above diagram,
OP_DUP will duplicate
Bob's Public key and push the result back to the stack.
OP_HASH160 operand takes one of
Bob's duplicated public key, acts on it, produces a Public Key Hash (PKH), and push the result - PKH- back to the stack.
OP_EQUALVERIFY comprises two operators -
OP_EQUAL will take the two
PKHs and compare them and return TRUE or FALSE back to the stack, while
OP_VERIFY will terminate execution if it is FALSE that is found on the stack otherwise it will remove TRUE from the stack. Then OP_CHECKSIG will take the pubkey and signature and check if the signature matches the pubkey, then it will return TRUE marking the transaction as valid otherwise it will return FALSE marking the transaction as invalid. You can read more about OP_CODES used in Bitcoin here.
In conclusion, a P2PKH is a type of transaction that can be spent by presenting a public key and a digital signature from a single pair of public and private keys. If TRUE remains after the Bitcoin execution engine executes the combined script, then the transaction is valid otherwise it is invalid. You can read more about Bitcoin transactions in Mastering Bitcoin by Andreas Antonopoulos. Thank you.