08 Sep 2021

Bitcoin

Money for the streets

Reactors online. Sensors online. Weapons online. All systems nominal.

Consensus

The value of bitcoin is derived from its leaderless-consensus (Nakamodo Consensus).

The word consensus can make people think of a jury where members need to find a verdict. Or maybe a distributed systemsrelying 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. Humans tend to abuse concentrated power. Thus bitcoin’s value proposition: consensus without leaders, so there is no power to abuse.

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 users agree on the rules and have equal responsibility, also known as, 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 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 core of this system uses a strategy called Proof of Work. In bitcoin, the proof of work outputs a ledger of bitcoin transactions which comprises 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 (linear). All other users can 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. The sheer amount of work required protects bitcoin from a central power.

Proof-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.

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:

Bitcoin’s only value proposition is consensus without leaders, if that is degraded there is no point to bitcoin. 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.

Transactions

Bitcoin is transactions, and the blockchain orders them.

Transaction outputs are indivisible chunks of bitcoin currency

{
  "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

inputs

Inputs are more interesting!

Each input contains:

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

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

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

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

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>

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.

Unequal amounts discussion

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.

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.

Schnorr signatures history

Merklized Abstract Syntax Trees (MAST)

P2SH has a few weaknesses

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.

(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.

MuSig

Deep dive

MuSig is effectively a key aggregation scheme for Schnorr signatures

Software

Full Node

Adventures in systemd

The packaged bitcoind.service unit file sets a STATE DIRECTORY with a mode that is used by the exec statement as the data dir. This hold the blockchain so I keep it off on a separate hdd. There is a symlink from /var/lib/bitcoind => /data/bitcoind. The symlink throws off systemd’s start up process though (guessing cause it can’t set the mode). I think the least invasive way to keep most of the supplied logic is to override just those settings.

sudo systemctl edit bitcoind
[Service]
StateDirectory=
StateDirectoryMode=

Trezor

Resources

Lightning

The lightning network is a “layer 2” application on top of bitcoin.

While base layer Bitcoin is a slow-moving bedrock that places caution and consensus before all else, the LN is a fast-paced, amorphous network of relationships that are inherently volatile.

Channels

in the beginning…

unidirectional + transaction timelocks

Abstract channels are based on layers of 2 main ideas:

A unidirectional channel with a set end time (e.g. will close 3 days from now) is pretty easy to model with these ideas in mind. A 2-of-2 multisig transaction is created (not yet broadcasted) between the 2 parties. A is paying B, so A funds the whole transaction. Before broadcasting this “funding” transaction though, another transaction is created based on the funding transaction (so it requires both A and B’s sigs). This “refund” transaction is a special case “commitment” transaction which sends all the funds back to A with a timelock of 3 days.

What are the incentives of the first commitment transaction?

After the funding transaction is broadcasted, A and B can trade within the offchain channel by exchanging new commitment transactions. These transactions are not broadcasted to the blockchain, but they are valid transactions which could be broadcasted at any point. Each commitment transaction is a possible closing transaction.

Since this is a unidirectional channel, the transactions are updated where A pays B a little bit more for each transaction. This is done by A receiving less from the multsig when the channel is closed. A signs the transaction and gives it to B as payment, B does not have to sign or broadcast the transaction yet.

A commitment transaction is a transaction that pays each channel partner their channel balance and ensures that the channel partners do not have to trust each other. By signing a commitment transaction, each channel partner “commits” to the current balance and gives the other channel partner the ability to get their funds back whenever they want.

What are the incentives after the first commitment transaction?

bidirectional

Bidirectional channels require more un-broadcasted transactions and timelock layering to make sure incentives stay aligned. If we kept the same protocol from the simpler unidirectional model, A could send a transaction that pays B less as a form of B paying A (bidirectional). But there is nothing stopping B from singing and broadcasting an old commit transaction which A has already signed given B more bitcoin. Bidirectional channels require a disincentive to broadcast old commitment transactions.

As of 2020, these are built with HTLCs. Schnorr signatures introduced by Taproot upgrade could allow a different implementation.

The HTLC script is complex, but this is the basic gist:

OP_SHA256 <H> OP_EQUALVERIFY <Bob's Pub> OP_CHECKSIG

The real world script uses more complex RIPEMD160 to minimize bytes in the transaction to minimize fees.

HTLCs require some way to fail gracefully in case parties don’t cooperate and share the secret, else funds would be locked up.

OP_DROP <cltv_expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP
OP_CHECKSIG

This is the beginning of a Revocable Sequence Maturity Contract, or RSMC, to cancel old commitment transactions.

What are the incentives of the HTLC?

Back to Bidirectional channels. They are funded the same as unidirectional. But the commitment transactions are more complex. There is now a pair of commitment transactions per payment.

A mechanism is required to not spend old commitment transactions (a.k.a steal). We need new commitment transactions to somehow invalidate the old.

In simple terms, Alice signs Bob’s new commitment transaction only if Bob offers his half of the revocation secret for the previous commitment. Bob only signs Alice’s new commitment transaction if she gives him her half of the revocation secret from the previous commitment.

What are the incentives in the bidirectional channel with revocation secrets?

A channel can be closed cooperatively which doesn’t involve timelocks and each party gets their funds immediately.

eltoo

Future upgrade which could mitigate the need for revocation secret complexity.

multihop

How is the channel balance updated without trust? A new HTLC output is introduced to the commitment transactions. Same process is used to forward HTLC in onion routing or payment between just 2 parties.

A decrementing timelock is necessary to protect against race conditions that would leave a users hanging (paid it forward, but never received).

(A) -> (B) -> (C)

If A is routing a payment to C through B, B will only update its commitment transactions with C if there is no chance the complementary commitment transaction from A will fall through. So the A to B timelock needs to be higher (last longer) than the timelock from B to C. If they were the same timelock, it would be possible for the A -> B transaction to be revoked by A, right as B got the (now worthless to B) secret from C.

The pre-image secret is used to settle (or “unwind”) an in process HTLC. update_fulfill_htlc updates a channel with the value of the HTLC. While there is not a huge incentive for A and B to “clean up” a completed HTLC output in the commitment transactions, there isn’t an incentive not too either.

Anchor Channels (?)

Liquidity

In order to provide liquidity for routing payments and to earn fee income, Lightning node operators need to lock up capital (Bitcoin) inside payment channels.

Opening a channel requires a bitcoin transaction. Closing a channel requires another bitcoin transaction. This encourages long lived channels to avoid the overhead.

  1. Outbound
    • owned by node operator
    • when an operator opens a channel its initially all outbound (the funding transaction is entirely one sided)
    • opening channels only gives you capacity to send, not to receive, balance is all on one side: A(1) -- B(0)
  2. Inbound
    • not owned by node operator

Fee market

If your node and another node on the lightning network are connected, that node is your peer. If you also lock up funds between your nodes, that is what is called a channel

The fee rate is different than on chain where the cost is MB instead of the value being sent. In the LN, liquidity is valuable so the fee is actually based on the value. If this was 0, one huge transaction could dry up a channel and it would only earn the base fee. It probably wouldn’t cover its opening/closing on chain costs.

The reasoning is: a lot of small payments are sustainable on my channels, no problem, but using up a lot of my liquidity is not sustainable

yonson