Bitcoin
Money for the streets
Reactor online. Sensors online. Weapons online. All systems nominal.
This manual first covers high level fundamentals of bitcoin and then decends into technical details.
Consensus
The value of bitcoin is derived entirely from its leaderless-consensus (known as Nakamodo Consensus).
The word consensus maybe makes people think of a jury where members need to find a verdict. Or perhaps they think of a distributed system relying on a quorum achieving consensus. In both these scenarios, there is trust put in relatively few leaders in order to pragmatically create consensus.
Trust is power. And humans tend to abuse it. Thus bitcoin’s value proposition: consensus, but without leaders. There is no power to abuse. Whether this is valuable or not…well, that is a question for yourself.
From a high level, Nakamodo Consensus is achieved through a combination of applied cryptography and game theory. The applied cryptography allows consensus responsibility to be shared among all users. The game theory allows users to assume which rules are the agreed upon rules. So, all users agree on the rules while having equal responsibilities. That’s leaderless consensus.
proof of work
There is a common characteristic of applied cryptography which is used over and over in the bitcoin system: hard to calculate, easy to verify. A real world metaphor might be cooking pancakes. Its very easy for someone to try a bite of pancakes and verify “Yep, these are pancakes”. It is harder for them to guess the exact recipe used to cook (a.k.a. calculate) these pancakes.
This cryptographic property can be chained together. Back to the pancake metaphor, there could be a new recipe, recipe2
, which is just recipe1
plus a new secret ingredient. This means though that if recipe1
changes, the pancakes produced by recipe2
will also change.
The bitcoin protocol defines a system which utilizes these characteristics to create Nakamodo Consensus. The crux of this system is a strategy called Proof of Work. In bitcoin, the proof of work outputs a ledger of bitcoin transactions which holds the entire history of bitcoin and the rules used to get there. This is called the blockchain.
Proof of Work uses the hard to calculate, easy to verify characteristic to enable random, short-term leaders who get to add one block on the blockchain. Users have incentives to be the leader, they then get to collect the fees in a block, but they must contribute work in order to have the chance. The more work, the higher the chance (its linear). When a new block is added by the leader, all other users are able to quickly validate that the leader was random and followed the rules (prove the work).
Proof of Work uses the chaining principle to link the blocks on the blockchain together. This allows users to quickly agree that the entire blockchain is valid and follows the rules.
What differentiates the bitcoin blockchain from another one which follows the same rules? The one with the most blocks (longest) has the most work poured into it and is the blockchain. This is where game theory gets involved to allow users to assume the longest blockchain is the real blockchain.
Bitcoin minimizes the complexity of achieving consensus by minimizing the scope of what consensus is covering. The consensus only producing a log (ledger) of events. In other words, “these things happened in this order”. Even the allowed “things” is a fairly minimal set of transaction types. Compare this to Ethereum where consensus is covering a much broader set of things. This requires more complexity in the how consensus is achieved. That complexity bears risks, known and unknown.
Sybil attack
A 51% attack, or Sybil attack, is the most well known attack on bitcoin which Proof of Work also defends against. The work in Proof of Work allows users to agree on a blockchain, but it also helps protect from this kind of attack.
A Sybil attack is when someone controls at least 51% of the work being poured into bitcoin. At this point, chances are they will guess the next block and thus be the short term leader. And as long as they hold at least 51% of the work, chances are that will happen again and again. With this power they could: 1. control what transactions get in to the blockchain and 2. mine a “shadow” blockchain and perform a double-spend by swapping it with the public blockchain. I think (1) is way more powerful given the cost to perform a 51% attack.
How does Proof of Work protect against this attack? As of 2021, the cost to control 51% of the bitcoin hashing power for just an hour is in the billions of USD. The sheer amount of work required protects bitcoin from a central power.
Proofm of Work incentivices miners with transactions fee per-mined-blocked. If a miner invests more power into bitcoin, increasing their share of all the power being poured into bitcoin from say 20% to 25%, there is a 5% higher chance they will mine a block and get more fees. They do not however, “control” 5% more of bitcoin. They have the same amount of influece as they did before due to the leaderless consensus: zero.
transaction fee market
There is an “artificial” blocksize which limits the amount of transaction per second on the bitcoin blockchain. Transactions which pay higher fees are selected into a block. The scarce resource in this market is bytes on the blockchain.
This leads to a few questions.
- Is there a real limit?
- Why have the artificial limit?
- Is this related to consensus?
The blocksize debate back in 2015 is bitcoin’s most famous holy war. As with all holy wars, there was a lot of noise coming from parties with different interests. I personally believe most of the noise was generated by parties which valued bitcoin succeeding quickly over bitcoin succeeding at all (e.g. my company survives if bitcoin is mass adopted in 2 years or my company fails, in which case I don’t care about bitcoin cause my company just failed).
My take on answering the above questions with the least amount of noise:
- I am not sure what the real limit is, but at some point the vast amount of computers would not be able to keep up with all the writes
- The artificial limit determines what quality of computer is necessary to run a node: lower limit means lower quality
- Nakamodo Consensus would function regardless of the blocksize, but as the number of users decreases so does the value of the consensus as it becomes more centralized
Bitcoin’s only value proposition is consensus without leaders, if that is degraded there is no point to bitcoin (might as well use a simple, centralized database). The limit should be kept low to encourage the highest value consensus. Second layer applications are responsible for increasing transactions per second and developing more value on top of the layer one consensus.
value as currency
Bitcoin’s value is entirely determined by it’s blockchain consensus. That is all it offers. Compare this to a cryptocurrency like Ethereum which promises more features. It’s value is not only its consensus, but the features it offers. I think it is much harder to put a number on this than bitcoin’s robust simplicity. In some sense the value of Ethereum is circular. Its measuring its own ever growing feature set. I don’t think this is a desired characteristic of currency.
further reading
Transactions
Bitcoin is transactions, and the blockchain orders them.
Transaction outputs are indivisible chunks of bitcoin currency
- unspent transaction outputs are called UTXO
- script language is called
Script
(great namespace grab) and is stack based- stateless and turning incomplete, no loops, to limit complexity
- executes from left => right input sig + output sig
{
"version": 1,
"locktime": 0,
"vin": [
{
"txid": "7957a35fe64f80d234d76d83a2a8f1a0d8149a41d81de548f0a65a8a999f6f18",
"vout": 0,
"scriptSig" : "3045022100884d142d86652a3f47ba4746ec719bbfbd040a570b1deccbb6498c75c4ae24cb02204b9f039ff08df09cbe9f6addac960298cad530a863ea8f53982c09db8f6e3813[ALL] 0484ecc0d46f1918b30928fa0e4ed99f16a0fb4fde0735e7ade8416ab9fe423cc5412336376789d172787ec3457eee41c04f4938de5cc17b4a10fa336a8d752adf",
"sequence": 4294967295
}
],
"vout": [
{
"value": 0.01500000,
"scriptPubKey": "OP_DUP OP_HASH160 ab68025513c3dbd2f7b92a94e0581f5d50f654e7 OP_EQUALVERIFY OP_CHECKSIG"
},
{
"value": 0.08450000,
"scriptPubKey": "OP_DUP OP_HASH160 7f9b1a7fb68d60c536c2fd8aeaa53a8f3cc025a8 OP_EQUALVERIFY OP_CHECKSIG",
}
]
}
outputs
- UTXO contain two parts: an amount and a cryptographic puzzle,
scriptPubKey
, to spend it scriptPubKey
made sense historically, but would be better calledlocking script
or something
inputs
Inputs are more interesting!
Each input contains:
- A transaction ID, referencing the transaction that contains the UTXO being spent
- An output index (vout), identifying which UTXO from that transaction is referenced
- A scriptSig, the script which satisfies the conditions placed on the UTXO
- A sequence number (locktime)
Each transaction input and any signature it may contain is completely independent of any other input or signature. Multiple parties can collaborate to construct transactions and sign only one input each.
signing
- A signature on the transaction proves: transaction can be spent and has not been modified. A hash of a subset of the data of a transaction.
sighash
flags allow for different parties to spend/modify outputs. Multiple parties can be involved in a single transaction, with their sigs only covering a portion of the inputs/outputs.
types
Theoretically, the scriptPubKey
could contain any script. But back in the early days, bitcoin limited this to a handful of “standard” types probably to keep stupid things from happening. This can be circumvented with P2SH.
P2PKH
Pay to Public Key Hash
Why did the OG bitcoin support both P2PK and P2PKH (key vs. key hash)?
Public keys in the original Bitcoin implementation were 65 bytes, but address hashes were only 20 bytes.
Hash indirection was added to lower space requirements and make it marginally easier (less mistakes) for human users to copy/paste things. Hashes also hide keys from public view until they actually want to be spent.
OP_DUP OP_HASH160 <PubkeyHash> OP_EQUALVERIFY OP_CHECKSIG
OP_CHECKSIG which returns true if a signature signs the correct parts of a transaction and matches a provided public key
- the
OP_DUP OP_HASH160 <PubkeyHash> OP_EQUALVERIFY
makes sure that theOP_CHECKSIG
can only be checked with the pubkey of the pubkeyhash- without this, a user could provide any pubkey + signature with that pubkey’s private key
- the
scriptPubKey
’sOP_CHECKSIG
does the heavy lifting, it validates that a signature was signed by the private key of the public key of the address (confirms this is the owner spending)- OP_CHECKSIG also validates that the owner signed the appropriate parts of the current transaction (determined by sighash type)
Tough to find a more influential opcode in Script than OP_CHECKSIG. There isn’t a “do less” opcode so it sets the bar for bare minimum requirements of a transaction. It forces an owner to prove they are the owner and prove that they agree to where they are now sending their bitcoin.
P2SH
Pay to Script Hash
P2SH transactions were standardized in BIP16. They allow transactions to be sent to a script hash (address starting with 3) instead of a public key hash (addresses starting with 1)
scripts act as dynamic public keys and signatures
- keeps redeem script hidden on public blockchain until spent
- a transaction attempting to spend the UTXO must contain the redeem script that matches the hash, in addition to the unlocking script (which references the redeem script)
The P2SH locking script pattern is recognized as a “special” form, so it gets executed slightly differently to “normal” scripts.
Recognizing one ‘special’ form of scriptPubKey and performing extra validation when it is detected is ugly. However, the consensus is that the alternatives are either uglier, are more complex to implement, and/or expand the power of the expression language in dangerous ways.
Prior to version 0.9.2 of the Bitcoin Core client, Pay-to-Script-Hash was limited to the standard types of bitcoin transaction scripts, by the isStandard() function. That means that the redeem script presented in the spending transaction could only be one of the standard types: P2PK, P2PKH, or multisig nature, excluding RETURN and P2SH itself. As of version 0.9.2 of the Bitcoin Core client, P2SH transactions can contain any valid script, making the P2SH standard much more flexible and allowing for experimentation with many novel and complex types of transactions.
OP_HASH160 [20-byte-hash-value] OP_EQUAL
- this is hashed to an address which begins with
3
- the
scriptSig
used to unlock this is executed in a special way: 1. Hash of redeem script (part of the scriptSig) is hashed and compared with theOP_HASH160 [20-byte-hash-value] OP_EQUAL
- then, the redeem script is actually run
Not sure what triggers bitcoin to run this special execution, but looks like the scriptPubKey
must be encoded with the 05
version: base58check.Encode("05", redeemScriptHash)
. It sounds like it might just look for the OP_HASH160 [20-byte-hash-value] OP_EQUAL
pattern in the scriptPubKey
.
<OP_0> <sig A> <sig C> <redeemScript> <OP_HASH160> <redeemScriptHash> <OP_EQUAL>
- example redeem script shows signatures outside of redeem script since these would throw off hash
- byte lengths are used in the tx to distinguish redeem script
OP_O
is the multisig bug, but it is outside the redeem script due to when it is needed on the stack
To identify a P2SH transaction on the blockchain to a user, the user can construct the agree’d upon script and generate the P2SH address, then scan the blockchain
addresses
segwit defines a new address type that’s encoded using Bech32 instead of base58check
bc1qeqzjk7vume5wmrdgz5xyehh54cchdjag6jdmkj
timelocks
A timelock can be applied on the transaction to make it valid only after the time has passed. Useful for signed, offchain transactions that you don’t want spent right away and could still invalidate by spending out of the same output as the timelocked transaction.
Inputs can be timelocked.
Outputs can be timelocked through opcodes.
coinjoin
no longer will input co-joining be strong evidence of common control
same amount input/outputs
For example, let’s take two transactions, one from Alice to Carol and one from Bob to Dave. Alice has two chunks of coins worth 2.3 and 1.4 bitcoin, and she wants to pay Carol 3.2 bitcoin. Bob has chunks of 3 and 2 bitcoin, and wants to pay Dave 4 bitcoin.
Simplified, these transactions look like so:
2.3 + 1.4 = 3.2 + 0.5
and
3 + 2 = 4 + 1
(The 0.5 BTC and 1 BTC outputs are change.)
Merged together, the CoinJoin transaction would look like so:
3 + 2.3 + 2 + 1.4 = 4 + 3.2 + 1 + 0.5
Although the transactions were merged, it’s trivial to rediscover which inputs paid which outputs, and, therefore, also which inputs can be matched together as belonging to the same sender.
BIP
BIP47 // Reusable Payment Code
A way to easily have a new address on every payment Reusable Payment Codes
.
BIP141 // Segwit
a weird name for moving signature data out of transactions
Move witness
data into a separate data structure in a block. The transaction data that describes its effects remains in the original location.
- fixed transaction malleability which allowed for offchain (lightning) systems to create chained, un-broadcasted, transactions.
- introduced
vbytes
instead of actual bytes when weighing transactions in order to give “discounts” to certain parts scriptSig
is empty in segwit transactions
Introduced 2 new transaction types to match the most used P2PKH
and P2SH
: P2WPKH
and P2WSH
It’s called a witness program because it can be regarded as a program of a weird language. In version 00, the witness program is a single operator whose length defines its behavior.
P2WPKH
pattern 00 followed by exactly 20 bytes gets special treatment
P2WSH
pattern 00 followed by exactly 32 bytes gets special treatment
BIP340 + BIP341 + BIP342 // Taproot
This proposal covers a lot of ground.
Schnorr signatures
All the new features depend on Schnorr signatures replacing ECDSA signatures.
In BIP340.
Schnorr signatures will make multi-signature transactions look identical to single signature transactions on the blockchain. This will reduce fees to our users and increase user privacy
Linearity (key aggregation): Schnorr signatures have the remarkable property that multiple parties can collaborate to produce a signature that is valid for the sum of their public keys. This is the building block for various higher-level constructions that improve efficiency and privacy, such as multi-signatures and other smart contracts.
Merklized Abstract Syntax Trees (MAST)
P2SH has a few weaknesses
- entire script needs to be posted to blockchain to spend, even if only sub branches of the script are used
- takes up space and unnecessarily discloses info
- limits contracts by their size instead of validation cost
A Merkle Tree is a hash tree which allows efficient and secure verification of the contents.
An Abstract Syntax Tree is splitting a program flow into a tree. Since Script doesn’t have loops, this can easily be described as a DAG.
The merkle root for this tree uniquely identifies Alice’s complete encumbrance in just 32 bytes of data. Alice then uses a substitute encumbrance that says that a spender must provide a merkle proof connecting the merkle root to one of the sub-scripts and that the sub-script must return True.
Taproot
Pay-to-Taproot outputs are version 1 SegWit outputs, and all Taproot transactions are SegWit transactions.
- New transaction type built on segwit
(P2TR) allows users to pay to either a Schnorr public key or the Merkle root of a variety of other scripts. Using this new script type, a user can create a UTXO which can be unlocked and spent by either the owner of the private key or anyone who can satisfy the requirements of any script within the Merkle tree.
- new opcode
OP_CHECKDLS
replaces checksig
MuSig
MuSig is effectively a key aggregation scheme for Schnorr signatures