Bitcoin Textbook
Bitcoin Textbook
Konstantinos Karasavvas
v0.4
Copyright © 2022 Konstantinos Karasavvas
0.1 Preface 7
3 Forking in a nutshell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.1 Software Development Forks 30
3.2 Blockchain Forks 30
3
3.3 Soft-forks 31
3.4 Hard-forks 33
3.5 Upgrading Bitcoin 35
4 Technical Fundamentals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
4.1 Bytes, Hex, Endianness and Encodings 38
4.2 Cryptographic Hash Functions 40
4.3 Asymmetric Cryptography 41
6 Scripting 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
6.1 Transactions 54
6.2 Creating P2PKH Transactions 57
6.3 Signatures 63
6.4 Pay to script hash (P2SH) 65
6.5 Segregated Witness (SegWit) 69
6.6 Pay To Multi-signature (P2MS) 76
6.7 Storing Data (OP_RETURN) 76
6.8 Exercises 79
7 Scripting 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
7.1 Timelocks 81
7.2 RBF & CPFP 88
7.3 Hash Time-Locked Contracts 89
7.4 Atomic Swaps 91
7.5 Exercises 93
8 Advanced Topics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
8.1 Payment Channels 94
8.2 Lightning Network 95
8.3 Sidechains 95
Literature . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
0.1 Preface
I started teaching Bitcoin programming in 2016. Every year I was trying to improve and
update my material to keep it as relevant as possible. Luckily, Bitcoin progresses at a steady
pace while always keeping backwards compatibility. This is convenient because existing
material will always be valid even though better alternatives might be introduced in the
future.
To understand the material better and to improve the material in my courses I started
an open source Python library, called bitcoin-utils1 . The library was created for educational
purposes and not for computational efficiency and that might be evident in certain parts of
the implementation. Before starting this library I had investigated several other well-known
Python libraries but I did not find an appropriate one for teaching. Some were too low-level
with limited documentation while others where abstracting concepts that I deemed where
important for students to understand. The book contains a lot of examples using this library
for demonstration.
Throughout the years I have prepared a lot of material based on my early code exper-
iments, the bitcoin-utils library and several online resources, especially the Bitcoin Stack
Exchange2 and the Bitcoin Book3 by A. Antonopoulos. While I try to always credit the ini-
tial sources that I have consulted over the years it is possible that I have missed some. Please
let me know and I will update accordingly.
This book is not about introducting what Bitcoin4 is. The readers are expected to have
some programming knowledge, be comfortable with their own operating system as well as
have some basic understanding of what Bitcoin is, its utility, what addresses and private
keys are as well as have some experience using wallets and sending bitcoins5 . However, the
first chapters do give a quick summary of Bitcoin and how it works to make sure that the
fundamentals are covered.
This book is about teaching Bitcoin programming; to help people delve deeper and in
particular learn how to talk to the Bitcoin network programmatically. The Bitcoin library is
relatively easy to navigate through, so you can go even deeper when required. There is an
emphasis on providing practical examples which, I believe, helps understanding.
I have been using a Linux-based machine and thus most command-line examples are
from bash shell. However, people comfortable with other Operating Systems should have
no issues to adjust as needed.
1 https://github.com/karask/python-bitcoin-utils
2 https://bitcoin.stackexchange.com/
3 https://github.com/bitcoinbook/bitcoinbook
4 https://github.com/karask/satoshi-paper
5 When we refer to the coins we will use bitcoin(s) (lowercase ‘b’) and when we refer to the protocol or the
network we will use Bitcoin (uppercase ‘B’)
1. How Bitcoin Works
1.9 Exercises 25
This chapter provides a high-level introduction of how Bitcoin works. It aims to be a summary
of the prerequisite knowledge required by the reader before moving into the following chapters.
The operation of the Bitcoin network is demonstrated with a walkthrough of a transaction and
its journey from its creation up until its final destination, the Bitcoin blockchain.
To send 1 bitcoin (or BTC) Alice needs to create a transaction T Xy that sends 1 BTC to
Bob. We know that Alice has at least 1.5 BTC from T Xx .
The names 1Zed, 1Alice and 1Bob are short for the actual bitcoin addresses of Zed, Alice
and Bob respectively. So Alice will send 1 BTC from her 1Alice bitcoin address to Bob to his
1Bob address.
Alice has to prove that she is indeed the owner of the address 1Alice when she creates
the T Xy . Bob does not need to do anything to receive the bitcoins.
8
Chapter 1. How Bitcoin Works 9
A transaction can consist of several inputs (outputs of past transactions) and several out-
puts (addresses to send bitcoins to). When an input is used it is completely consumed; i.e.
all the bitcoins that the TX contains as inputs need to be spent.
The amount of all the inputs needs to be greater or equal to the amounts of outputs. If
greater (recommended) the difference is an implied transaction fee that goes to the miners
(see figure 1.1 where the miner receives 0.01 BTC). A typical transaction transfers some
bitcoins to another user and returns the remaining bitcoins as change to the originating
address or another address that the sender controls.
For privacy reasons it is recommended to send the change to a different address than
the originating. Most bitcoin wallets already do this behind the scenes.
Any number of inputs and outputs is possible as long as a transaction fee is included; the
larger the transaction the larger the transaction fee. The unspent outputs are called Unspent
Transaction Outputs (UTXOs) and the set of UTXOs is essentially all the available bitcoins in
the network.
Once a transaction is created it needs to be sent to a Bitcoin node. After the node receives
the transaction it checks if it is valid, e.g. the output amounts should be less or equal to the
input amounts, the signature proving ownership should be valid, etc. If it is valid the node
will propagate it to all its peers1 , i.e. the other nodes that it is aware of. In turn, the other
nodes will check if the transaction is valid and so on and so forth until all nodes receive the
transaction (see figure 1.2).
From a Bitcoin’s node perspective, the node receives transactions and places all valid ones
into its memory pool, or mempool. It keeps receiving new ones until it decides that it will
group some of those transactions into a block (see figure 1.3).
1 To be more precise they will notify their peers of the transaction by its transaction identifier (txid) and the
peers can choose to request it or not. More details will be provided in the Peer-to-Peer chapter.
10 1.3. Mining: basics
Figure 1.3: A node receives transactions into its mempool and can attempt to create new
blocks for the network.
We are describing what mining nodes typically do. The majority of nodes are not
mining nodes and thus do not attempt to create new blocks, rather they validate and
propagate valid transactions and blocks when they are aware of them.
Every block contains a coinbase transaction that is added by the miner (see next section)
and it sends a deterministically calculated reward to an address of the miner’s choosing.
Finally a header is added to the block containing important information that links this block
to its parent and other information that we will examine in the next section.
But how do we select which blocks will be part of the blockchain? Since, miners
include a reward for themselves everyone wants their block to be the next block in
the blockchain. In other words, how do we avoid spam and Denial of Service (DoS)
attacks?
For a block to be considered valid a miner has to prove that he has done some intensive
computational work. Thus, miners have to spend resources before they create a block. This
mechanism of proving computational work is called Proof-of-Work (PoW) and it involves
solving a problem or puzzle. PoW puzzles have the fundamental property of being difficult
to solve but trivial to validate their correctness.
Bitcoin mining is the process of solving the PoW puzzle and selecting the next valid
block in a way that is undisputed and thus achieve consensus on the current blockchain
state. Bitcoin uses the Hashcash PoW algorithm [1] for its mining.
Figure 1.4: All nodes will eventually receive all transactions but they are free to include
them into a block as they see fit.
A cryptographic hash function is a hash function that takes an arbitrary block of data
and returns a fixed-size bit string, the cryptographic hash value, such that any (acci-
dental or intentional) change to the data will also change the hash value significantly.
As more miners join the blocks will be created faster so the puzzle’s difficulty automat-
ically adjusts (increases) so that it again requires approximately 10 minutes to solve. This
difficulty adjustment is happening every 2016 blocks, which is approximately 2 weeks if each
block takes 10 minutes to mine.
The hash algorithm used is SHA256 and it is applied twice to the block header. As we
will see later the header uniquely represents the whole block including all the transactions
12 1.4. Mining: a bit more technical
and thus hashing the header is effectively the same as hashing the whole block, but much
more efficiently since the header is much smaller.
The miner that successfully creates a valid block first will get the bitcoin reward that they
have set themselves in the coinbase transaction as well as the fees from all the transactions
in the block.
The block reward can be deterministally calculated according to the current block height.
The reward started at 50 bitcoins and is halved every 210000 blocks (approximately 4 years
for 10 minute blocks). So, after block 630000 the reward will be 6.25 bitcoins. The mining
reward can be claimed by the miner only after 100 confirmations, i.e. after 100 blocks have
been confirmed as part of the blockchain since.
Block version and timestamp are self explanatory but we will briefly go through the
remaining fields.
hashMerkleRoot
A block has two parts, the header and the transactions. Since we only hash the block header
to link blocks together, a header needs to represent the whole block, including all its trans-
actions (coinbase and normal). The transactions are indirectly hashed via using a merkle
root and being included in the block by hashMerkleRoot.
A merkle tree2 is constructed by concatenating all the transaction hashes, in pairs. The
resulting hashes are again concatenated and hashed until only a single hash remains, the
merkle root.
An important property of a merkle tree is that you can efficiently prove that a hash (and
thus transaction) is part of the merkle root. A merkle proof consists of the hashes required
to reconstruct the merkle root from the leaf TX, thus proving that the TX hash is indeed part
of the merkle tree. For example to prove that tx1 is part of the merkle root we would need
to provide the hash of cb and its positioning (i.e. left) as well as the parent hash of tx2 and
tx3 (cc3f1) and its positioning (i.e. right).
2 https://en.wikipedia.org/wiki/Merkle_tree
Chapter 1. How Bitcoin Works 13
Figure 1.5: Simple merkle root calculation of coinbase and three transactions.
hashPrevBlock
This is the hash of the previous block in the blockchain. It designates the parent of the
current block and it is effectively what chains the blocks together. For example, if someone
changes a transaction in the previous block then the hashPrevBlock will change. This is of
particular importance as we will see in more detail in section 1.5.
target
Target bits or just bits is represented as an 8 hex-digit number. The first 2 digits are the
exponent and the rest the coefficient. Target bits can be used to calculate the actual target
with the following formula:
The highest possible target (the easiest target) is defined as 0x1d00ffff and gives a 32-
byte target of (expressed as a 64 hexadecimal number):
0 x00000000ffff0000000000000000000000000000000000000000000000000000
If the result of hashing the block header produces a hash that begins with 0x00000000e
(or less) then we have found a solution. That would require, statistically 232 (4,294,967,296)
attempts on average. The smaller the target the more difficult the solution, the more at-
tempts on average.
14 1.4. Mining: a bit more technical
highest_target
Dif f iculty =
current_target
When Bitcoin started it started with the highest target (0x1d00fff) and thus it had diffi-
culty 1. Difficulty 1 requires 232 attempts on average to find a solution. Difficulty 10 requires
232 ∗ 10 attempts on average, etc.
nonce
The nonce is just a number used to differentiate the hash while trying to reach the target.
Given that it is only 4 bytes it can only handle 4.2 billion combinations, while we need
quintillion nowadays3 .
When the limit was reached miners started modifying the timestamp (e.g. -1 sec) to
allow for an additional of 4.2 billion combinations. However, there is a limit of seconds that
a node can deviate from the rest of the network so that did not suffice either4 .
Finally, miners started to use the unused space of coinbase’s transaction input as an extra
nonce allowing an immense amount of extra nonces to be used5 .
Difficulty Adjustment
We already mentioned that the difficulty to find the proper hash is expected to take approx-
imately 10 minutes. However, Bitcoin is an open system and anyone can join (or leave) the
network as a miner. Thus, the network’s hashrate can increase (or decrease) with time.
With more hashing power blocks will be issued faster than 10 minutes and thus the
network has to adjust the difficulty of the problem accordingly. This can be seen in figure 1.6.
Specifically, Bitcoin nodes, check every 2016 blocks (∼2 weeks) the timestamps between
consecutive blocks and sums them to find out how much time t it took. We want t to take
two weeks and thus the new difficulty will be:
2. Get the longest chain’s top block hash and add it in hashPrevBlock
5. Hash the header to find a solution smaller than the specified target
• If more TXs are included in the block or the extra nonce is modified
• If the longest chain changed we want to build on that chain from now on
The new block is being added on top of the existing blocks (every 10 minutes). This
occurs on every single node on the network thus the blocks are the same in all nodes. Blocks
are linked with cryptographic hashes forming a chain of blocks, called Blockchain.
When Block B1 is accepted by the network we say that a transaction on that block has
one confirmation. When B3 is accepted we say that our transaction has 3 confirmations (see
figure 1.8. The more confirmations the more final and secure a transaction is.
Figure 1.8: A node receives blocks and links them to form the blockchain.
(i) Initially our example network has only two blocks and all nodes are in sync.
(ii) Then node I finds the next block, which is disseminated to all other nodes and again
everyone is in sync.
(iii) Next, let’s suppose that two nodes find a solution at about the same time. These blocks
will typically be very similar, including almost the same transactions, but will be dif-
ferent.
(iv) The nodes will propagate their blocks and some peers will get one of the blocks and
some the other. The nodes are aware of both blocks but they will use the block that
they received first as the next block and will start mining the next block on top of that
block. At this stage we do not have consensus since some of the nodes have a blockchain
with the orange block at the top and some the green block.
(v) However, after a while a new block will be found. In our example, this is node F and it
will propagate it throughout the network.
(vi) Finally, when the block is propagated to the nodes with the green block on top they will
realise that there is a longer chain than the one that they are working on. According
to nakamoto consensus the nodes will accept the longer chain as the valid chain and
ignore the green block. The green block is typically called an orphan block7 . And now
7 Precise terminology is more complicated as discussed in https://bitcoin.stackexchange.com/questions/5859/what-
are-orphaned-and-stale-blocks
18 1.6. Nakamoto Consensus and Trust
If there are transactions in the orphaned block that are not in the orange or the blue
block they are moved to the mempool ready to be included in one of the following
blocks.
Of course it would be possible that at step (v) 2 new solutions could again be found one
from a node with an orange block on top and another from a green block on top. Similarly,
consenus would be achieved with the following block and two blocks would be orphaned.
In such a case, we would say that a 2-block reorg occurred.
Nakamoto consensus is a natural and expected reorg event that currently occurs less
than once per month8 even for 1-block reorgs. The chance of a reorg is proportional with
the number of blocks and thus larger reorgs are exceedingly rare.
Establishing Trust
As we have seen, blocks are linked together by including the hash of the previous block on
the new block. For example, in figure 1.10 the hash of B1 is included in the header of B2.
In our example a transaction in B1 (represented with the cyan box) has 3 confirmations.
If an attacker wishes to attempt a double spend attack9 they will need to create and new B1’
block with the modified transaction. However, there are two more blocks on top of B1 and
8 https://bitcoinchain.com/block_explorer/orphaned
9 https://en.wikipedia.org/wiki/Double-spending
Chapter 1. How Bitcoin Works 19
thus the attackers block will be ignored since B1’ will not be the longer chain. The attacker
also needs to create B2’, B3’ and B4’ to succeed in a double spend.
To achieve that, the attacker will need to have the majority of the network’s hash rate,
which is what is typically called the 51% attack10 .
Achieving this kind of hash rate and sustaining it would require extravagant amounts of
funds to accommodate for the mining hardware and operational costs and thus it would not
be easily feasible.
This is even more evident when one considers what is possible with such an attack: po-
tential censorship and double spends. Even with such an attack the funds on all the Bitcoin
addresses are safe as is the historical records of the transactions; the former are secured by
strong cryptography while the latter would require much more hash rate to modify them.
Bitcoin security model is based on game theory principles and proper incentives. Eco-
nomically speaking only a very irrational entity would make such an attack since setting up
the environment for the attack would position the attacker in a very economically advanta-
geous position, i.e. they will be earning a lot of money with the mined bitcoins.
Even though Bitcoin and Nakamoto Consensus provide us with some of the strongest
probabilistic guarantees it is theoretically possible to be influenced by malevolent ac-
tors.
Until now the network had been extremely resilient to any kind of attack and has proven
its robustness and stability securing hundreds of billions worth of value. The Bitcoin blockchain
is considered by many as the most immutable structure constructed by humans.
After installing the Bitcoin software11 we can notice that it includes several executables, one
providing the core functionality and the other for interaction and extra utility:
bitcoind: The daemon server that implements the Bitcoin protocol and networking func-
tionality. It also includes a wallet. It provides a JSON-RPC API to talk to the node
(ports: mainnet: 8332, testnet: 18332, regtest: 18443, sigtest: 38332).
bitcoin-qt Provides a graphical user interface to the Bitcoin peer and wallet (subset of the
API as part of GUI but also provides a console for all calls).
testnet=1 The Bitcoin node uses the testnet network for development (i.e. fake funds). If
the option is missing or if it is ‘0’ then mainnet (the real network) is used.
regtest=1 This is a local test environment. The blockchain starts at height 0 (genesis block)
and we can trivially mine new blocks with the generatetoaddress command. This
allows developers to also control the block creation and get fake funds immediately.
Regtest uses testnet’s network parameters (e.g. address prefixes, etc).
signet=1 New test network for development that adds an additional signature requirement
for block validation. Signet is similar in nature to testnet, but more reliable and cen-
trally controlled. Anyone can run their own unique signet for their testing purposes.
Available from Bitcoin Core v0.21.0.
prune=1000 Only keep more recent blocks that fit in 1000 MiB. Pruning is not compatible
with txindex and rescan.
mempoolsize=100 Only keep transactions that fit in 100 MiB. Transactions are ordered by
fee rate and if there is not enough space the ones with the lowest fee rate are removed.
We can also include sections like main, test and regtest to provide specific options de-
pending on the network used. Usually, when optioins are not specified under a section they
apply to all sections with the exception of addnode, connect, port, bind, rpcport, rpcbind
and wallet.
A typical minimalistic config for development is:
daemon =1
testnet =1
#regtest =1
server =1
rpcuser=kostas
rpcpassword= toodifficulttoguess
12 https://developer.bitcoin.org/examples/testing.html
Chapter 1. How Bitcoin Works 21
[main]
mempoolsize =300
[test]
mempoolsize =100
[regtest]
mempoolsize =20
After version 0.22 a bitcoin wallet is not created by default. We have to create one our-
selves. We can create a default wallet with:
The default wallet is a descriptor wallet (see chapter 5 for more on descriptor wallets). To
use commands like importaddress and dumpprivkey a non-descriptor wallet needs to be
created:
By default Bitcoin v0.20+ use bech32 (or native segwit) addresses. The example above over-
rides the default. We will examine the different kind of Bitcoin addresses in Chapter 5.
14 You can check the transaction online using a Bitcoin testnet block explorer:
https://blockstream.info/testnet/tx/ff8322626c21c5bdfa1d27f75a55a1cb1d3b764bb34063f64b38f0803c370c08
Chapter 1. How Bitcoin Works 25
To get more information for the status of your node you can use commands like: get-
blockchaininfo, getmempoolinfo, gettxoutsetinfo, getmemoryinfo, getrpcinfo, getmining-
info, getnetworkinfo, getpeerinfo, getdescriptorinfo, getaddressinfo, getwalletinfo.
1.9 Exercises
Exercise 1.3 Use a Bitcoin testnet faucet to get some testnet bitcoins (tBTC) to one of
your addresses.
Exercise 1.4 Ask your classmates or friends for their testnet address and send them
some tBTC using bitcoin-cli.
Exercise 1.5 Use a block explorer to see the status of the transaction that you created
in the previous exercise.
Exercise 1.7 Go through the rest of the API and get familiar with more commands.
Exercise 1.8 Search for historical data on Bitcoin’s difficulty adjustments and make
sure you understand what you see.
2. P2P Networking in a nutshell
2.1 Introduction 27
This chapter aims to introduce the very basics of the Bitcoin Peer-to-Peer networking, dis-
cussing peer (or node) discovery, blockchain synchronisation and others.
2.1 Introduction
A Bitcoin full node serves several functions to the network.
• Wallet
• Miner
By default most nodes will have a wallet (irrespectively of its use1 ) and will be able to
propagate information through the network. By default they are also archival nodes, i.e. they
keep the complete list of all blocks from genesis. However, lately, some nodes opt to prune
the size of the blockchain for storage purposes2 . Finally, only a few of those will provide
mining services.
In November 2022 there were around 14663 nodes3 in the network with ~99.9% of them
using the Bitcoin Core implementation while the rest consists of alternatives like Bcoin, Bit-
coin Unlimited, Bitcoin ABC, etc. A significant number of nodes (~53%) were using the Tor
network4 . With regard to mining there were 15 known mining pools5 and other unknown
ones corresponding to the mining Tor nodes.
1 Wallet functionality can be disabled with disablewallet=1 in bitcoin.conf. After v0.22 a wallet is not cre-
ated by default.
2 This is accomplished by specifying, say, prone=1000 in bitcoin.conf to keep only the latest 1000 MiB of
blocks
3 https://bitnodes.io/
4 https://www.torproject.org/
5 https://www.blockchain.com/charts/pools
27
28 2.2. Peer Discovery
DNS seeds: A list of (hardcoded) DNS servers that return a random subset of bitcoin node
addresses. It sends a getaddr network message to those peers to get more bitcoin ad-
dresses and so forth. The peers reply with an addr message that contains the addresses.
The node can be configured to use a specific DNS seed overriding the defaults by using
the -dnsseed command-line option.
Seed nodes: A list of (hardcoded) node IP addresses from peers that are believed to be stable
and trustworthy. This is a fallback to DNS seeds. A specific node can be specified by
using the -seednode command-line option.
Node addresses are stored internally so the above discovery methods are only required
at first run. From then on the stored addresses can be used to remain up-to-date with active
nodes in the network.
A list of the connected peers can be acquired with the getpeerinfo command and a node
can connect to specific (trusted) peers with the connect option.
Note that the sole purpose of a relay network is to help propagate blocks fast between
interested parties (like merchants, miners). They do not replace the P2P network rather
provide additional connectivity between some nodes.
3. Forking in a nutshell
3.3 Soft-forks 31
3.4 Hard-forks 33
This chapter will look into the process of upgrading the network. It explains what forking the
blockchain means and what are the consequences.
30
Chapter 3. Forking in a nutshell 31
If the implemented rules change to a degree that the messages are not compatible with
the original rules then some peers will start rejecting some of the messages with the possi-
bility that the peer to peer network is effectively split into two networks, depending on the
kind of change that occurred; i.e. the blockchain will fork and different peers will add blocks
to different blockchains.
Since running new code might result in a network (aka chain) fork the only way to update
the Bitcoin protocol1 is by forking.
Temporary branching on the blockchain can sometimes occur and it is part of the
Nakamoto consensus. Forking refers to compatibility breaking changes between peers.
Forks can occur when nodes on the network run different versions of the software. This is
the case when the Bitcoin software is being upgraded, e.g. from core v0.11.2 to core v0.12.0.
This is a scheduled fork and if all peers agree on the change and upgrade the software in a
timely manner there will be no issues.
Alternatively, competing versions might run, e.g. Bitcoin Core v0.12.0 and Bitcoin Clas-
sic v0.12.0. The two groups will have different visions on how they wish Bitcoin to evolve
and thus compete to gain the majority of the hashing power in order for their chain to pre-
vail2 .
We can have intentional forks due to software upgrades or alternative implementations,
and unintentional forks due to incompatibilities caused by bugs.
There are two different types of blockchain forking:
Soft-forks: blocks that would be valid (to old nodes) are now invalid
Hard-forks: blocks that would be invalid (to old nodes) are now valid
3.3 Soft-forks
Blocks that would be valid are now invalid; thus new blocks created are a subset of the
possible blocks that the old rule-set would allow. Both old and new nodes will accept new
blocks. However, blocks created by old nodes will be accepted only by old nodes.
In theory, even 51% of the hashrate would be enough for the new chain since it will
consistently (over a period) have the longer chain. Since the longer chain consists of new
blocks which are valid by both old and new nodes, the old nodes will switch to the chain
consisting new node blocks; thus the blockchain itself remains compatible between all the
nodes.
Soft-forks are backward compatible; valid inputs of the new version are also valid by the
old version. They do not force old nodes to upgrade or else consider them out of consensus.
A easy to understand example would be a new rule that decreases the maximum block
size to 300kB. From now on new nodes will accept as valid only blocks that are 300kB or less.
These blocks are also valid to the old nodes so it is a soft-fork change. Since the new blocks
have the majority of the hashrate the chain will eventually consist of only 300kB blocks and
old nodes will slowly upgrade to the new rules3 .
Another example is Segwit but that involved several changes. Several sophisticated mod-
ifications were required to implement it a soft-fork; see section 6.5 for more details.
To summarize, in a typical soft-fork, the new rules do not clash with the old rules. For a
step by step example of a soft-fork and how new blocks are added on top see figure 3.1.
(i) Initially our example network has only two blocks and all nodes are in sync.
(ii) Then, a soft-fork upgrade occurs where 67% of the network uses the new rules and one
of the new nodes finds a new block. That block is accepted by everyone since new rules
are a subset of the old rules. All the nodes are still in sync.
(iii) Next, a block with the old ruleset is created. It is only accepted by old nodes and thus
we now have a temporary split.
(iv) Next another block with the new rules is found. It is accepted only by the new rules
since the chains’ tips are different. Note that the chains are now of equal size.
(v) Then yet another block with the new rules is found (67% chance!). Again, it is added
on top of the chain with an orange block on top. However, the chain with the new rules
is now the longest chain!
3 They don’t have to upgrade but their larger than 300kB blocks will never be finalized in the blockchain, so
they might as well upgrade.
Chapter 3. Forking in a nutshell 33
(vi) The old nodes are forced to follow the longest chain and thus the network is in sync
again.
The actual blockchain will always sync to the longest chain and the above mentioned
percentages have to do with the hashing rate and thus the miners. However, to other stake-
holders like users and merchants a prolonged soft-fork could prove very disruptive.
Specifically, if a merchant is using the old chain for its transactions it is possible that
their transactions are ignored when the node switches to the new nodes’ (longest) chain. In
between, that would lead to fake confirmations and potential double spends.
Typically, if hashrate is obviously leaning to one side the rest of the network nodes will
follow; miners to stop losing rewards and merchants/users to have move consistent transac-
tions.
Note that if the new nodes have 49% or less they will not be able to sustain the longest
chain and two incompatible chains will be created that cannot re-sync, leading to a temporary
hard-fork.
Whenever a longer alternative chain appears nodes have to accept it and substitute
their latest blocks up until a common parent is found with the new chain. When that
happers we say that a re-organization or reorg occured.
3.4 Hard-forks
Blocks that would be invalid are now valid; thus new blocks created are a superset of the
possible blocks that the old rule-set would allow. Neither old or new nodes will accept
blocks created from the others4 .
Irrespective of the hashing rate this will result in a chain split that will not be able to be
resolved unless one of the sides changes software.
For a step by step example of a hard-fork and how new blocks are added on top see
figure 3.2.
(i) Initially our example network has only two blocks and all nodes are in sync.
(ii) Then, a soft-fork upgrade occurs where 67% of the network uses the new rules and one
of the new nodes finds a new block. The new block is accepted only by the nodes with
the new rules and thus we have a split.
(iii) Next a block is found based on the old rules which is accepted only by the nodes run-
ning the old rules.
(iv) Finally, another block is found by the nodes running the new rules which goes on the
respective chain. The old nodes will never accept the incompatible blocks even from a
longer chain. The split is permanent.
If a hard-fork occurs the network is effectively split in two. The mining hashrate is split
in two as are the merchants and users. If one side does not change their software a hard-fork
4 Of course this assumes that the new incompatible feature is being used in that block.
34 3.4. Hard-forks
can permanently split the community in two, effectively having two separate coins from that
point onwards.
The same amount of bitcoins will exist in both chains and users will be able to access
both. Miners, users and merchants have to choose which side to support and in some cases
merchants/users can choose to support both; one of the coins will probably be termed an
altcoin and supported as such.
All transactions after the split are in danger of being rolled back (e.g. allow some users
to double-spend) if the fork resolves.
A chain fork also has potential replay attacks; signed transaction in one chain to be re-
layed on the other chain. For example, a merchant that gets some bitcoins for a product,
replays the transaction on the other chain to get the coins of the other chain as well.
BIP-34
The block version was traditionally 1. The BIP suggested that when miners want to support
a proposal they would increase the block version to signal that to others and specify in the
coinbase input the block height when the upgrade will be activated given it has enough
support. The (convention) rules were as follows:
To add a new feature a block version number (e.g. 2) would be associated with it as well
as a block height for activation.
7 https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki
8 https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki
9 https://github.com/bitcoin/bips/blob/master/bip-0008.mediawiki
36 3.5. Upgrading Bitcoin
• If 750 out 1000 blocks10 have block version of 2 then reject invalid v2 blocks (if no
block height included)
• If 950 out of 1000 blocks11 have block version of 2 then reject all block version 1 blocks
The BIPs activated with this signaling process were, BIP-32 (v2), BIP-65 (v3) and BIP-66
(v4).
BIP-9
BIP-34 allowed only one upgrade at a time and no easy way to reject a proposal to replace it
with another. BIP-9 solves these issues with the following (convention) rules:
• The remaining 29 bits of the block version field can be used to signal for 29 proposals,
potentially in parallel
• A structure is defined with:
– name
– bit, the block version bit used to signal for this change
– starttime, time (Median Time-Past12 , BIP-11313 ) when signalling can begin
– timeout, time (MTP) when change is considered rejected if not activated by then
• Threshold for activation is 95%
• Signalling is based on the whole 2016 blocks of a re-target interval
• If threshold is passed activation occurs one re-target interval later
BIP-9 was used to activate proposal “csv” that contained BIPs 66, 112 and 113 and pro-
posal “segwit” that included BIPs 141, 143 and 147. There is a list14 of all BIP-9 deployments
(both past and current ones).
The Bitcoin community opted to do only soft-fork upgrades to minimize potential dis-
uption to the network. To that end extra precautions and effort is required in the
upgrade design and implementation. A notable example is the Segregated Witness or
segwit upgrade. The latter would be easier to implement as a hard-fork but since those
are contentious they had to come up with a design that allowed the upgrade to happen
as a soft-fork.
The segwit upgrade was quite contentious and there was a lot of political agendas and
drama involved. A good walkthrough was published in Bitcoin Magazine15 and a more
detailed account of what happened is described in The Blocksize War book [2].
10 510 out of 1000 for testnet
11 750 out of 1000 for testnet
12 Timestamp of the median of the past 11 blocks.
13 https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki
14 BIP-9 was used to activate proposal “csv” that contained BIPs 66, 112 and 113. There is a list of all BIP-9
deployments (both past and current ones).
15 https://bitcoinmagazine.com/articles/long-road-segwit-how-bitcoins-biggest-protocol-upgrade-became-
reality
Chapter 3. Forking in a nutshell 37
BIP-8
This is the current BIP used for upgrading. It has the following differences from BIP-9:
• Uses block height instead of timestamps for signalling; this makes it more predictable
• Gives the option to reject or enforce the upgrade at the end of the timeout
This chapter aims to provide some basic technical computer science background required for
later material. It is of particular importance if you want to delve deeper and read the code
of the Python bitcoin-utils library1 . It aims to concisely explain some fundamental concepts
by providing examples.
1 >>> format (0, ’04b’) # converts decimal 0 to binary with 0 padding for 4 bits
2 ’0000 ’
3 >>> format (15, ’04b’) # same for decimal 15
4 ’1111 ’
5 >>> format (15, ’X’) # convert decimal 15 to hex string
6 ’F’
7 >>> format (0x41 , ’08b’) # converts hex number 41 to binary with 0 padding for
8 # 8 bits
9 ’01000001 ’
10 >>> 0x41 # converts hex number 41 to decimal
11 65
12 >>> 0x41 == ’41’ # compares hex number 41 with string 41
1 https://github.com/karask/python-bitcoin-utils
2 https://www.rapidtables.com/convert/number/binary-to-hex.html
38
Chapter 4. Technical Fundamentals 39
13 False
14 >>> b’41’ == ’41’ # compares byte literal 41 with string 41
15 False
Listing 4.1: Python examples
One byte can represent up to 28 = 256 numbers (0-255). Several bytes are needed to
represent larger numbers. For example, decimal number 1000 is 1111101000 in binary
which requires 10 bits. Computers operate at the byte level and thus 2 bytes (or 16 bits) will
be required to represent this number; binary: 0000001111101000 and hex: 03E8. Note
that the byte ordering is important and it is called endianness3 . The above example uses big-
endian ordering, where the most significant byte comes first and the least significant byte
comes last. This is the same way we order numbers in languages (in left-to-right scripts4 ).
In little-endian the same number would be represented as 1110100000000011 and E803.
Internally Bitcoin uses little-endian byte order as it improves speed (most comput-
ers use little-endian byte ordering internally). Most hash function libraries (see next
section) create hashes using big-endian and Bitcoin transmits those in that ordering.
However, when hashes are displayed Bitcoin uses little-endian order! The latter might
be because it treats them as integers to compare them faster.
As we already mentioned computers only know about binary. To display these numbers
for human consumption we need to convert them into characters (i.e. text). In order to
accomplish that we need character encodings that provide mappings between bit sequences
and characters. Examples of such encodings are ASCII and UTF-8. UTF-8 is widely used
nowadays and it provides an 8-bit mapping between (binary) numbers and characters. For
example, character A is mapped to 01000001. You can experiment with such encodings
with online tools5 .
4 >>> b’41’ == ’41’.encode(’utf -8’) # Unicode string literals are stored internally
5 # in binary for efficiency
6 True
7 >>> ’ε ’.encode () # UTF -8 (the default) is a variable lenth
8 # encoding - ’ε ’ is stored as two bytes
9 b’\xce\xb5’
10 >>> ’41’.encode () # converts UTF -8 string literal 41 to binary -
11 # ’4’ and ’1’ occupy 1 byte each
12 b’41’
13 >>> binascii.unhexlify(’41’) # converts string hex value 41 to binary -
14 # the UTF -8 value for ’A’ is 0x41
15 b’A’
16 >>> b’A’ == b’\x41’ # the bytes from 0x01 to 0x7f are confusingly
17 # specified with UTF -8 characters
18 True
19 >>> b’41’ == b’\x34\x31’ # similarly for binary characters b ’4’ and
20 # b ’1’ or b ’41’
21 True
22 >>> b’A’.decode(’utf -8’) # convert binary to characters for displaying
23 # according to UTF -8 encoding
24 ’A’
25 >>> binascii.hexlify(b’A’) # convert binary value to hex value (expressed
26 # in binary)
27 b’41’
28 >>> b’41’.decode () # decode to get as string (UTF -8 is the default)
29 ’41’
30 >>> b’\xce\xb5’.decode () # convert from bytes to UTF -8 characters (0xce
31 # 0xb5 maps to ’ε ’)
32 ’ε ’
Listing 4.3: Python examples
• it is deterministic, i.e. the same block of data always returns the same hash
• it is quick to compute
• it is an one-way function; given the hash one cannot derive the original value unless
they brute-force all possible values (which is close to impossible for large data sets)
• even a trivial change to the original data will change the resulting hash completely (it
will appear uncorrelated to the previous hash)
Cryptographic hash functions are very important in information security systems. They
are used in digital signatures, message authentication codes and as ordinary (but more se-
cure) hash functions to index data in hash tables, to uniquely identify files (bittorrent, IPFS),
as checksums to detect accidental (or not) corruption of data, etc.
Bitcoin is using two hashing functions: SHA-256 and RIPEMD-160 which create a hash
value of 256 and 160 bits respectively (or 32 and 20 bytes or 64 and 40 hex characters).
• Encryption: Alice can encrypt a message with Bob’s public key and send it to Bob.
Only the owner of the corresponding private key can decrypt and view the message.
• Authentication / Digital Signatures: Alice can sign a message using her private key
and send it to Bob. Anyone can view the contents and verify the signature using Alice’s
public key, thus ensuring that it was indeed Alice that send the message.
6 https://en.wikipedia.org/wiki/Public-key_cryptography
42 4.3. Asymmetric Cryptography
• Integrity: While anyone can view the contents of a signed message no one can modify
it since the signature will be invalidated.
Bitcoin does not use encryption at all. Digital signatures are used to sign transactions
in order to authenticate that you are the owner of the coins you wish to transfer. In-
tegrity and non-repudiation also apply to transaction signing.
There are several different algorithms for asymmetric cryptography, like RSA and ECDSA.
ECDSA, which Bitcoin uses, has the property that a private key can be used to calculate the
corresponding public key.
5. Keys and Addresses
5.3 Addresses 47
5.4 Wallets 51
5.6 Exercises 53
In this chapter we introduce Bitcoin’s keys and addresses and describe how they are created
and the rationale behind that process. We then go through different wallet types and how
these keys can be used in practice.
In ECDSA a private key can be used to calculate the corresponding public key, and
since a Bitcoin address is calculated from the public key, if you hold a private key
securely you effectively have everything.
The ECDSA private key in Bitcoin is just a very large random number consisting of 256
bits or 32 bytes or 64 hexadecimal digits. Nearly all 256-bit numbers can be valid private
keys as specified in secp256k1.
To display a private key (the bytes) we need to format it appropriately. It could be dis-
played in hex but the most common format used to display a private key is Wallet Import
Format (WIF) or WIF-compressed (WIFC); both are a Base58Check3 encoding of the ECDSA
key; Base584 with a version prefix to specify the network and a 32-bit checksum.
A WIF-compressed adds an extra byte (0x01) at the end of the ECDSA key before the
Base58Check encoding. It specifies whether the public key (and by extension addresses)
will be compressed or not. By default most wallets use WIFC format in order to reduce the
size of the blockchain5 .
1 https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm
2 https://en.bitcoin.it/wiki/Secp256k1
3 https://en.bitcoin.it/wiki/Base58Check_encoding
4 https://en.wikipedia.org/wiki/Base58
5 Note that the segregated witness upgrade allows only compressed public keys.
43
44 5.1. Private Keys
The WIFC will be 33 bytes long. The compression is happening when creating the
public key which will be 33 bytes instead of 65 bytes.
The following is pseudocode of the process that converts the private key to WIF.
Note that all the above functions operate on big-endian bytes. The network prefix spec-
ifies the Bitcoin network that this private key would be used6 . The Base58 WIF prefix de-
pends on the network prefix and whether it is compressed or not, as shown in table 5.1.
Mainnet Testnet
ECDSA HEX 64 digits number 64 digits number
ECDSA HEX-C Above number + “01” Above number + “01”
Network Prefix Base58 Prefix Network Prefix Base58 Prefix
WIF 128 | 0x80 5 239 | 0xef 9
WIF-C 128 | 0x80 K or L 239 | 0xef c
0dde70823a4bb0ca3bd75a2010e8d5dc091185e73d8b4257a981c695a3eba95b
You can now consult table 5.2 for its compressed version and the corresponding WIF and
WIF-C.
HEX 0dde70823a4bb0ca3bd75a2010e8d5dc091185e73d8b4257a981c695a3eba95b
HEX-C 0dde70823a4bb0ca3bd75a2010e8d5dc091185e73d8b4257a981c695a3eba95b01
WIF 91h2ReUJRwJhTNd828zhc8RRVMU4krX9q3LNi4nVfiVwkMPfA9p
WIF-C cN3fHnPVw4h7ZQSRz2HgE3ko69LTaZa5y3JWpFhoXtAke4MiqVQo
Let’s use the bitcoin-utils library to construct the WIF and WIFC.
The actual Python implementation of the functionality demonstrated above can be found
at to_wif()8 on github. You can also check how we can get to the private key bytes from
WIF in _from_wif()9 . Feel free to consult the rest of the code and/or the examples in the
repository.
Another tool that you can use from the command line is BX10 . It has extensive capabilities
including creating WIFs.
The public key is a point P in the elliptic curve. P = (x, y), where both x and y are 32-byte
integers. Thus a public key can be expressed with 64 bytes. In Bitcoin, we encode a public
key by a prefix that specifies some extra information.
Remember that we can represent a public key in two forms, compressed and uncom-
pressed. This is where we can reduce the size of the blockchain by using the com-
pressed form.
An encoded uncompressed public key is 65 bytes long since it has the two points (32
bytes each) concatenated and a prefix of 0x04 to specify an uncompressed public key.
Since the curve is mirrored in the x axis the y coordinate can only take 2 values for a
specific x (positive/negative). Thus, an encoded compressed public key is only 33 bytes long
and has only the x coordinate with a prefix of 0x02 (when y is positive/even) or 0x03 (when
y is negative/odd).
Let’s use the bitcoin-utils library to construct a private key object from a WIF and use
that to create a public key object to show its two forms.
11 addc4cbba6656a4be4bc6933a6af712b897a543a09c4b899e5f7b943d38108a8 ’
Listing 5.2: Python example to generate compressed and uncompressed public keys
You can see in lines 10-11 in listing 5.2 that the uncompressed public key has the same x
coordinate as the compressed one plus the y coordinate.
To create the PublicKey from the PrivateKey object we make use14 of the Python ECDSA
library as can be seen in get_public_key() on github15 . The PublicKey object holds the x
and y coordinates and can convert accordingly. It checks if y is even or odd and prefixes it
with 0x02 and 0x03 respectively. You can check the code of to_hex() on github16 .
We can get the public keys from the private keys using BX again.
5.3 Addresses
Addresses can be shared to anyone who wants to sent you money. They are typically gener-
ated from the public key, consist of a sequence of characters and digits and start with 1 for
the mainnet and with m or n for testnet17 .
An address typically represents the owner of a private/public pair but it can also repre-
sent a more complex script as we will see in a future chapter.
Notice that we do not share the public key as one would expect in public key cryptogra-
phy but rather the address, which is derived from the public key. Some benefits are:
• shorter addresses
• quantum computer resistance
Until one spends from an address the public key will never appear on the blockchain
and thus to potential attackers and since the address is hashed from the public key not
even quantum computers could brute force to get the public key and then the private
key. Note, however, that even if that is the case the majority of addresses would be
hacked thus destroying trust in (and the value of) the network anyway!
14 It is always recommended to reuse well-tested cryptography libraries than implementing your own.
15 https://github.com/karask/python-bitcoin-utils/blob/fb0849f81117943563b17f1870a9607d48ca9653/
bitcoinutils/keys.py\#L351-L355
16 https://github.com/karask/python-bitcoin-utils/blob/fb0849f81117943563b17f1870a9607d48ca9653/
bitcoinutils/keys.py\#L453-L469
17 Or for segwit addresses bc1 and tb1 for mainnet and testnet respectively.
48 5.3. Addresses
Legacy Addresses
An address is really just the hash of the public key, called public key hash (or PKH). That
is how it is represented on the blockchain. The way we format addresses to display them
(starting with 1, m/n, etc.) are just for our convenience. The format that we use is the
Base58Check encoding of the public key hash; Base58 with version prefix to specify the
network and a 32-bit checksum.
The following is pseudocode of the process that converts the public key to public key
hash and then address:
n e t w o r k _ p r e f i x = ( 1 byte v e r s i o n number )
keyHash = RIPEMD−160( SHA−256( publicKey ) )
data = n e t w o r k _ p r e f i x + keyHash
dataHash = SHA−256( SHA−256( data ) )
checksum = ( f i r s t 4 b y t e s o f dataHash )
a d d r e s s = Base58CheckEncode ( data + checksum )
Note that all the above functions operate on big-endian bytes. The network prefix speci-
fies the Bitcoin network that this private key would be used. The Base58 WIF prefix depends
on the network prefix and whether it is compressed or not, as shown in table 5.3.
Mainnet Testnet
Network Prefix Base58 Prefix Network Prefix Base58 Prefix
P2PKH 0 | 0x00 1 111 | 0x6f m or n
P2SH 5 | 0x05 3 196 | 0xc4 2
P2PKH stands for Pay to Public Key Hash and is the typical legacy address. P2SH stands
for Pay to Script Hash and is the typical legacy script hash address; an address that is pro-
tected with an arbitrary script rather than just a private-public key pair as in the P2PKH
case.
Let’s use the bitcoin-utils library to construct some addresses; compressed and uncom-
pressed.
Since the hash of a compressed public key would be different from the hash of an
uncompressed public key we have two distinct legacy addresses.
The actual Python implepmentation of converting a public key hash (the application of
SHA256 and then RIPEMD160, also called HASH160) can be found at _to_hash160() on
github18 . For code to convert from public key hash to address consult to_string()19 . Feel
free to consult the rest of the code and/or the examples in the repository for segwit address
creation, etc.
Effectively you could nest or wrap a segwit address into a P2SH address. As already
mentioned P2SH addresses can be created from arbitrary scripts and thus could also include
a witness script. Again, P2SH and segwit are outside our scope for now and will be explained
in more detail in section 6.5.
After the segwit upgrade one needs to choose the type of address to create (e.g. when
using getnewaddress). The supported types where legacy, p2sh-segwit and bech32.
The default, starting from version 0.16.0, was nested segwit addresses (p2sh-segwit)
and from version 0.19 onwards the default is segwit addresses (bech32). The default
can be changed in the configuration using addresstype.
Vanity Addresses
These are normal addresses that contain a specific string. They are calculated randomly by
creating random private keys and then checking if the corresponding address starts with
that string, e.g. 1KK.
1 import random
2 from bitcoinutils.setup import setup
3 from bitcoinutils.keys import PrivateKey
4
5 setup(’mainnet ’)
6
7 vanity_string = ’1KK’
8 found = False
9 attempts = 0
10
11 while(not found ):
12 p = PrivateKey( secret_exponent = random.getrandbits (256))
13 a = p.get_public_key (). get_address ()
14 print(’.’, end=’’, flush=True)
15 attempts += 1
16 if(a.to_string (). startswith(vanity_string )):
17 found = True
18
19 print("\nAttempts: {}".format(attempts ))
20 print("Address: {}".format(a.to_string ()))
21 print("Secret Key: {}".format(p.to_wif ()))
Listing 5.5: Example of creating a vanity address using Python
You will notice that it takes some time even for a short string. Legacy addresses always
start with 1 so we can disregard that. Since addresses use base58 each character will take
an average of 58 attempts to be found. The next character an additional 58 attempts (thus
58 ∗ 58). We can generalize with 58n where n is the number of characters the vanity address
should start with.
There are efficient implementations for calculating vanity addresses in C, Go, Rust or
other compiled system languages that will calculate much faster than our simple example
above, but still to create a vanity address that starts with 1Kostas will require 38,068,692,544
attempts (586 ). That will take considerable time regardless of the efficiency of the program
or the hardware used.
Chapter 5. Keys and Addresses 51
In practice, these large vanity addresses are created via vanity address pools. Such pools
have specialized hardware (i.e. mining hardware) that can create vanity addresses fast, albeit
for a fee. However, how can they send you your private key that corresponds to the vanity
address without them knowing it?
A+B will produce the public key of the a+b private key.
Consider that Alice wants to use a pool operated by Bob to get a vanity address. Fig-
ure 5.2 illustrates the process to securely get to the private key that corresponds to the vanity
address.
Figure 5.2: Example of how a vanity address pool securely shares the private key to a user.
• First Alice creates a key pair and sends the public key A to Bob.
• Bob creates a key pair and adds the new public key B1 to Alice’s key. Then uses the
resulting public key to generate an address. If this address does not match the vanity
string required by Alice, it repeats the process by creating another key pair, and so on.
When a match is found the respective private key, e.g. b9, is send to Alice.
• Now Alice, and only Alice, can construct a private key that corresponds to the vanity
address by adding it to her private key.
5.4 Wallets
A wallet is software that allows us to manage the private and public keys as well as our
Bitcoin addresses. They usually have functionality to send bitcoins, check balances, create
52 5.5. More examples
contact lists and other. Usually a key (i.e. address) is used only once. Depending on how the
private keys are handled there are two types of wallets:
Non-deterministic All the private keys on the wallet are just randomly generated. Several
private keys are pre-generated and new keys are created if needed. If you backup your
wallet and then create new keys, you will need to backup your wallet again.
Deterministic A seed is used to create a master private key, which can be used to create all
other private keys (thus public keys and addresses as well). If you backup your seed
you are safe no matter how many keys you use since all can be generated from the seed.
Nowadays, most wallets are Hierarchical Deterministic (HD) since they offer more flexi-
bility, easier backups and enchanced security in certain use cases. HD wallets are described
in detail in Bitcoin Improvement Proposals (BIPs) 3223 , 4324 and 4425 .
23 https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
24 https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki
25 https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
Chapter 5. Keys and Addresses 53
We verify using the address instead of the public key. In ECDSA cryptography the
public key can be reconstructed given the signature and the public key hash (or ad-
dress).
5.6 Exercises
Exercise 5.1 Describe possible outcomes of mistyping a Bitcoin address when trying
to send some bitcoins.
Exercise 5.3 Use Python and the bitcoin-utils library to create a simple vanity gener-
ator.
Exercise 5.4 Write a function that creates a Bitcoin address given a public key. The
only Python libraries that you are allowed to use are hashlib for the hashing algo-
rithms and binascii to convert between hexadecimal and bytes.
Exercise 5.5 Create and display a P2SH address than contain a P2PK script using any
random private key.
6. Scripting 1
6.1 Transactions 54
6.3 Signatures 63
6.8 Exercises 79
This chapter goes deeper into what constitutes a transaction and how scripting is used to lock
bitcoins and later unlock them to spend them. Several examples are provided on how to create
transactions by calling a node’s API or programmatically.
6.1 Transactions
A transaction sends bitcoins from one address to another and it consists of 1+ inputs and 1+
outputs. The inputs of a transaction consist of outputs of previous transactions. When an
output is spend it can never be used again1 . All the bitcoins are transferred elsewhere (to a
recipient, back to yourself as change, etc.). Outputs that are available to be spend are called
Unspent Transaction Outputs (UTXOs) and Bitcoin nodes keep track of the complete UTXO
set.
Each time funds are sent to an address a new output (UTXO) is created. Thus, the
balance of an address depends on all the UTXOs that correspond to it. Bitcoin wal-
lets hide UTXOs to make the whole experience friendlier but some wallets allow you
to specify which UTXOs you want to spend if needed. When we create transactions
programmatically we will deal primarily with UTXOs.
When an output (UTXO) is created we also specify the conditions under which this out-
put can be spend. When you specify an input (the UTXO of a previous transaction) to spend
from you have to prove that you satisfy the conditions set by the UTXO.
The spending conditions and the proof that authorizes transfer are not fixed. A scripting
language is used to define them. When a new output is created a script is placed in the
UTXO called scriptPubKey or more informally locking script.
When we want to spend that UTXO we create a new transaction with an input that refer-
ences the UTXO that we wish to spend together with an unlocking script or more formally a
scriptSig.
1 Think of cash. If you give a 20 euro note you can never reuse it. You might be given change but it will be
different notes or coins.
54
Chapter 6. Scripting 1 55
The standard transaction output types supported by the Bitcoin protocol are:
The most common transaction output type offering a standard way of transferring bit-
coins around is P2PKH (and P2WPKH), which is effectively “pay to a Bitcoin address”. It
is also possible, and used in the past, to pay directly to a public key with P2PK but that is
not used anymore. Another very important transaction output type is P2SH (and P2WSH)
which allows locking scripts of arbitrary complexity to be used.
To define a locking and unlocking script we make use of a scripting language, simply
called Script3 . This relatively simple language consists of several operations each of them
identified by an opcode in hexadecimal. It is a simple stack-based language that uses re-
verse polish notation (e.g. 2 3 +) and does not contain potentially dangerous programming
constructs, like loops; it is a domain-specific language.
P2PKH
Let’s examine the standard transaction of spending a Pay to Public Key Hash. The locking
script (scriptPubKey) that secures the funds in a P2PKH address is the following:
As we have seen in section 5.3 the public key hash (PKHash) can be derived from the
Bitcoin address and vice versa. Thus, the above script locks the funds that have been sent in
the address that corresponds to that PKHash.
To spend the funds the owner of the private key that corresponds to that address/PKHash
needs to provide an unlocking script that if we prepend to the locking script the whole script
will evaluate to true. An unlocking script for a P2PKH will look like this:
2 Valid non-standard transactions (containing scripts other than those defined by the standard transaction
output type scripts) are rejected and not relayed by nodes. However, they can be mined if it is arranged with a
miner.
3 https://en.bitcoin.it/wiki/Script
56 6.1. Transactions
<Signature> <PublicKey>
Using the private key we provide an ECDSA signature of part of the transaction that
we create (see section 6.3 for more details). We also provide the public key4 for additional
verification.
The validation to spend a UTXO consists of running the script of scriptSig plus script-
PubKey. Both scripts are added in the stack and executed as one script.
4 As we have already discussed in section 5.3 the public key only appears in the blockchain after we spend
from an address. This is where it appears!
Chapter 6. Scripting 1 57
Step 6: Next element is an operator that checks if the top two elements of the stack are equal
and fails the script if they are not. Effectively this validates that the public key provided is
indeed the one that corresponds to the PKH (or address) that we are trying to spend.
<Signature> <PublicKey> OP_DUP
OP_HASH160 <PKHash> <Signature> <PublicKey>
OP_EQUALVERIFY OP_CHECKSIG
Step 7: Next element is an operator that expects two elements from the stack; a signature
and a public key that corresponds to that signature. If the signature is valid it returns true,
otherwise false.
<Signature> <PublicKey> OP_DUP
OP_HASH160 <PKHash> OP_TRUE
OP_EQUALVERIFY OP_CHECKSIG
Since the script finished and the only element in the stack is now OP_TRUE5 the node
validated ownership of the UTXO and it is allowed to be spent. Success!
To help clarify how addresses, locking scripts and UTXOs relate please see figure 6.1.
Addresses 1Zed, 1Alice and 1Bob are short for the actual bitcoin addresses of Zed, Alice and
Bob respectively. The diagram emphasises what happens when funds are sent to an address.
This section explained how funds residing in UTXOs are locked/unlocked and how scripts
are evaluated for validation. In the next section we will go through several examples of how
we can create simple transactions programmatically.
In this example we use the node to send 0.1 bitcoins to a testnet address. Notice that
we do not specify any details on which UTXOs to spend from. The node wallet will decide
which UTXOs it will spend and in which address the change (there is almost always change)
will go; i.e. we do not have any control when sending funds this way.
Notice that the result is the transaction identifier (txid) of this transaction.
The above command lists all UTXOs (even those with 0 confirmations; i.e. in the mem-
pool). Now we can create a transaction specifying the UTXO that we want to spend.
The result is the serialized raw transaction in hexadecimal. Note that this is not signed
yet. To see the details of the raw transaction we can use:
We can confirm that this is unsigned because the unlocking script or scriptSig is empty.
We now need to sign this transaction before it becames a valid transaction.
60 6.2. Creating P2PKH Transactions
Now we have the final signed raw transaction (in attribute hex). If we use decoderaw-
transaction now you will see the unlocking script is properly set. We can test if this is a
valid transaction before sending it to the node for broadcasting with the mempoolaccept
command. Finally, we need to send it to the node for broadcasting.
In this instance we get an error saying that the transaction has an exceptionally high fee.
We have not specified any output for change so 1.1 bitcoins would be given to miners (1.3-
0.2). Most wallets have similar protection mechanisms to help safeguard from user errors.
rpcuser=kostas
rpcpassword=too_long_to_guess
Then we could use a tool like curl to make the JSON-RPC request:
$ curl --user kostas --data -binary ’{" jsonrpc ": "1.0" , "id":" curltest", \\
"method ": "getblockcount", "params ": [] }’ -H ’content -type: text/plain;’\\
http ://127.0.0.1:18332/
Enter host password for user ’kostas ’:
{
"result": 1746817 ,
"error": null ,
"id": "curltest"
}
Chapter 6. Scripting 1 61
Thus, we can also send the commands seen before to construct transactions via JSON-
RPC.
All API calls can be used, including the ones to create a transaction with either send-
toaddress or createrawtransaction + signrawtransaction + sendrawtransaction.
6 The library can be installed directly with pip install bitcoin-utils in your working Python environment
7 https://github.com/jgarzik/python-bitcoinrpc
8 https://github.com/karask/python-bitcoin-utils/blob/b31c82e7005e06db7f780688cfcd9332d479f39d/
examples/p2pkh_transaction.py
62 6.2. Creating P2PKH Transactions
This produces the serialized raw transaction in hexadecimal. We can then use sendraw-
transaction to broadcast this to the Bitcoin network. Notice that the transaction identifier
Chapter 6. Scripting 1 63
used to create the input is hardcoded for simplicity; in an actual program we would call
listunspent to find the available UTXOs.
6.3 Signatures
In this section we will explain how and what needs to be signed to prove ownership of funds
residing in specific addresses.
When we create a new transaction we need to provide a signature for each UTXO that we
want to spent. For a P2PKH UTXO the signature proves:
The digital signature algorithm used is ECDSA and each signature is serialized using
DER. There are different ways to sign inputs of a transaction so as to provide different com-
mitments. For example: “I agree to spend this input and sign it as long as no one can change
the outputs I specified”. To specify these commitments, i.e. which parts of the transaction
will be signed, we add a special 1 byte flag called SIGHASH at the end of the DER signature.
Each transaction input needs to be signed separately from others. Parts of the new trans-
action will be hashed to create a digest and the digest is what is signed and included in the
unlocking script. To determine which parts are hashed the following rules are followed:
ALL (0x01) Signs all the inputs and outputs, protecting everything except the signature
scripts against modification. This transaction is final and no one can modify it without
invalidating this signature.
NONE (0x02) Signs all of the inputs but none of the outputs, allowing anyone to change
where the satoshis are going. A miner will always be able to send the funds to his
address. It can also be used to send funds somewhere as long as everybody else also
sends funds; in this case it is assumed that one of the signers will use SIGHASH ALL
(or SINGLE) to lock the outputs before broadcasting. It can be used as a blank check to
a miner.
SINGLE (0x03) Sign all the inputs and only one output, the one corresponding to this input
(the output with the same output index number as this input), ensuring nobody can
change your part of the transaction but allowing other signers to change their part
of the transaction. The corresponding output must exist. It can be used if someone
creates a transaction with some inputs that they cannot spend and specific outputs
and then send to other participants, one of which will to sign (with ALL or SINGLE), if
they agree. A concrete example is provided later in this section.
64 6.3. Signatures
ALL|ANYONECANPAY (0x81) Signs only this one input and all the outputs. It allows anyone
to add or remove inputs, so anyone can contribute additional satoshis but they cannot
change how many satoshis are sent not where they go. It can be used to implement
kickstarter-style crowdfunding.
NONE|ANYONECANPAY (0x82) Signs only this one input and allows anyone to add or re-
move other inputs or outputs, so anyone who gets a copy of this input can spend it
however they like. This input can be spend even in another transaction!
SINGLE|ANYONECANPAY (0x83) Signs this one input and its corresponding output. Al-
lows anyone to add or remove other inputs. A potential use would be as a means to
exchange colored coin9 tokens with satoshis. For example, one can create a transaction
that has an input which holds 10 of their tokens and an output of 10 million satoshis
to an address that they own. This transaction would be invalid since the inputs do
not provide the 10 million satoshis but it can be shared with others. If someone wants
to claim the 10 tokens they can add an input with at least 10 million satoshis and an
output that sends the 10 tokens to them. This would complete the transaction which
can then be broadcasted.
Figure 6.2: Example transaction with two inputs and two outputs.
For an example of SINGLE, consider creating the transaction shown above. Alice needs to
pay 1.5 bitcoins to Zed and they agreed with Bob that he will contribute 0.5 of that amount.
Then Alice creates a transaction with two inputs, UTXO1 that she owns (with 1 BTC) and
UTXO2 that Bob owns (with 1 BTC) and a single output that sends 1.5 bitcoins to Zed. She
signed UTXO1 with SIGHASH SINGLE and sends the incomplete transaction to Bob. Bob
cannot choose a UTXO other than UTXO2 since it will invalidate Alice’s signature of UTXO1.
However, he is free to add other outputs so he creates an output that sends the remaining
bitcoins (he agreed to pay only 0.5) to one of his addresses. He can then sign UTXO2 with
SIGHASH ALL which will effectively finalize the transaction10 . Note that:
• The sequence numbers of other inputs are not included in the signature, and can be
updated.
• As already demonstrated above, with multiple inputs, each signature hash type can
sign different parts of the transaction. If a 2-input transaction has one input signed
with NONE and the other with ALL, the ALL signer can choose where to spend the
funds without consulting the NONE signer.
9 https://en.bitcoin.it/wiki/Colored_Coins
10 No more input or output changes are allowed without invalidating this signature.
Chapter 6. Scripting 1 65
This section explains the rationale behind Pay to Script Hash (P2SH) type of addresses and
demonstrates with code.
2 <Director ’s Public Key > <CFO ’s Public Key > <COO ’s Public Key >
3 CHECKMULTISIG
Indeed, this is the locking script of the multisignature standard transaction output type.
If someone needs to send money (lock funds) to that output script then they need to know
it! The company would need to send this script to all their customers that wish to pay them.
This is not practical since the whole script is recorded on the blockchain for every trans-
action and more importantly has privacy issues; the company is revealing the public keys
that control the funds.
If you think about it the precise locking/unlocking script of the funds should not concern
the customers at all. Only the company should know how to spend them.
11 https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki
66 6.4. Pay to script hash (P2SH)
RIPEMD -160( SHA -256( 2 <Director ’s Public Key > <CFO ’s Public Key >
<COO ’s Public Key > 3 CHECKMULTISIG ) )
Using this hash we create a Bitcoin address (same process as described in section 5.3 but
instead of OP_HASH160(pubkey) we use OP_HASH160(redeem script)) using the version
prefix of 0x05 that creates addresses that start with 3.
We then only need to disseminate this address to the company’s customers. They can
send funds oblivious to how these funds are locked. The company knows how they are
unlocked so they can prepare the appropriate unlocking script.
As an example, to spend the funds, the company can create the following script:
It has two parts, the redeem script’s unlocking conditions (which in this case are two of
the signatures) plus the redeem script. Notice how the redeem script is revealed only when
the company spends the funds; and it only reveals the two signatures, not all three.
Validation occurs in the following steps:
Initially, the scriptSig part is pushed into the stack and then the stack is copied for later
use. The copy would look like:
If the hashed redeem script is equal to the 20-byte hash value the above script will result
OP_TRUE in the top of the stack, which validates that the correct redeem script was passed.
We can now proceed in validating the actual redeem script. We do this by using the copy of
the stack, by first deserializing the top element (redeem script) and then executing normally:
Chapter 6. Scripting 1 67
Summary / Advantages
P2SH moves the responsibility for supplying the conditions to redeem a transaction (locking
script) from the sender of the funds to the redeemer (receiver).
• P2SH allows us to create arbitrary redeem scripts; we can thus create quite complex
scripts and not be limited to the few standard transaction output types.
• Reduces the size of the funding transactions typically resulting in saving blockchain
sace.
28 print(addr.to_string ())
29
30 if __name__ == "__main__":
31 main ()
43
44 # print raw signed transaction ready to be broadcasted
45 print("\nRaw signed transaction :\n" + signed_tx)
46 print("\nTxId:", tx.get_txid ())
47
48
49 if __name__ == "__main__":
50 main ()
As already mentioned, the first time we spend from the address, i.e. broadcasting this
transaction, reveals the redeem script to everyone.
Figure 6.3: Example transaction with (i) a non-segwit input and (ii) a segwit input.
The segwit upgrade is described in detail in BIPs12 141, 143, 144 and 145 and it provides
several benefits13 . We will examine two of them here: transaction malleability and effective
block size increase.
12 Bitcoin Improvement Proposals
13 https://bitcoincore.org/en/2016/01/26/segwit-benefits/
70 6.5. Segregated Witness (SegWit)
Transaction malleability
Each transaction is uniquely identified by its transaction identifier or txid. The txid is con-
structed by hashing14 the serialized transaction (the blue part of figure 6.3).
It is possible to slightly change the unlocking script, e.g. by a miner, so as the resulting
transaction is semantically identical to the original; thus still valid. This can be accom-
plished, for example, by slightly changing the structure of the signature15 .
That is a problem because given how the txid is created even the slightest modification
will change the txid. While the transaction is identical, i.e. funds will be moved exactly
as intended, our ability to monitor this transaction is problematic given that we will be
checking for confirmations in a txid that is not valid anymore.
With segwit inputs, however, the unlocking script (the green part of figure 6.3 (ii) ) is not
part of the txid construction and thus it is impossible to modify it. A non-malleable txid is
more reliable and allows for more advanced scripts/solutions like the lightning network.
where the pubkey-hash is substituted with the witness program. Note that this is used
for calculating the digest and not for validation (see next section).
P2WPKH
In segwit version 0, a P2WPKH witness program is just the 20-byte public key hash. The un-
locking script (scriptSig) should be empty and the script witness (or just witness18 ) contains
the unlocking script.
scriptPubKey: 0 6 b85f9a17492c691c1d861cc1c722ff683b27f5a
scriptSig:
witness: <signature > <pubkey >
P2WSH
In segwit version 0, a P2WSH witness program is just the 32-byte script hash. The unlocking
script (scriptSig) should be empty and the witness contains the script that unlocks the funds
as well as the witness script19 .
1. The ‘0’ in scriptPubKey specifies that the following is a version 0 witness program.
2. The length of the witness program (32-bytes) indicates that it is a P2WSH type.
3. The witness must consist of the unlocking script followed by the witness script)
4. The SHA256 of the witness script must match the 32-bytes witness program
5. Finally, the witness script is deserialized and executed after the remaining witness
stack: 0 <signature1> 1 <pubkey1> <pubkey2> 2 CHECKMULTISIG .
P2SH(P2WPKH)
Get the hash of the P2WPKH scriptPubKey and use it in P2SH as usual:
HASH160 (0 6 b85f9a17492c691c1d861cc1c722ff683b27f5a )
And thus:
Note that for spending20 the scriptSig contains the redeem script as a single element and
without any extra unlocking data before it since those are in witness (check section 6.4 for
how P2SH works).
For validation the scriptSig is hashed with HASH160 and compared to the <20-byte-
script-hash> in scriptPubKey. If they are equal we can then verify the public key and
signature as a native P2WPKH.
P2SH(P2WSH)
Get the hash of the P2WSH scriptPubKey and use it in P2SH as usual:
And thus:
Note that for spending the scriptSig contains the witness script as a single element and
without any extra unlocking data before it since those are in witness (check section 6.4 for
how P2SH works).
For validation the scriptSig is hashed with HASH160 and compared to the <20-byte-
script-hash> in scriptPubKey. If they are equal we can then verify the witness script as a
native P2WSH.
Implemented as a soft-fork
Changing the transaction format is normally a hard-fork. The new transactions would not
be accepted by the nodes running the old software. To go around that and implement the
new functionality as a soft-fork additional effort was required. Without going into too much
details:
• The original transaction format was not changed. The scriptSig would just be empty
and the witnesses would go in a new structure.
• The header should represent the whole block and thus a witness merkle root is calcu-
lated (from all transactions’ witness scripts) and included in an OP_RETURN output
(see section 6.7) of the coinbase transaction. Being in the coinbase means that the wit-
nesses are represented in the header via the hashMerkleRoot (see section 1.4 for a
reminder).
• Witness data are provided only when nodes ask for them and thus old nodes will get
blocks without the witness data, i.e. new nodes will remove witness data before relay-
ing the blocks to old nodes. To old nodes, segwit blocks would look like blocks that
contain some non-standard transactions.
• Old nodes trying to spend a segwit output would violate the clean stack rule21 ; OP_0
<bytes in hex> will remain in the stack.
52 if __name__ == "__main__":
53 main ()
The CHECKMULTISIG opcode has a bug where it pops an extra element from the stack.
For backward compatibility the bug cannot be fixed and thus to avoid the issue we add
an additional dummy value at the beginning of the unlocking script. Typically, OP_0
is used as a dummy but anything is valid.
Indirectly
However, Bitcoin’s blockchain was not designed for storage in general and data could only
be stored indirectly. Examples include adding data to coinbase transactions, to transaction
outputs and to multi-signature addresses.
Let’s go through one of the above examples, and explain how it would be possible to store
data in the outputs of fake addresses. Remember that the output address is represented as
the public key hash or 20 bytes (40 hex characters). Those can be faked to represent the data
that we need to store. For example22 , to store “3Nelson-Mandela.jpg?” (20 characters) we
22 Borrowed from Ken Shirriff’s excellent blog post: https://www.righto.com/2014/02/
ascii-bernanke-wikileaks-photographs.html
Chapter 6. Scripting 1 77
Storing data this way creates an overhead for the UTXO set in every node in the net-
work. These addresses will never be used (i.e. the satoshis there are lost) but the
system is not aware so they need to keep track of them as unspent outputs!
Directly
Storing data on the blockchain with the above methods was frowned upon the community
because of the overhead it was placing on the running nodes. Others argued that as long
as the transaction fee is paid there is no reason why it should be considered spam. The
compromise was the introduction of an operator, called OP_RETURN specifically dealing
with storing small amount of data on the blockchain.
The OP_RETURN opcode was followed by a maximum of 80 bytes of data24 . No satoshis
were required to be sent (other than the transaction fees) and more importantly, OP_RETURN
was not bloating the UTXO set.
Since 80 bytes is a very small amount of data it is usually used to store a hash (or digest or
digital fingerprint) of some data ensuring the integrity of the data rather than the immutable
existence of the data itself. Alternatively, it can be used to encode meta-protocol information,
such as used by Counterparty25 , the OMNI protocol26 and verifiable PDFs27 .
An example script would be:
OP_RETURN 4 f1edef24e9e2a169f56e1b0ae936d32232652dc51be1860ecd714
6.8 Exercises
Exercise 6.1 Write a program that spends a UTXO. The user will provide a P2PKH
address as a parameter and he will then be prompted to choose between the available
UTXOs of that address.
Exercise 6.2 In mainnet, how can we estimate what is an appropriate fee to include
to a transaction?
Exercise 6.3 Write a scriptPubKey script that requires both a key and password to
unlock.
Exercise 6.5 Create a script that spends funds from the P2SH address created in the
previous exercise.
Exercise 6.6 Write a Python function that goes through a serialized transaction and
calculates what percentage of its size are the scriptSigs.
Exercise 6.7 Write a script that goes through a block and prints the percentage of all
the scriptSigs relative to the size of the block.
Exercise 6.8 How can we calculate what the maximum effective block size limit is with
segwit?
Exercise 6.9 Create a P2WSH address that contains a P2PK locking script. Then
display the address.
Exercise 6.10 Create a transaction that spends UTXOs from a P2WSH address that
contains a P2PK locking script.
Exercise 6.11 Create a P2SH(P2WSH) address that contains a P2PK locking script.
Then display the address.
Exercise 6.12 Create a transaction that spends UTXOs from a P2SH(P2WSH) address
that contains a P2PK locking script.
Exercise 6.13 Create a transaction that sends some bitcoins to a 2-of-2 P2MS standard
output type.
80 6.8. Exercises
Exercise 6.14 Create a transaction that spends some bitcoins from the 2-of-2 P2MS
created above. Remember the CHECKMULTISIG bug.
Exercise 6.15 Create a 2-of-3 multisig (wrapped in P2SH) and display the address.
Exercise 6.16 Create a transaction that spends funds from the 2-of-3 multisig created
above. Remember the CHECKMULTISIG bug.
Exercise 6.17 The Bitcoin white paper (PDF) is stored on the blockchain. The
transaction id is:
54e48e5f5c656b26c3bca14a8c95aa583d07ebe84dde3b7dd4a78f4e4186e713
Can you extract the data from this transaction and reconstruct the PDF?
7. Scripting 2
7.1 Timelocks 81
7.5 Exercises 93
This chapter is build upon the previous one and continues to explore more advanced scripts
and techniques for locking and unlocking funds in the Bitcoin network. Several examples are
provided.
7.1 Timelocks
Timelocks is a mechanism for postdating transactions or to lock funds for specific periods of
time. It applies only to version 2 transactions. There are two different types of locking, one
for absolute and one for relative time. In each one we can specify timelocks at transaction
level or at script level.
Absolute nLocktime is used in some wallets to prevent fee sniping. Fee sniping is a
theoretical attack that involves large miners/pools mining two (or possibly more) blocks in
an attempt to reorganize past blocks. The miner can then add the highest-fee transactions
from the previously valid blocks plus any high-fee transactions in the mempool.
The Bitcoin Core wallet (from 0.11.0) creates transactions that include an nLocktime of
the current best height plus one. Thus, the transaction is valid for the next block as normal
but in the case of a reorg a miner cannot add this transaction in a previous block. This means
that, if all transactions use this mechanism, the miner will not be able to gain any new fees
81
82 7.1. Timelocks
by including new transactions to older blocks. This will be more important as the miners’
reward is reduced further making transaction fees the major source of income for miners.
This can be achieved by setting nLocktime and nSequence appropriately.
nLocktime = current_best_height + 1
nSequence = 0xFFFFFFFE
The original idea behind nSequence was that a transaction in the mempool would be
replaced by using the same input with a higher sequence value. This assumes that min-
ers would prefer higher sequence number transactions instead of more profitable ones (i.e.
higher fee) which would never work.
For this reason the nSequence input field was repurposed to specify additional transac-
tion semantics like timelocks. Typical transactions have an nSequence of 0xFFFFFFFF.
For example, as we can see in figure 7.1, if we want to spent a UTXO of transaction T Xx
in block Y (a block in the future, say 700000) we need to create a transaction that spends
it but also set nLocktime to Y . Then this new transaction T Xx+1 will be invalid until that
block height.
Note that nLocktime creates a transaction that cannot be included in the blockchain until
the specified block/time. This means that the person who created the transaction could
create another transaction to spend the funds, invalidating the nLocktime transaction. This
is problematic in several use cases and thus absolute timelocks at script level were created.
A scriptPubKey example that locks an output until an expiry_time and a P2PKH equiv-
alent would look like:
To spend a transaction output with a timelock we need to specify the future block in
nLocktime and activate the nSequence of the particular input that we want to spend to
0xFFFFFFFE.
For example, as we can see in figure 7.2 we can create a locking script with CLTV on
block Y (a block in the future, say 700000) and send some funds to it (and keep sending). If
we want to spend it we need to create a transaction that spends it but also sets nLocktime to
at least 700000. Then this new transaction T Xx+1 will be invalid until that block height.
3 https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki
4 https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki
84 7.1. Timelocks
Expiry date can be expressed in either block height or timestamp (as previously dis-
cussed) but it has to be the same type as the one used in the nSequence field. Note that in
the script only the block height or timestamp is included6 and not the whole nSequence
field.
For example, we can create a locking script with CSV with a value of 10 blocks and send
some funds to it (and keep sending). If we want to spend it we need to create a transaction
that spends it but also set the nSequence of the input that spends it to 10. Then, this new
transaction T Xx+1 will be invalid until T Xx gets 10 confirmations.
5 https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki
6 If timestamp the 23rd bit has to exist and be set. Also note that integers in the script should be serialized as
signed integers in little-endian. Fortunately, programming libraries hide these details from the developers.
Chapter 7. Scripting 2 85
Time
In
Type Location specifica- Example
blockchain
tion
Similar to a will. Your heirs could
get the funds in 2040 but you
nLocktime Transaction Absolute No
could spend them (changle will) in
between.
Lock funds as part of a deal that
nLocktime allows no one access until
Script Absolute Yes
+ CLTV 1-Jan-2020. Used in CLTV-based
payment channels.
Lock funds as part of a deal that
prohibits the other party to spend
nSequence Input Relative No
funds until 3 months have passed
but you can.
Lock funds as part of a deal that
allows no one access until 3
nSequence
Script Relative Yes months have passed. Used in
+ CSV
payment channels and Lightning
network
7 https://github.com/karask/python-bitcoin-utils/blob/master/examples/create_p2sh_csv_p2pkh_address.py
86 7.1. Timelocks
6
7 def main ():
8 # always remember to setup the network
9 setup(’testnet ’)
10
11 # This script creates a P2SH address containing a CHECKSEQUENCEVERIFY plus
12 # a P2PKH; locking funds with a key as well as for 20 blocks
13
14 # set values
15 relative_blocks = 20
16
17 seq = Sequence(TYPE_RELATIVE_TIMELOCK , relative_blocks )
18
19 # secret key corresponding to the pubkey needed for the P2SH (P2PKH) transaction
20 p2pkh_sk = PrivateKey(’cRvyLwCPLU88jsyj94L7iJjQX5C2f8koG4G2gevN4BeSGcEvfKe9 ’)
21
22 # get the address (from the public key)
23 p2pkh_addr = p2pkh_sk.get_public_key (). get_address ()
24
25 # create the redeem script
26 redeem_script = Script ([seq.for_script (), ’OP_CHECKSEQUENCEVERIFY ’, ’OP_DROP ’,
27 ’OP_DUP ’, ’OP_HASH160 ’, p2pkh_addr.to_hash160 (),
28 ’OP_EQUALVERIFY ’, ’OP_CHECKSIG ’])
29
30 # create a P2SH address from a redeem script
31 addr = P2shAddress.from_script(redeem_script)
32 print(addr.to_string ())
33
34 if __name__ == "__main__":
35 main ()
8 https://github.com/karask/python-bitcoin-utils/blob/master/examples/spend_p2sh_csv_p2pkh.py
Chapter 7. Scripting 2 87
18 vout = 0
19
20 seq = Sequence(TYPE_RELATIVE_TIMELOCK , relative_blocks )
21
22 # create transaction input from tx id of UTXO (contained 11.1 tBTC)
23 txin = TxInput(txid , vout , sequence=seq. for_input_sequence ())
24
25 # secret key needed to spend P2PKH that is wrapped by P2SH
26 p2pkh_sk = PrivateKey(’cRvyLwCPLU88jsyj94L7iJjQX5C2f8koG4G2gevN4BeSGcEvfKe9 ’)
27 p2pkh_pk = p2pkh_sk.get_public_key (). to_hex ()
28 p2pkh_addr = p2pkh_sk.get_public_key (). get_address ()
29
30 # create the redeem script - needed to sign the transaction
31 redeem_script = Script ([seq.for_script (), ’OP_CHECKSEQUENCEVERIFY ’, ’OP_DROP ’,
32 ’OP_DUP ’, ’OP_HASH160 ’, p2pkh_addr.to_hash160 (),
33 ’OP_EQUALVERIFY ’, ’OP_CHECKSIG ’])
34
35 # to confirm that address is the same as the one that the funds were sent
36 #addr = P2shAddress.from_script(redeem_script)
37 #print(addr.to_string ())
38
39 # send/spend to any random address
40 to_addr = P2pkhAddress(’n4bkvTyU1dVdzsrhWBqBw8fEMbHjJvtmJR ’)
41 txout = TxOutput(to_satoshis (11), to_addr. to_script_pub_key () )
42
43 # no change address - the remaining 0.1 tBTC will go to miners)
44
45 # create transaction from inputs/outputs
46 tx = Transaction ([ txin], [txout ])
47
48 # print raw transaction
49 print("\nRaw unsigned transaction :\n" + tx.serialize ())
50
51 # use the private key corresponding to the address that contains the
52 # UTXO we are trying to spend to create the signature for the txin -
53 # note that the redeem script is passed to replace the scriptSig
54 sig = p2pkh_sk.sign_input(tx , 0, redeem_script )
55
56 # set the scriptSig (unlocking script) -- unlock the P2PKH (sig , pk) plus
57 # the redeem script , since it is a P2SH
58 txin.script_sig = Script ([sig , p2pkh_pk , redeem_script.to_hex ()])
59 signed_tx = tx.serialize ()
60
61 # print raw signed transaction ready to be broadcasted
62 print("\nRaw signed transaction :\n" + signed_tx)
63 print("\nTxId:", tx.get_txid ())
64
65
66 if __name__ == "__main__":
67 main ()
spend.
Input 0:
1 OP_CLTV
Input 1:
500000001 OP_CLTV
The same would apply even for a single locking script that had both types of absolute
locking.
Relative timelocks use nSequence which is per input and thus for CSV the issue comes
up only when a single script has both types of locking.
Replace-By-Fee
Replace-by-fee, specified in BIP-1259 is a mechanism for replacing any transaction that is
still in the mempool. It is primarily useful for re-sending a transaction of yours in case it
was stuck, e.g. due to low fees. However, it may be useful for other reasons.
Similar to timelocks it applies only to version 2 transactions and you need to set nSe-
quence to a value of 0x01 to 0x7fffffff. However, since that such a value also enables rel-
ative timelocks one has to be careful. Typically, for RBF you set the nSequence value to 1,
which makes relative timelocks irrelevant, or from 0xf0000000 to 0xfffffffd which disables
relative timelocks.
When creating transactions with the Bitcoin core software RBF transactions are opt-in. A
replaceable transaction has the bip125-replaceable flag set to yes in its JSON display. You
can make all transactions replaceable by default by setting walletrbf=1 as a node option.
To work, in addition to setting the nSequence the transaction needs to reuse one or more
of the same UTXOs10 and increase the fees.
Using the Bitcoin core wallet there is an easy way to RBF a transaction (that is, of course,
replaceable) by using bumpfee:
9 https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki
10 Note that this allows the new transaction to have different output addresses.
Chapter 7. Scripting 2 89
Child-pays-for-parent
Child-pays-for-parent or CPFP is a mechanism (or trick, if you wish) for including a previous
transaction (parent) in a block by creating a transaction (child) that spends one of the UTXOs
of the parent. Miners will notice that the new transaction uses another one and will consider
both transactions’ fees when deciding whether to include it in the next block.
For example if someone sends you bitcoins but the transaction was stuck (e.g. due to low
fees) you as a recipient can create a transaction that tries to spend the bitcoins from your
address from the unconfirmed transaction. The fees of this transaction should be quite high
to properly incentivize the miner (i.e. proper fees for two transactions).
If the fee is high enough the miner will want to include the new (child) transaction and
in doing so he is forced to include the initial transaction (parent) in the same block. There
is nothing special with CPFP and can apply to any transaction. It makes use of miners’
incentives to prioritize a transaction.
The sender of some funds can use RBF to increase the fee to unstuck a transaction from
the mempool. The recipient of some funds can use CPFP to indirectly increase the fee
to unstuck a transaction from the mempool.
This makes it possible to create multiple outputs locked with the same hashlock and
when one is spent the rest will also be available for spending, since, by spending one the
passphrase will be revealed). Effectively, by spending one such output you share the passphrase.
Of course, since the passphrase will become public, everyone will be able to spend the
rest of the outputs, which is not very useful. Thus, outputs protected by hashlocks are
typically also protected by specific signatures so that only the owners of the corresponding
keys could spend the remaining outputs. This is similar to what 2FA offers (something one
owns and something one knows).
90 7.3. Hash Time-Locked Contracts
HTLC
A Hashed Time-Locked Contract (BIP-19911 ) is a combination of a hashlock and a timelock
that requires the receiver of a payment to either provide a passphrase or forfeit the payment
allowing the sender to take the funds back. For example:
OP_IF
OP_SHA256 <passphrase_hash > OP_EQUALVERIFY
OP_DUP OP_HASH160 <receiver PKH >
OP_ELSE
100 OP_CHECKSEQUENCEVERIFY OP_DROP
OP_DUP OP_HASH160 <sender PKH >
OP_ENDIF
OP_EQUALVERIFY
OP_CHECKSIG
The above locking script would be created by both sender and receiver collaborating.
The receiver knows the passphrase, also called pre-image, but only shares its hash, also called
digest. The sender can then send some funds to that P2SH address. The receiver can claim
the funds if he reveals (in the blockchain) the passphrase. If not, after 100 blocks pass the
sender can claim the funds.
Let’s go through this scenario in more detail. Alice wants to learn some information, e.g.
a passphrase, and is willing to pay to get it. Bob has the passphrase and is willing to sell it12 .
To setup an HTLC, see figure 7.5 (i), the following steps are required:
According to the locking script there are only two possible scenarios as seen in figure 7.5
(ii) and (iii) respectively.
(ii) Bob claims the funds and in doing so reveals the passphrase.
(iii) Bob does not claim the funds until the agreed timeout. Alice can take the funds back.
11 https://github.com/bitcoin/bips/blob/master/bip-0199.mediawiki
12 This scenario might sound very abstract but it will make more sense in the Atomic Swaps section.
Chapter 7. Scripting 2 91
HTLC Applications
HTLC transactions are a safe and cheap method of exchanging secrets for money over the
blockchain. Applications include Atomic Swaps, Lightning Network, Zero-knowledge con-
tingent payments13 and potentially several others.
• Alice and Bob exchange public keys on both Bitcoin and Litecoin.
• Alice and Bob agree upon the timeout thresholds, say 48 and 24 hours.
• Alice knows of a passphrase (pre-image) which is hashed to produce a digest; the
latter is shared with Bob.
(ii) Both Alice and Bob create a HTLC for the Bitcoin and Litecoin blockchain respectively.
The funds can be redeemed by:
(iii) Both Alice and Bob create a refund transaction for the funds they have just sent
• Alice creates a timelocked refund transaction that would be valid after 48 hours.
• Bob creates a timelocked refund transaction that would be valid after 24 hours.
• Both pass the refund transaction to their counterpart for their signature (satisfying
the “both signatures” clause of the HTLCs).
• They now both have a final refund transaction that is ready to be broadcasted if
something goes wrong.
(iv) Alice and Bob both broadcast the funding transaction from step (ii).
(v) Alice unlocks the Litecoin HTLC by the “passsphrase” clause of the HTLC revealing
the passphrase in the process.
(vi) Bob uses the passphrase to unlock the Bitcoin HTLC as well and the atomic swap was
successful.
Note that the above ordering is not strict in any sense. As long as the refund transactions
are both signed before the passphrase is revealed everyone is safe.
If Bob does not send the LTC, Alice will be able to get her 1 BTC back after 48 hours by
broadcasting her refund transaction.
If Alice does not send the BTC, Bob will be able to get his 100 LTC back after 24 hours
by broadcasting his refund transaction.
It is important to understand that active participation is required in this exchange. For
example, if Bob does not use the passphrase to claim the bitcoin in time after the passphrase
is revealed, Alice can use her refund transaction and also get her bitcoin back!
Chapter 7. Scripting 2 93
Participants in an atomic swap need to inspect the blockchain for the relevant transac-
tions!
Atomic swaps allow for trustless exchange between assets of different blockchains. One
potential use case is trustless decentralized exchanges.
7.5 Exercises
Exercise 7.1 In section 7.1 we created an address for a relative timelock. Now create
an address that locks the funds with an absolute timelock some time in the future (use
block height or timestamp).
Exercise 7.2 In section 7.1 we spent from an address with a relative timelock. Now
create a script that unlocks the funds from an address with an absolute timelock like
the one created in the previous exercise.
Exercise 7.3 Implement the example HTLC scenario of section 7.3. Create the appro-
priate scripts for both Alice and Bob.
Exercise 7.4 Write the HTLC locking script that Alice needs to create for the atomic
swap in step (ii) as described in section 7.4.
Exercise 7.5 Write the unlocking script that Alice needs to use to claim the litecoin in
step (v) as described in section 7.4.
Exercise 7.6 Try to design a platform that would facilitate atomic swaps between
Bitcoin and Litecoin. Think about it holistically and in practical terms; i.e. how would
you design and implement such a platform. Keep a note of all the potential difficulties
that might come up and try to find solutions.
8. Advanced Topics
8.3 Sidechains 95
94
Chapter 8. Advanced Topics 95
8.3 Sidechains
Bibliography
[1] Adam Back. Hashcash - A Denial of Service Counter-Measure. Tech. rep. 2002.
[2] Jonathan Bier. The Blocksize War: The battle over who controls Bitcoin’s protocol rules.
2002.
96
Bibliography 97