As of Sep 12, 2023, there are 16,391 nodes in the Bitcoin network
How to represent binary as text?
Perhaps for printing
Or for email
Many email systems can only transmit text, not binary
So images need to be suchly encoded
Example: the Bitcoin genesis block has hash 0x000000000019d6689c085ae165831e934ff763ae46a2a6 c172b3f1b60a8ce26f
Hex encoding: each byte becomes 2 hex digits
Each (8-bit) text character represents 4 bits: 200% increase in size
Base 64 encoding
Given binary data, split it into 6 bit chunks
Each 6-bit chunk maps to a given printable letter
0 -> A ... 25 -> Z
26 -> a ... 51 -> z
52 -> 0 ... 61 -> 9
62 -> +
63 -> /
= is a pad character if the total number of bits is not evenly divisible by 6
Each text character represents 6 bits: 133% increase in size
Base 64 encoding example
$cat lorem-ipsum.txt
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
$ base64 lorem-ipsum.txt
TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdCwg
c2VkIGRvIGVpdXNtb2QgdGVtcG9yCmluY2lkaWR1bnQgdXQgbGFib3JlIGV0IGRvbG9yZSBtYWdu
YSBhbGlxdWEuIFV0IGVuaW0gYWQgbWluaW0gdmVuaWFtLCBxdWlzCm5vc3RydWQgZXhlcmNpdGF0
aW9uIHVsbGFtY28gbGFib3JpcyBuaXNpIHV0IGFsaXF1aXAgZXggZWEgY29tbW9kbyBjb25zZXF1
YXQuCg==
$
Note that this particular text did not produce a + or / in the base 64 encoding
- Given an ECDSA privatekey:
18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725
- And an ECDSA publickey (0x02 is y-coord, rest is x-coord)
0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352
- SHA-256on the publickey:
0b7c28c9b7290c98d7438e70b3d3f7c848fbd7d1dc194ff83f4f7cc9b1378e98
- RIPEMD-160on that: f54a5851e9372b87810a8e60cdd2e7cfd80b6e31
- Prefix that with0x00 for a "standard" (P2PKH) address:
00f54a5851e9372b87810a8e60cdd2e7cfd80b6e31
- Generate the checksum:
- Perform SHA-256 twice on RIPEMD-160 result:
c7f18fe8fcbed6396741e58ad259b5cb16b7fd7f041904147ba1dcffabf747fd
- Take the first 4 bytes: c7f18fe8
- Concatenate together (spaces for clarity only):
00 f54a5851e9372b87810a8e60cdd2e7cfd80b6e31 c7f18fe8
- Convert that (binary) hex value to base 58:
1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs
Bitcoin address -> hash
Given a Bitcoin invoice address
Base-58 decode it
Verify the correct network (first byte)
Verify the checksum (last 4 bytes)
What's left is the hash of the public key
Formally the RIPEMD160 of the SHA256 of the public key
Confirmations
As the blockchain grows, it becomes harder to change transactions many blocks in the past
Each additional block since a given transaction is a "confirmation" that the given transaction is "permanent"
Formally: the number of confirmations of a block is the number of successive blocks since then in the blockchain
The more confirmations, the more confident you are that the transaction will not change
We'll talk later about how many confirmations, how to attack this, etc.
Difficulty / target
The target (and thus difficulty) is deterministically computed by each node
Based on the average time taken every 2016 blocks (2 weeks)
Reference: the Script page of the Bitcoin developer wiki
BTC Stack
It's like the stack we all know and love, with some differences:
It has many more operations
Pop 2, pop second, swap top two, etc.
Each value on the stack can be a different size
It keeps track of the type of each value as well
Bitcoin Output Script
Each TXN has a output script
Specifies the commands that are executed to verify who can spend these coins
The most common states that any transaction that provides a public key that matches the given signature
Typically involves public key signatures, not the public keys themselves
This is commonly called the pubkey script
Because it often (but not always!) states the (hash of the) public key required to spend the TXN
Bitcoin Input Script
If a TXN's output script says one must provide a public key...
... then we provide it in the input script
One can provide more than just the keys, though
This is commonly called the sig script
Because it provides the signature (and public key) required by the output (pubkey) script
How a Bitcoin TXN is verified
To spend a UTXO:
Take the input script (aka sig script) from the TXN that is trying to spend the UTXO
Take the output script (aka pubkey script) that created the UTXO
Concatenate these together (sigscript before pubkey script), and execute
If the result of these is true, then the coins can be spent (transferred)
Formally, if the top value on the stack is true after execution
Output scripts
A typical output script will state:
The redeemer must provide a public key that matches the hash listed in the output script
Recall that a BTC address is a hashed public key
The redeemer must sign the entire UTXO transaction with that public key
Called the 'pubkey script' because it (typically) requests a public key (or hash of one)
A typical input script will provide:
The public key that matches the hash in the output script
A signature of the entire transaction
Called the 'sig script' because it provides the signature of the TXN
Input scripts
An input script provides the data the output script needs to be valid
Typically that is just two data items:
The signature of the entire UTXO transaction
Meaning the transaction that created the BTC that is trying to be spent
The signature is created by the private key of the Bitcoin key pair
This is the sender verifying that this transaction really came from the key pair's private key
The public key of the sending Bitcoin key pair
The hash of this key is in the UTXO's output script
This will shortly be verified to match with the private key that signed the signature
Selected Bitcoin Opcodes
Hex value(s)
Name
Description
0
OP_0
Push 0 (false) onto the stack
81-96
OP_1 → OP_16
Push that number onto the stack
1-75
(push)
Push that many (following) bytes onto the stack
118 = 0x76
OP_DUP
s.push(s.top())
169 = 0xa9
OP_HASH160
s.push(RIPEMD160(SHA256(s.pop())))
136 = 0x88
OP_EQUAL_ VERIFY
OP_EQUAL: s.push(s.pop()==s.pop()); OP_VERIFY: abort if s.top() is false
172 = 0xac
OP_CHECKSIG
Check the sig of the previous TXN
OP_CHECKSIG
It's a signature of the previous UTXO transaction, not the current one
Pops two values off the stack: first the public key kpub and then the signature s
The signature s was by the redeemer: the hash h′ of the previous UTXO transaction encrypted with the private key kpri
Hashes the previous UTXO transaction to get h
Decrypts s with kpub to get h′
Verifies h==h′, and pushes result (true (1) or false (0)) onto stack
OP_CHECKSIGVERIFY will run OP_VERIFY after
OP_VERIFY: abort if stack top is not true (1)
P2PKH example script
This is a standard pay-to-pubkey-hash (P2PKH) script:
76 A9 14
OP_DUP OP_HASH160 Bytes to push (0x14 == 20)
89 AB CD EF AB BA AB BA AB BA AB BA AB BA AB BA AB BA AB BA
20bytes of data to push
88 AC
OP_EQUALVERIFY OP_CHECKSIG
Full hex-only script (spaces for clarification only):
76 A9 1489ABCDEFABBAABBAABBAABBAABBAABBAABBAABBA 88 AC
P2PKH example script
This is a standard pay-to-pubkey-hash script:
76 A9 14
OP_DUP OP_HASH160 Bytes to push (0x14 == 20)
89 AB CD EF AB BA AB BA AB BA AB BA AB BA AB BA AB BA AB BA
20bytes of data to push
88 AC
OP_EQUALVERIFY OP_CHECKSIG