Contracting Primitives and Upgrades to Bitcoin

Day 8: Rubin's Bitcoin Advent Calendar

on December 5, 2021

This post is syndicated from rubin.io.

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:

  1. Optech
  2. utxos.org
  3. Templates, Eltoo, and Covenants, Oh My!
  4. 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.

  1. My BIP-118 Review
  2. The BIP
  3. Eltoo/Decker Channels
  4. 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.

  1. Optech
  2. Mailing List
  3. 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.

  1. BIP Suggestions
  2. Templates, Eltoo, and Covenants, Oh My!
  3. 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).

  1. OP_PUSHTXDATA
  2. 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.

  1. Mailing List Post

Transaction Sponsors

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.

  1. Mailing List Post
  2. 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.

  1. Quantum Proof Bitcoin
  2. Poelstra CAT Blog I
  3. 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.

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

  1. Coin Delegation
  2. Graftroot
  3. Entroot
  4. 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.

  1. BIP-300
  2. 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.

  1. Existing Opcodes
  2. 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.


comments powered by Disqus