Here you'll find an assorted mix of content from yours truly. I post about a lot
of things, but primarily
Day 8: Rubin's Bitcoin Advent Calendar
05 Dec 2021
Welcome to day 8 of my Bitcoin Advent Calendar. You can see an index of all
the posts here or subscribe at
judica.org/join to get new posts in your inbox
In this post we’ll rapid fire roll through a bunch of different smart contract
primitives, existing and proposed. For a more thorough reading, links will be
provided.
BIP-119 CTV CheckTemplateVerify
CTV is a general purpose smart contract opcode with full enumeration, no dynamic
state, no recursion, and primarily works through validation.
Essentially, CTV only lets you select a specific next transaction that can
occur. Consensus just checks a transaction hash against a CTV hash.
Although this seems to be limited functionality, it can be used with a template
metaprogramming system such as Sapio to create
sophisticated programs.
The limited functionality isn’t a bug, it’s a feature. CTV was designed to be
quick and easy to garner technical consensus with the entire Bitcoin community
as a simple and safe covenant without some of the issues more sophisticated
covenant systems might have. However, since its launch there’s been more
interest developing for more flexible covenants, which may take much longer to
deploy and deliver meaningful benefits to users.
CTV is also designed to work well with other opcodes that might be added (such
as CSFS, OP_AMOUNT, and OP_CAT), so it does not become irrelevant should more
features be added, it simply gets better.
CTV is currently a decently reviewed BIP pending more support from the community
for inclusion (see social signals).
Disclosure: I’m the author/advocate of BIP-119.
For more:
- Optech
- utxos.org
- Templates, Eltoo, and Covenants, Oh My!
- Shinobi’s Covenant Concerns
BIP-118 APO AnyPrevout
AnyPrevout is a culmination of research for the Lightning Network (dating back
to the original whitepaper) for creating a type of “rebindable” bitcoin
transaction that dramatically simplifies the protocols for LN by getting rid of
a lot of the complexities around storing state and closing channels
unilaterally. AnyPrevout helps make Decker Channels possible (or, confusingly,
sometimes called Eltoo not to be confused with L2).
The basics of how Anyprevout works is that it changes what parts a signature
signs to exclude the specifics of the coin being spent. This has some drawbacks
in terms of changing current invariants true of signatures, but it is generally
safe.
APO can also be used to implement something similar to CTV, but there are
sufficient differences between the two (including with respect to efficiency)
such that the proposals aren’t competitive.
APO is currently a decently reviewed BIP pending more support from the community
for inclusion. The largest blocker for wider support is a concrete functional
prototype of LN with Decker Channels, which would drive surety that APO has
“product market fit”. Certain developers believe that additional proposals, like
SIGHASH_BUNDLE, would be required to make it fully functional.
- My BIP-118 Review
- The BIP
- Eltoo/Decker Channels
- Templates, Eltoo, and Covenants, Oh My!
TLUV TapLeafUpdateVerify
TLUV is a proposed general purpose smart contract opcode that is open ended, has
dynamic local state, recursive, and is somewhat computational.
Essentially, TLUV lets you modify a Taproot Output being spent by changing the
toplevel key and script paths being spent. TLUV only can read and affect a
single input/output pair; the other outputs are unaffected. The functionality of
TLUV is very “specific” to the implementation details of Taproot, as it must
correctly modify the data structures behind it. For Example, you could have a
Taproot output with 10 coins and a script like:
[{"amt": 10,
"key": "multi(A,B,C)",
"scripts": ["signed(A) with up to 2 coins",
"signed(B) with up to 5 coins",
"signed(C) with up to 3 coins"]
}
]
and TLUV would enable you to transition to the following outputs:
[{"amt": 9,
"key": "multi(A,B,C)",
"scripts": ["signed(A) with up to 1 coins",
"signed(B) with up to 5 coins",
"signed(C) with up to 3 coins"]
},
{"amt": 0.25,
"address": "someone paid by A"
},
{"amt": 0.75,
"address": "someone else paid by A"
}
]
or even a full exit:
[{"amt": 9,
"key": "multi(B,C)",
"scripts": ["signed(B) with up to 5 coins",
"signed(C) with up to 3 coins"]
},
{"amt": 0.25,
"address": "someone paid by A"
},
{"amt": 0.75,
"address": "someone else paid by A"
}
{"amt": 1,
"address": "A's key (exiting funds)"
}
]
There are some potential footguns around modifying the top level key, as it
needs to be a valid Taproot key after tweaking.
TLUV as designed requires some form of OP_AMOUNT to enable the
recursive shared UTXO shown above.
There is no current concrete proposal (e.g. BIP) for TLUV, it’s open ended
research presently.
- Optech
- Mailing List
- My Mailing List Response
CSFS CheckSigFromStack
CheckSigFromStack, or CheckDataSig (note for experts: usually shorthand for the
verification-only version as there’s little point to check that something wasn’t
signed by someone) is an opcode which checks an arbitrary message was signed by
a key. Normally, when a Bitcoin script checks a signature, the message must be
a hash of the current transaction computed in accordance with the requested
transaction hashing program.
CSFS has a couple “basic” applications that could be useful. For example, one
might write a program where either a key K signs a transaction normally, or it
signs a key which then signs a transaction. This allows the holder of a coin to
“delegate” the ownership of a coin to another key without moving the coin.
CSFS already exists in Bitcoin in some sense: using Lamport Signatures it is
currently possible to check a signature over 5 bytes of data. This is not
terribly useful, but one could imagine certain uses for e.g. delegating to the
specified signer the duration of a timelock.
CSFS really shines when it is combined with other opcodes. For example, CSFS
plus CTV can enable something similar to AnyPrevout and Eltoo. CSFS plus CAT
enables fully generic covenants in segwit V0, but not in Taproot (without some
sort of OP_TWEAK as well). This is best left to reading some additional
materials on the subject, but imagine if I first check the transaction signature
normally, and then I check it on the stack against the transaction itself pushed
onto the stack, which I used CAT to assemble from pieces. This would let me run
programmatic checks on all the components of a script).
While there is not currently a proposal for CSFS, it’s not terribly
controversial and the design would be relatively straightforward.
- BIP Suggestions
- Templates, Eltoo, and Covenants, Oh My!
- CSFS from Math (5 bytes)
OP_AMOUNT
OP_AMOUNT was proposed in 2017 by Johnson Lau (the earliest citation I could dig
up) through a scripting extension called PUSHTXDATA that allows arbitrary data
to be pushed on the stack. As a standalone extensions, getting the amount
spent/created on the stack (whether as a push opcode or an opcode with verify
semantics) would allow for smart contracts to either limit the amount being
spent or switch behavior based on the amount.
For example, with TLUV a Taproot branch can have an individual balance that can
be updated at the discretion of the branch holder. Suppose I had a script tree
that said Alice has 1 bitcoin and Bob has 20 Bitcoin. When Alice is spending,
the script would require that the corresponding output (e.g., input 0 output 0)
be reduced by at most 1 Bitcoin, and the output should be updated to change
Alice’s script to have 1-(spent amount) in the next instance.
As another example, CTV could be used with an OP_AMOUNT to enable a ultra high
security vault if the amount sent is greater than 1 Bitcoin and a lower security
vault if it is less than 1 Bitcoin.
There’s no current concrete proposal for OP_AMOUNT. Difficulties in adding it
remain because Bitcoin Scripts deal in 32-bit math and amounts are 64-bit values
(51 bits precisely).
- OP_PUSHTXDATA
- OP_IN_OUT_AMOUNT
SIGHASH_BUNDLE
Sighash Bundle is a part of an effort to make “Sighash Flags” more general.
Sighash Flags are a mini “programming language” to describe what parts of a
transaction a signer wants to sign for a transaction. Bundles in particular
allow a signer to select a range of inputs and outputs in a way that the bundle
description can be rebound to allow some form of post-hoc aggregation of
transactions.
It’s primarily proposed to help make Decker Channels work with a sub-protocol
called “layered commitments”. It’s possible for inclusion, but it has the same
issue as AnyPrevout, we need to see an end-to-end implementation of LN using it
to be sure that the technology is solving the problem it is designed to.
There’s no concrete implementation proposed yet.
- Mailing List Post
Transaction Sponsors is another proposal by yours truly.
The basic concept of Transaction Sponsors is to allow expressing logic that
Transaction B should only be in a block if Transaction A is also in the block.
In particular, the proposal says that a transaction with a 0 value output with
script OP_VER <txids>
would make the transaction valid only if the txids were
also in the block.
The ability to express such a dependency has implications for designing novel
smart contracts based on these dependencies, but this is not the focus of the
sponsors proposal with respect to mempool policy.
Instead, the Sponsors proposal is to use the ability to express additional
dependencies as a way of dynamically adding fees to transactions in the mempool
without relying on CPFP or RBF. This primitive is particularly helpful for
driving progress of smart contracts based on CTV or Decker Channels without
requiring any sort of transaction malleability.
There is currently an implementation and Draft BIP of Sponsors, but the BIP has
not been advanced for inclusion yet.
- Mailing List Post
- Post about difficulties of paying fees
OP_CAT (Or SHASTREAM)
OP_CAT is “deceptively simple”. All it enables is the ability to take an
argument “hello “ and an argument “world” and join them together into “hello
world”.
CAT was originally a part of Bitcoin, but it had some implementation flaws and
was removed by Satoshi in an emergency patch early on in Bitcoin’s history.
Although it is simple, it turns out that the ability to join bytestrings
together adds a remarkable variety of functionality to Bitcoin, including things
like quantum proof signatures and covenants. There are a couple different
variants of CAT that would be possible and have different tradeoffs, but largely
CAT and friends are not controversial in their design. What does make CAT
controversial is that because it has the propensity to introduce so many
surprising behaviors in Bitcoin, we might prefer to better understand the
impacts of users being able to author such advanced smart contracts.
- Quantum Proof Bitcoin
- Poelstra CAT Blog I
- Poelstra CAT Blog II
OP_TWEAK / ECMUL
These two opcodes enable manipulating an elliptic curve point on the stack for
use in a covenant or to compute a particular private key.
There’s no concrete proposal for this pair, but the implementations are
basically specified already by the requirements of the secp256k1 curve.
Adaptor Signatures
Adaptor Signatures are a technique that can be used with Schnorr signature and
do not require any additional forks to Bitcoin.
The basics of an Adaptor signature is that a party (or group of parties) can
create an object which either takes in a signature and reveals a secret or takes
a secret and reveals a signature.
These adaptors can be used in place of hash preimage locks for a variety of use
cases.
- Optech
Delegation / Graftroot
Delegation is a general concept whereby you can take a script and instead of
signing a transaction, you sign another script that can then execute. For
example, imagine if there is a coin that requires a signature of Alice and Bob
to spend. Suppose Alice wants to go offline, but Bob might want to transact.
Alice could sign a script requiring a signature from Carol that “substitutes”
for Alice’s signature in the future.
Delegation is currently possible in a somewhat roundabout way through
coin-delegation. This is where the other script fragment must be represented by a UTXO.
Graftroot is an extension to Taproot which would let the top-level key-path
signers sign delegating scripts, but not other tapscript branches. There are
also several confusingly named extensions and alternatives in the links below.
Delegation could also be combined with Anyprevout so that delegation
authorizations are bound to a specific coin or to a specific script. CSFS
enables a basic kind of delegation as well. This would enable, with Graftroot, a
version of Taproot where the trees are constructed interactively and do not have
any lookup cost.
Other than what’s presently possible, there are no concrete proposals for adding
new delegation features to Bitcoin.
- Coin Delegation
- Graftroot
- Entroot
- G’Root (not graftroot)
BIP-300 DriveChains
Drive chains are a highly application specific type of recursive covenant that
is designed to help sidechains operate by tracking sidechain deposits and
withdrawals with an on-chain miner driven voting system.
The sidechains would have the ability to run arbitrary smart contracts (at the
choice of the sidechain operators). Miners the upvote, downvote, or abstain from
voting on withdrawals through a special output type.
One of the main downsides to this approach is that the BIP-300 proposal as
written requires the addition of new global state databases, rather than local
state contained within the covenant transaction itself.
Overall Drivechains are relatively controversial among the community; with lots
of interest from the community and also some outspoken critics because of the
changes to Bitcoin’s incentive stability for consensus. It’s included here for
completeness and by request of what topics to cover in today’s post.
It’s the author’s opinion that while the concept of Drivechains is useful, the
implementation of it does not need to be as transactions inside of the existing block
space and instead could be tracked via a separate commitment (like Segwit). This could
happen if Drivechains were implemented via a more generliazed covenant rather than
application specific.
- BIP-300
- Drivechains
Elements Opcodes
Elements is Blockstream’s Bitcoin fork for their Liquid Sidechain. Elements has
planned to add a broad variety of opcodes that can help to accomplish a variety
of tasks, including many of the above, in addition to their existing extensions.
- Existing Opcodes
- Upgrade for Taproot
Breathe! That was a lot! There’s still other stuff that’s floating around, but
these are the top-of-mind primitives in my head for bringing more
programmability to Bitcoin.
Future posts will zero in on what’s possible with BIP-119 and Sapio and help
make the case that it is a fantastic next step in Bitcoin’s Upgrade journey by
showing (not telling) how one little limited opcode opens up an entire world of
possibilities, as well as laying out a – dare I say – personal roadmap for the
inclusion and development of other upgrades as a coherent narrative for Bitcoin.
Day 7: Rubin's Bitcoin Advent Calendar
04 Dec 2021
Welcome to day 7 of my Bitcoin Advent Calendar. You can see an index of all
the posts here or subscribe at
judica.org/join to get new posts in your inbox
In this post we’ll review a concepts for thinking about different types of smart
contract capabilities and the implications of their availability.
Recursive v.s. Non Recursive
Recursive is pretty much just a fancy way of saying “loops”. This is sometimes
also called “Turing Complete”. That’s an even fancier way of saying loops. For
example, imagine a bitcoin contract with the following logic:
When Alice requests moving 1 coin to Bob by broadcasting a transaction with the
request, Alice has 24 hours to completely cancel the transfer by broadcasting
another transaction.
This is a looping contract because after cancelling Alice can immediately
re-request the transfer. An example of non-looping but similar logic would be:
When Alice requests moving 1 coin to Bob, Alice has 24 hours to cancel the
transfer by sending the coins to Alice’s backup key.
Here, the contract terminates after one canceled request by moving the coin
elsewhere. It’s possible to emulate recursive behavior a limited amount by
“unrolling” a loop. For example:
When Alice requests moving 1 coin to Bob, Alice has 24 hours to cancel the
transfer by sending the coins to (when Alice requests moving 1 coin to Bob,
Alice has 24 hours to cancel the transfer by sending the coins to Alice’s backup
key).
Here we substituted the backup key with a copy of the original logic. Now Alice
can make 2 cancellable requests before sending the money to the backup. This
looks recursive, and it can be expressed by a recursive meta-program. Meta
program is just a fancy term for a program that makes programs. But when we put
the contract into writing (e.g., an address on the chain), it has to be unrolled
for the specific number of iterations we want possible.
Unrolling is a very useful technique, and can be used in a broad variety of
circumstances. For example, imagine we unroll a contract a million times and
specify that transactions can only happen every 10 blocks. That covers like 200
years of contract execution. However, unrolling has it’s limits. When choices
(action A or B) are introduced, unrolling can be less effective since you have
and exponential blowup (that means unrolling even like 32 steps might be too
many). However, there are some tricks that can be employed by a clever and
careful programmer to reduce this complexity through, for example, memoization.
Fully Enumerated v.s. Open Ended
Suppose I have a contract which is supposed to strike an American option and
transfer a token. It might look like this:
If Alice is paid 1 BTC by December 25th, 2021 Midnight, then transfer 100 tokens
to Bob’s Control.
A fully enumerated contract would be expressed as:
If Alice is paid 1 BTC by December 25th, 2021 Midnight, then transfer 100 tokens
to Bob’s Address B.
Whereas an Open Ended contract would be expressed as:
If Alice is paid 1 BTC by December 25th, 2021 Midnight, then transfer 100 tokens
to the address Bob requested with the payment.
The key difference being that in the fully enumerated case we must know the
exact specifics of the contract and how it will execute, and in the open ended
contract case there are bits and pieces we can dynamically specify.
There are ways that a fully enumerated contract can emulate dynamic choice. For
example:
If Alice is paid 1 BTC by December 25th, 2021 Midnight, then transfer 100 tokens
to one of Bob’s Address B1, B2, or B3 at Bob’s discretion.
Now Bob can pick from one of three destinations in the future. However, these
options must have been known in advance (a priori). With an open ended contract,
the address could be generated after the fact (post hoc).
This is a separate concept from recursive or non recursive. A contract that
loops could loop through a set of fully enumerated states until reaching some
terminal predetermined “exit” state (e.g., a plain address). The option contract
described above is non-recursive, but can be open ended.
Client v.s. Consensus Validation
When you have a Bitcoin in an output, anyone who has run, say, Bitcoin Core can
tell that it is valid by seeing it in the UTXO set. But what happens if you want
to issue a token on top of Bitcoin with some set of unique rules? Bitcoin does
not know anything about these tokens, and so it would be possible to make an
invalid transaction (e.g., spending more value than you have). In order to
ensure the token is valid and not corrupt, one must trace every prior
transaction back to some “axiomatic” genesis transaction(s) minting the token.
These traces can be cached, but by default Bitcoin software will not enforce
that only valid transfers be made. We say that the token is Client validated
while the Bitcoin is Consensus validated.
Is one worse than the other? Not necessarily. While permitting invalid
transactions in the chain seems bad, as long as the invalid transactions can be
uniformly excluded by all who care about the token it is not much worse than the
work you do to run a Bitcoin full node anyways. There does seem to be some value
in the Bitcoin network preventing you from making invalid transactions, but the
network doesn’t stop you from making bad transactions (e.g., you could send
money to the wrong place).
Client side validation can check all sorts of properties, not just tokens. For
example, you could write a contract for an on-chain governed company and check
transactions for valid state transitions amending the rules.
The main drawback to client side validation comes when you want your contract to
interoperate with Bitcoin values. While client side validation can burn tokens
that are transferred invalidly, imagine an exchange contract that swaps Bitcoin
for Token. If the exchange contract sends more Bitcoin than it should, the
clients can tell that it was an invalid transaction but the Bitcoin is still
gone. Thus Client validated contracts are best left to things that don’t hold
Bitcoin. The exception to this rule is if the Client validated contracts admit a
custodian, a special monitor or set of monitors that handle the contracts
Bitcoin balances in e.g. a multisig. The monitors can client-side validate the
contracts and sign off on any balance transfers. The drawback to this approach
is trust, but in certain applications that we’ll see later the monitor could be
all of the participants themselves, which makes the application of the rules
trustless.
Validation v.s. Computation
Validation and Computation are two sides of the same coin. A simple example to
demonstrate:
Type |
Task |
Input |
Output |
Computation |
Sort the numbers [4,5,1] |
None |
[1,4,5] |
Validation |
Check that [4,5,1] is sorted by indexes A |
A = [2,0,1] |
True |
Validation is a computation, but hopefully it’s easier to perform the
validation computation than the computation itself.
In a Bitcoin transaction we are always validating that the transaction was
approved. A transaction in Bitcoin makes a clear precondition (the coins spent)
and postcondition (the coins sent). Even in cases where we have to do a lot of
computation to check the authorization, we still know the proposed outcome.
Compare to an Ethereum transaction: We pass some input to a function, and the
EVM verifies that our input was authorized (e.g., send 1 Eth to contract X with
message “hello”). Then, the side effects of that action are computed dynamically
by the EVM. For certain contracts, we might be able to predict what the side
effect will be (e.g., a 1:1 token exchange like Eth to Wrapped Eth), but for
other contracts (e.g., a floating exchange rate for Eth to Wrapped BTC) we will
get an outcome that can’t be fully predicted. It is possible for contracts to
choose to engineer themselves in a way to create more predictability, however in
Ethereum this does not result in an Invalid transaction, it results in a valid
transaction (that e.g. still costs gas) that has a result which is not taken.
For example, a transaction which says “Buy 1 WBTC for 15 ETH” might fail to
acquire WBTC since the price is now 16ETH, but the transaction would be valid
that you tried to make the trade and failed. This is because Ethereum’s base
layer is computational in nature with little validation: validation must be
built on top.
Sidenote: Malleability
For certain Bitcoin “covenant” transactions the validation/computation line can
be thin. Transactions must always be transactions in a block, but it’s possible
that in the future miners could receive “details” of a transaction and be
responsible for generating the appropriate transaction themselves. For example,
Blockstream released details on a noninteractive
feebumping
transaction, whereby a miner can dynamically compute a transaction that pays
them more fees the longer it takes to confirm.
In the case of malleability like this, it’s not as simple as saying “don’t do
it”, because miners have an incentive to extract the value if it is available.
Dynamic State
Contracts can have different types of state. State is just a fancy term for
information available to execution.
Global state is information that is observable from anywhere. An example of this
in Bitcoin is the UTXO Set: any transaction could spend any coin, and can “pull
it into scope” by naming it’s Outpoint (whether or not the transaction is valid
is another question). Another example of global state is the current block
height, used for validating things like lock times. In Ethereum, there is a much
expanded concept of Global state whereby contracts persist and allow read/write
access from other contracts, and unlike Bitcoin’s UTXO set, observing a piece of
information doesn’t destroy it like spending a coin does.
Local State is information observable only within your own context. For example,
a contract might hold balances for 3 different people, but the current values of
those split balances is not something queryable by outside parties. This also
includes implicit state, such as “the contract is currently pending an Action
from Alice” that are not explicitly coded.
Lastly, certain things are not State. An example of this is an authorizing
signature, which is ephemeral data that is used in the transaction execution but
does not have relevance for the continued execution of the contract and is not
particularly observable (which signature we use shouldn’t matter).
General v.s. Specific
A General contract primitive is something that can be used across many different
types of contract. A Specific contract implements well defined logic. In Bitcoin
and Ethereum, the focus is on General contract primitives that can be used many
ways. In some other ecosystems (e.g. NXT, Stellar), contract primitives have
much more specific functionality.
General/Specific ends up being more of a spectrum than a binary. Certain
contract primitives might be very specific but find general use, similarly some
general primitives might be more general than others.
For example, the Lightning Network on Bitcoin has pursued a path of using
general purpose extensions to Bitcoin so as not to “special case” payment
channels. But is that worth it? Might Payment Channels be cheaper, easier to
use, etc if we just designed built-in channels from the get-go? Perhaps yes, but
then it might be harder to embed other things or incorporate new innovations
into Lightning if it had to fit a single mold.
This isn’t an exhaustive list of topics by any means, but it should be a good
primer for thinking about upgrade proposals that people discuss in Bitcoin.
You’ll find out more about that in… tomorrow’s post!.
Day 6: Rubin's Bitcoin Advent Calendar
03 Dec 2021
Welcome to day 6 of my Bitcoin Advent Calendar. You can see an index of all
the posts here or subscribe at
judica.org/join to get new posts in your inbox
Now that we’ve established the four pillars of Privacy, Decentralization, Self
Custody, and Scalability, let’s get into smart contracts. But first…
DOES BITCOIN HAVE SMART CONTRACTS?
There is a lot of fuss around if bitcoin has or doesn’t have smart contracts,
and this is usually people talking past one another. Bitcoin does have enough
functionality to create certain smart contracts. But Bitcoin does not “have
Smart Contracts” in the same way that, say, Ethereum “has” Smart Contracts.
Sure, one can argue that because Ethereum is weaker in terms of its fulfillment
of the four pillars, it doesn’t really have smart contracts either. But almost
undeniably there is something happening in the Ethereum Ecosystem that isn’t
happening for Bitcoin – yet.
Often, Bitcoin Boosters will say that the types of things happening on Ethereum
aren’t desirable at all and are just scams. Many of these Boosters then go on to
promote projects of similar dubious nature… but that’s off topic for this post!
While there are many projects that frankly suck, there are also many projects on
Ethereum that are relevant to the interests of Bitcoiners! Examples of projects
that advance Ethereum’s realization of these 4 pillars that would be difficult
to build on Bitcoin include: Gnosis Safe for Custody; Tornado Cash for Privacy;
Optimistic/Zero Knowledge Rollups for scalability; SmartPool for on-chain mining
pool coordination. It’s claimed that any time something of value proves out in
the other ecosystems, Bitcoin can easily just incorporate the highlights.
My position is somewhat unique on this matter: Smart Contracts aren’t something
you build on top of a layer with good decentralization, privacy, scalability,
and self custody – Smart Contracts are a central part of what makes achieving
those pillars possible! In other words, we need a Smart Contract ecosystem that
enables broad innovation in order to make our four pillars robust. This is not
the same as saying we need the Ethereum VM, but we do need something to be
different than the status quo today to empower builders to create new tools on
top of Bitcoin. This differs from a traditional Bitcoiner perspective which is
more along the lines of once we improve our (insert generic property here); then
we can consider figuring out how to add more smart contracts.
That bar sucks it’s too crowded
Another reason sometimes given for not wanting smart contracts is that they’re
too expensive and won’t scale. While this is a valid concern, the story around
fees is somewhat interesting. You may have seen people complain about high fees
on other platforms and say therefore it sucks and should die. It’s a bit like saying
a crowded bar is no good. Obviously, if people are at the bar it is good. That
your enjoyment is less is solely because you’re antisocial. On other platforms,
there are users paying exorbiant fees to do transactions… but would they be
doing them if they weren’t getting commensurate value? Let’s have a look at some
data from cryptofees.
Name |
1 Day Fees |
7 Day Avg. Fees |
Ethereum |
$62,620,320.03 |
$55,285,528.00 |
Uniswap |
$11,315,687.79 |
$10,507,247.12 |
Binance Smart Chain |
$7,240,187.13 |
$7,525,565.73 |
Balancer |
$1,572,934.46 |
$445,368.69 |
Aave |
$1,465,761.04 |
$1,354,792.55 |
SushiSwap |
$1,379,856.87 |
$1,664,071.03 |
Bitcoin |
$1,160,676.57 |
$730,368.10 |
Clearly a lot of folks are willing to pay for Ethereum and projects on top of
it. Bitcoin is ultimately a business, and it relies on its customers paying fees
to incentivize the production of blocks. More fees, more incentive to provide
security for Bitcoin. It’s a little problematic, therefore, when users are
getting more utility from (by virtue of how much they are spending) other chains
than Bitcoin.
Although we need to be careful to not hurt Bitcoin’s essential properties, it’s
clear that smart contracts provide massive leverage for incentivizing users to
do transactions to pay for block production, without which Bitcoin falls apart.
Capitalist or Communist?
The last point I’ll leave you with is perhaps a bit charged / “problematic”, but
I think it’s a good one. Bitcoin is a bit like America. Ethereum is a bit like China.
Provisionally, America is the Free Market Capitalism country and China is the
State Controlled Communist Markets country. In practice, if you visit a market
in China there seems to be a lot more capitalism than in the US. Tons and tons
of small businesses, operating with (seemingly) little regulation. On the other
hand, in San Francisco you can spend
$200k
trying to get permits for an Ice Cream shop and fail. On the flip side, in the states once you’re
successful and operating it’s pretty darn hard for the government to substantial interfere.
In China, your CEO might vanish for a few weeks like Jack Ma.
Bitcoin is a bit like America. Building on it is incredibly hard, but if you
figure it out and crack the code it’s supposed to work forever and devs bend
backwards to ensure your use case won’t break.
Ethereum is a bit like China. Building on it is incredibly easy – at first –
but if what you’re doing violates the “social order” your thing will get rekt by
king VB with EIPscallibur. Examples of this include the removal of refunds for
clearing space which bricked a popular gas fee arbitrage token.
Now, obviously this description is tinged with preference. I love America.
Best country in the world (or, rather, terrible country, just better than all
the other terrible countries). However, Bitcoin is not America and Ethereum is
not China. There can be a middle road, and benefits from such an approach as
well. Smart contracts seem to be really good at enabling permissionless
innovation. Permissionless innovation is great for capitalism! Capitalism is
great for improving utility of users and coordinating people. Wouldn’t it be
nice if building on Bitcoin didn’t require getting proposals passed the
developer “commitiburo” and more innovators picked Bitcoin as the best chain to
build new ideas on top of? Obivously we don’t want to sacrifice the other parts
that make Bitcoin great, but we can still entertain the types of economic
benefits we would see by enabling more permissionless innovation. Because
ultimately, and perhaps tautologically…
As described, Bitcoin has certain positive and negative properties. Ethereum
too. At the end of the day, in aggregate, what “matters” is what participants
choose to use and rely on through a free market selection process. That’s why
despite not offfering the playground of Ethereum, Bitcoin has something that
people value more: stability. However, stability and stagnation are two sides of
the same coin. Stagnate for too long and competitors will eat your lunch. And
perhaps the stability that makes Bitcoin unique will eventually be convincingly
present in other ecosystems, despite Bitcoin’s head start in that endeavor.
Spooky Scary!
In the coming posts we’ll review the concepts more in depth, the state of the
art research for Bitcoin Smart Contracts, and get into some examples of useful
Bitcoin contracts.
Day 5: Rubin's Bitcoin Advent Calendar
02 Dec 2021
Welcome to day 5 of my Bitcoin Advent Calendar. You can see an index of all
the posts here or subscribe at
judica.org/join to get new posts in your inbox
Privacy is foundational to Bitcoin. Fundamentally, we care about censorship
resistance so folks can’t stop you from doing activity they can tell you’re
doing… but what if they couldn’t tell you were doing anything at all? The more
private a system is, the better it is at ensuring that all participants are free
to do as they wish.
Unfortunately, privacy is one of the most difficult things to achieve in the
universe. For every action there is an equal and opposite reaction; if one wants
to make an action, how can one ensure the reaction is not observable? And if one
masks the reaction, how can one hide the masking?
Privacy exists in a delicate position in our society. America is hands down the
leader in rights to privacy of any society, but citizens still face a barrage of
assaults against their privacy. Privacy from the government also differs from
privacy from corporations, and the corporations often times can be in cahoots
with the government. Some regulatory regimes (e.g., the EU) claim to be “better
on privacy” than America, but have overall a weaker sense of individual rights
than in America (so they may be better at the privilege of privacy, but not at
the right to it).
Why is privacy so delicate? In part, because unlike speech there’s no explicit
enumerated right to privacy. Privacy is an unenumerated right under
the American constitution. What this means is that legally we do believe it to
be a right because it seems to be implied by other constitutional protections
that could not exist without it (e.g., the right to not be searched without due
process). Because there’s not explicit protection of privacy, it’s a constant
battle to determine what constitutes an violation of privacy. For example, if
your house is extra hot because you’re growing pot in it (or hint hint Bitcoin
mining), can police use thermal cameras to detect it and then establish probable
cause to get a warrant and raid your house? See Kyllo v. United States, that’s
an illegal search baby! However it’s possible that this line would erode over
time as the expectation of privacy changes – if everyone had thermal camera
sunglasses and could see your pot growing plain as day, maybe it’d be
unreasonable to think
you’re private!
Cryptographic research has yielded amazing tools for creating provable privacy
for digital actions. For example, it’s possible to send a digital message in a
manner such that only the intended recipient can read it. And as long as your
spying adversary isn’t standing over either of your shoulders looking at your
screen (or more realistically, running a scanning program on all your data like
the one Apple said they might be doing earlier this year), the only people who
will know the contents of the message are you and the recipient.
The government kinda sorta hates this stuff!
Because the bad guys can use it! But, because America is super free privacy
loving country, citizens still have a basically unlimited protected right to use
whatever privacy technology they want. Many politicians have mentioned wanting
backdoors into software, but none have truly succeeded to introduce much truly
limiting. Not to mention you can’t make math illegal, which is all that
cryptography is. Alphabet soup agencies resort to trying to insert backdoors,
but these are still subject to public review and the information revealed could
only really be used legally for big “national security issues” like against a
group with a pre-existing warrant, but the general collection of information
would be illegal under the expectation of privacy right. At least in theory –
Snowden showed us that mass data collection
does still happen… But cryptography gets better, and open-source supply chain
devices become better, so inserting backdoors in the code becomes harder and
harder.
So great, probably solved for Bitcoin, right? Just Crypto It. Not quite. While
systems like ZCash do exist that make transactions much more private, they take
up more space, so they decrease the availability of block space… however,
perhaps with better privacy, there’s less ability to discriminate against
different transaction sources, so less decentralization is needed to guarantee
censorship resistance.
This points to another conflict, which arises with privacy: auditability v.s.
transparency v.s. Deniability.
An auditable system means that anyone can verify the history of all transactions
and check for validity transparently. Many bitcoiners have a preference for
“elementary school math”, where validating the transaction record requires very
basic math in the code, and not much else. However, if you go to a fully
encrypted form, you might no longer be able to easily check important rules like
the amount of coins not being increased through a crypto backdoor. This type of
auditability where you could “do it by hand on a calculator” we’ll call
transparency, since you can see everything! If it were encrypted, it would be
opaquely auditable. You could tell it’s valid, but not the specific transfers
that happened. Maybe no one person is going to look through all the data, but
across all humanity someone is bound to audit at least the transactions they’re
involved in.
Deniability stands in contrast to either of these properties. If, say, a
government agency comes to you and says “hey, we know you controlled key X,
please show us all transactions that X was involved in”, a deniable system would
allow you to produce any answer, making such a query useless. However, if a
system was strongly deniable like that, it would be very hard to audit because
the audit could potentially turn up differing results. So Bitcoin transactions
aren’t particularly deniable by default.
One of the drawbacks of Bitcoin’s auditability is that the auditability is
forever. So if you have a lapse of privacy, all your old information can be
checked. So let’s say you bought a coffee in 2021, and in 2055 the government
decides all coffee drinkers are going to go to jail to pay for their drug use
sins, then your old cafe might be able to reveal you as a customer. Bitcoin
never forgets.
It’s My Data and I want it Private Now
Therefore it’s an urgent priority to make Bitcoin as private as possible as soon
as possible in order to keep users safe now and forever, or else the fundamental
usability of the system is at risk. However, compromising on auditability or
decentralization would be unpopular, so it’s not as simple as adding ZCash and
increasing block space.
There are a lot of different pathways Bitcoin can take to increase privacy. For
example, the lightning network can mask and make many payments ephemeral, as
well as adding deniability if one continually signs false histories of revoked
txns. Sidechains can add all sorts of privacy primitives, if they want. And
on-chain techniques like swaps or joins can be used to make the base privacy
better as well.
In future posts we’ll explore how covenants can have a role in improving
privacy!
Day 4: Rubin's Bitcoin Advent Calendar
01 Dec 2021
Welcome to day 4 of my Bitcoin Advent Calendar. You can see an index of all
the posts here or subscribe at
judica.org/join to get new posts in your inbox
Many may have tried, but few have successfully characterized what “being
decentralized” means in an objective / quantitative sense. Instead, we’re left
with soft “know it when I see it”s.
Decentralization may be a pillar of Bitcoin with a lotta fanfare, but it’s still
just a means to an end. It’s about the Pantheon, not the pillars! A system can
be very decentralized and still kinda suck. Much like pillars with no roof won’t
keep the rain out!
Got Gas?
For a more than slightly contrived example, imagine a pre-internet driver
navigating gas stations prices. Kind of “decentralized”, right?
Users/purchasers operate on local information to see pricing and make a decent
decision, and sellers operate on local information to stay competitive. Over
time the network should “converge” a sellers learn who has better prices
throughout town, but from the perspective of an individual purchaser it’s really
hard for them to determine within their remaining tank range/willingness to
drive across town for a dollar who has the best prices. So while the market
works as a decentralized pricing system, it’s not highly consistent!
It’s Hard; No CAP
Computer network nerds have three rules for keeping their jobs: consistency,
availability, and partition tolerance. What do these mean in practice? Thinking
back to our gas analogy, gas stations are very available (you can always get gas
at some price), they’re strongly partition tolerant (i.e., if you can’t see
other gas station’s advertised prices you won’t know if it’s better, but you can
still get gas). But the pricing might be all over the map! No consistency!
It’s really hard to achieve all three properties – there even exist proofs of
its impossibility. Instead, engineers make tradeoffs to achieve different
amounts of guarantee across the properties.
For Bitcoin we care a lot about consistency. If I send money to
Alice, I should not be able to send it to Bob. We also care a lot about
partition tolerance. If some group of participants should shunt themselves out
from others, the system should still operate? So do we inherently care less
about availability? Well, kinda! If the “blockchain is closed” and you can’t
transact, at least you still have your money. And technologies like Lightning
Network can help bridge the gaps if the Bitcoin blockchain is unavailable that
you can still fully confirm transactions as long as it comes back eventually.
So, interestingly, Availability seems like the property we need to care about
the least… but it’s one of the main reasons we need decentralization! That’s
because even though we might have a design that elevates the other two
properties, it doesn’t mean that availability is unimportant. And availability
is not one monolithic level, there are many different types of availability
fault one might experience on a network. For example, you might experience
reduced or no availability if:
- The network doesn’t have blockspace at your price
- The internet is down
- Your usual peers are offline
- Theres a fire at a major data center
- Your battery on your phone dies
- A big solar flare happens
- An evil government changes your DNS records to your mining pool and you don’t know the IP address
- An evil government runs the network entirely and doesn’t like your transactions so they get censored.
Some of these problems, decentralization can help us with! Some,
decentralization can’t help with. And some are caused by decentralization. Uh
oh!
For example…
A fire a major data center can be defrayed by being more decentralized – a fire
can only spread so far! The other data centers should be fine, since Bitcoin is
partition tolerant, the overall network is available.
If a big solar flare happens, there’s not much any of us can do if all the
internet is down and our devices got fried. Too catastrophic… We can recover
eventually, your metal seed plates will be fine, but hopefully someone had some
Faraday cage shielded backups.
If blockspace is too expensive, decentralization may be the cause!
In order to keep the network decentralization friendly, Bitcoin uses far less
bandwidth and storage than a centralized system (like Google) could use. This
ensures that participants on the network need not be particularly well resourced
or well connected to be a meaningful, full participant in the Bitcoin Network.
That’s because of another availability issue: censorship. Bitcoin fundamentally
stands as a fuck-you to the entrenched powers that be. As such, Bitcoin uses
decentralization to guarantee censorship-resistance against state actors. While
there’s been much ink scaled about the censorship of scalability v.s. the
censorship of state actors, Bitcoin is hyper focused on providing some form of
“equal protection”.
Everyone hates that you lose availability from high tx prices, and all are
equally affected. Everyone hates solar flares, and all are equally
affected. But with state actor censorship, enemies of the state, be they Jews,
Conservative Non-Profits, Black Americans, Gazan Chocolatiers, People who
believe things posted on *******’s Twitter Account etc, can be picked
apart and subjected to selective abuses. If anyone can run a node (and
hopefully miner), and most people don’t have a political agenda, we can maybe
protect individuals of any background.
As such, Bitcoin’s decentralization is focused on censorship-resistance, even at
the expense of on-chain availability.
The Neverending Story
The story doesn’t end there. Decentralization, as we noted earlier, is very
tough to quantify. Even if we can’t quantify it, we can still reason about
decentralization efficiency. Given the “costs of decentralization”, how much
censorship resistance do we get? Can we decrease the costs and achieve the same
amount? Can we keep the cost the same and gain more censorship resistance?
Or… do we need to increase the costs, because we’re not censorship resistant
enough? Stay tuned for future posts we’re we’ll see if we can’t do something
about it!