When first learning about the scripts the Bitcoin protocol uses, I couldn’t find in-depth information in one place. I compiled a document for my own reference based on sites and posts I’ve encountered. Hopefully this will make someone’s life a little easier!
Every transaction contains one script per input and one script per output. Output scripts specify who the money is going to and what must be done to claim it. Input scripts specify who the money is from and generally claim previous outputs (unless the input is a coinbase transaction), thus using coins received from previous transactions.
The scripts contain data fields and operations. When an output is claimed by an input, the input script is prepended to the output script.
i.e. [input script claiming money][output script being claimed]
Data fields, each starting with a length, are pushed onto a stack. Operations indicate what must be done to the field(s) at the top of the stack. Usually, this is simply signature verification.
See https:en.bitcoin.it/wiki/Script for more general information.
There are a number of different script output/input pairs:
a) Standard script sending money to a Bitcoin address and claiming money sent in this way.
output (send): OP_DUP OP_HASH160 [pubKeyHash] OP_EQUALVERIFY OP_CHECKSIG
input (claim): [sig][pubKey]
b) Standard script assigning newly generated coins to a Bitcoin address and clamining these coins. This is also used for transactions to an IP address.
output (send): [pubKey] OP_CHECKSIG
input (claim): [sig]
c) Standard input script for newly generated coins (COINBASE).
The script is random data (prev_hash is all 0′s, and prev_index is all f’s). Some mining pools encode their information in these scripts. The “extranonce” field, along with a timestamp, may also be encoded here when a miner has exhausted the nonce space while trying to solve the proof-of-work puzzle.
d) Standard script sending money to a script instead of a Bitcoin address (P2SH = Pay-To-Script (BIP 16)). The script must be one of the other standard output scripts.
output (send): OP_HASH160 [hashOfScript] OP_EQUAL
input (claim): [signatures as required by script][script]
e) Standard script requiring multiple signatures to claim coins (BIP 11) .
output (send): OP_SMALLINT1 [pubKey][pubKey][pubKey] OP_SMALLINT2 OP_CHECKMULTISIG
input (claim): OP_0 [sig][sig][sig]
f) Sample non-standard transaction including a message.
output (send): [message] OP_DROP [pubKey] OP_CHECKSIG
input (claim): [sig]
On-The-Wire: Parsing The Scripts
Parsing the scripts requires understanding what they look like at the byte level. The following diagram has helped me out quite a bit:
OP_DUP = 0×76
OP_EQUALVERIFY = 0×88
OP_DROP = 0×75
OP_HASH160 = 0xa9
OP_CHECKSIG = 0xac
OP_EQUAL = 0×87
OP_CHECKMULTISIG = 0xae
OP_SMALLINT1 = m
OP_SMALLINT2 = n
where 1 ≤ n ≤ 3 and 1 ≤ m ≤ n are integers representing that m out of n signatures need to appear to claim the transaction.
Common Data Fields:
[sig] = [sigLength][0×30][rsLength][0×02][rLength][sig_r][0×02][sLength][sig_s][0×01]
sigLength gives the number of bytes taken up the rest of the signature ([0×30]…[0×01])
rsLength gives the number of bytes in [0×02][rLength][sig_r][0×02][sLength][sig_s]
rLength gives the number of bytes in [sig_r] (approx 32 bytes)
sLength gives the number of bytes in [sig_s] (approx 32 bytes)
[pubKeyHash] = [pubKeyHashLength][RIPEMD160(SHA256(public key))]
where pubKeyHashLength is always 0×14 (= 20) since the RIPEMD160 digest is 20 bytes.
[pubKey] (uncompressed) = [publicKeyLength][0×04][keyX][keyY]
where publicKeyLength is always 0×41 (= 65) since keyX and keyY are 32 bytes and 0×04 is 1 byte
[pubKey] (compressed) = [publicKeyLength][0×02 or 0×03][keyX]
where publicKeyLength is always 0×21 (= 33) since keyX is 32 bytes and 0×02/0×03 is 1 byte.
Note: [pubKey] can be either compressed or uncompressed. [keyX] and [keyY] are always 32 bytes each. Thus, publicKeyLength will always be 0×41 (= 65) for uncompressed keys and 0×21 (= 33) for compressed keys. The 0×02/0×03/0×04 is part of the key and describes the encoding. 0×04 is for uncompressed while 0×02/0×03 is for compressed key encodings.
Bitcoin Addresses: Base 58 Encoded Public Keys
Bitcoin addresses can be built from the public key or the public key hash as follows:
(Taken from https://en.bitcoin.it/wiki/Protocol_specification#Addresses)
Key hash = Version concatenated with RIPEMD-160(SHA-256(public key))
Checksum = 1st 4 bytes of SHA-256(SHA-256(Key hash))
Bitcoin Address = Base58Encode(Key hash concatenated with Checksum)
Note: Version = 1 byte of 0 (zero); on the test network, this is 1 byte of 111
Note: The Base58 encoding used is home made, and has some differences. Especially, leading zeroes are kept as single zeroes when conversion happens.
A more detailed step by step algorithm can be found at:
Note: In step 9, it should not be using Base58Check, which appends a checksum to its input and then converts to base 58. Since the checksum has already been appended in step 8, just convert the string from step 8 to base 58 using the custom alphabet.
There is a site that provides a form which performs these steps for a given key:
A full public key (including the 0×02/0×03/0×04 leading byte) would be pasted into #1, while a public key hash would be pasted into #3.