This week’s newsletter summarizes a discussion about a proposed new opcode and links to an updated wiki page for tracking bech32m support. Also included are our regular sections with highlights from a Bitcoin Core PR Review Club meeting, suggestions about preparing for taproot, and descriptions of notable changes to popular Bitcoin infrastructure projects.

News

  • Request for OP_CHECKSIGFROMSTACK design suggestions: Jeremy Rubin posted to the Bitcoin-Dev mailing list a draft specification for an OP_CHECKSIGFROMSTACK opcode and asked for feedback from any developers who would prefer an alternative design. Some alternatives were discussed, but the thread also branched off into a discussion about whether an OP_CAT opcode should be introduced at the same time.

    OP_CAT and OP_CSFS would enable arbitrary transaction introspection—the ability to receive bitcoins to a script that could check almost any part of the transaction that later spends those bitcoins. This can enable many advanced features (including versions1 of other proposed upgrades like SIGHASH_ANYPREVOUT and OP_CHECKTEMPLATEVERIFY), but OP_CAT also makes it possible to create recursive covenants which could permanently restrict the spendability of any bitcoins committed to the covenant. Some people have objected to allowing covenants in Bitcoin, but several arguments were made to the effect that the worst case problems of recursive covenants already exist in Bitcoin today so we shouldn’t be concerned about enabling OP_CAT or a similar opcode.

    Despite the discussion, Rubin decided he wanted to keep his OP_CSFS proposal independent of any proposal to add OP_CAT, arguing that OP_CSFS is useful enough on its own.

  • Tracking bech32m support: the Bitcoin Wiki page for bech32 adoption has been updated to track which software and services support spending or receiving to bech32m addresses for taproot.

Bitcoin Core PR Review Club

In this monthly section, we summarize a recent Bitcoin Core PR Review Club meeting, highlighting some of the important questions and answers. Click on a question below to see a summary of the answer from the meeting.

Use script_util helpers for creating P2{PKH,SH,WPKH,WSH} scripts is a PR by Sebastian Falbesoner which substitutes manual script creation with calls to script_util helper functions in functional tests and fixes an error in the get_multisig() function. The review club meeting broke down terminology and each of the script output types used in the PR.

  • What do key_to_p2pkh_script, script_to_p2sh_script, key_to_p2wpkh_script and script_to_p2wsh_script in script_util.py do?

    These are helper functions to construct CScript objects for Pay to Public Key Hash, Pay to Script Hash, Pay to Witness Public Key Hash, and Pay to Witness Script Hash scripts from public keys and scripts. 

  • Define scriptPubKey, scriptSig, and witness.

    The scriptPubKey and scriptSig are fields in the output and input of a transaction, respectively, for specifying and satisfying spending conditions. The witness is an additional field for the same purpose introduced with Segregated Witness. Spending requirements are committed to in an output’s scriptPubKey and the input that spends it must be accompanied by data satisfying those conditions in the scriptSig and/or witness. 

  • Define redeem script and witness script. What is the relationship between them?

    P2SH and P2WSH output types commit to a script hash in the scriptPubKey. When the output is spent, the spender must provide the script itself, along with any signatures or other data required to make it pass. The script is called a redeemScript when contained in the scriptSig and a witness script when in the witness. In that sense, they are analogous; a redeemScript is to a P2SH output what a witness script is to a P2WSH output. They are not mutually exclusive, however, since a transaction spending a P2SH-P2WSH output contains both. 

  • To send coins to someone with spending conditions encoded in a script, what is included in the scriptPubKey of the output? What needs to be provided in the input when the coin is spent?

    The scriptPubKey includes the script hash and opcodes to verify a match: OP_HASH160 OP_PUSHBYTES_20 <20B script hash> OP_EQUAL. The scriptSig includes the script itself and initial stack. 

  • Why do we use Pay-To-Script-Hash instead of Pay-To-Script?

    The primary motivation as stated in BIP16 is to create a generic way of funding arbitrarily complex transactions while placing the burden of supplying spending conditions on the one who redeems the funds. Participants also mentioned that keeping the script out of scriptPubKeys means its associated fees are not paid until redemption and results in a smaller UTXO set. 

  • When a non-segwit node validates a P2SH-P2WSH input, what does it do? What does a segwit-enabled node do in addition to the procedure performed by a non-segwit node?

    The non-segwit node never sees the witness; it simply enforces P2SH rules by verifying that the redeemScript matches the hash committed to in the scriptPubKey. A segwit node recognizes this data as a witness program and uses the witness data and appropriate scriptCode to enforce segwit rules. 

  • What is wrong with the P2SH-P2WSH script in the original get_multisig() function?

    It uses the witness script instead of its hash in the P2SH-P2WSH redeem script. 

Preparing for taproot #4: from P2WPKH to single-sig P2TR

A weekly series about how developers and service providers can prepare for the upcoming activation of taproot at block height 709,632.

For wallets that already support receiving and spending v0 segwit P2WPKH outputs, upgrading to v1 segwit P2TR for single-sig should be easy. Here are the main steps:

  • Use a new BIP32 key derivation path: you don’t need to change your BIP32 Hierarchical Deterministic (HD) code and your users don’t need to change their seeds.2 However, you are strongly encouraged to use a new derivation path for your P2TR public keys (such as defined by BIP86); if you don’t do this, there’s a possible attack that can occur if you use the same keys with both ECDSA and schnorr signatures.

  • Tweak your public key by its hash: although technically not required for single-sig, especially when all your keys are derived from a randomly-chosen BIP32 seed, BIP341 recommends having your key commit to an unspendable scripthash tree. This is as simple as using an Elliptic Curve addition operation that sums your public key with the curve point of that key’s hash. Advantages of complying with this recommendation are that you’ll be able to use the same code if you later add scriptless multisignature support or if you add support for tr() descriptors.

  • Create your addresses and monitor for them: use bech32m to create your addresses. Payments will be sent to the scriptPubKey OP_1 <tweaked_pubkey>. You can scan for transactions paying the script using whatever method you use to scan for v0 segwit addresses like P2WPKH.

  • Creating a spending transaction: all the non-witness fields for taproot are the same as for P2WPKH, so you don’t need to worry about changes to the transaction serialization.

  • Create a signature message: this is a commitment to the data from the spending transaction. Most of the data is the same as what you sign for a P2WPKH transaction, but the order of the fields is changed and a few extra things are signed. Implementing this is just a matter of serializing and hashing various data, so writing the code should be easy.

  • Sign a hash of the signature message: there are different ways to create schnorr signatures. The best is not to “roll your own crypto” but instead to use the function from a well-reviewed library you trust. But if you can’t do that for some reason, BIP340 provides an algorithm that should be straightforward to implement if you already have available the primitives for making ECDSA signatures. When you have your signature, put it in the witness data for your input and send your spending transaction.

Even before taproot activates at block 709,632, you can test your code using testnet, the public default signet, or Bitcoin Core’s private regtest mode. If you add taproot support to your open source wallet, we encourage you to add a link to the PR(s) implementing it on the taproot uses and bech32m adoption pages of the Bitcoin Wiki so other developers can learn from your code.

Releases and release candidates

New releases and release candidates for popular Bitcoin infrastructure projects. Please consider upgrading to new releases or helping to test release candidates.

  • LND 0.13.1-beta.rc2 is a maintenance release with minor improvements and bug fixes for features introduced in 0.13.0-beta.

Notable code and documentation changes

Notable changes this week in Bitcoin Core, C-Lightning, Eclair, LND, Rust-Lightning, libsecp256k1, Hardware Wallet Interface (HWI), Rust Bitcoin, BTCPay Server, Bitcoin Improvement Proposals (BIPs), and Lightning BOLTs.

  • C-Lightning #4625 updates its LN offers implementation to match the latest specification changes. Notably, offers are no longer required to contain a signature. This significantly shortens the encoded string for offers, improving QR code recognizability.

  • Eclair #1746 adds support for replicating data to a PostgreSQL database in parallel to the primary SQLite database. The feature is meant to facilitate testing for servers that want to make an eventual backend transition. Last year, Suredbits engineer Roman Taranchenko described customizing Eclair for enterprise-use with a PostgreSQL backend in an Optech field report.

  • LND #5447 adds a document describing how to set up multiple LND nodes in a cluster with an alternative database that is replicated between the cluster’s nodes and which allows for automatic failover. Interested readers may wish to contrast this with the approach taken by Eclair and described in Newsletter #128.

  • Libsecp256k1 #844 makes several updates to the API for schnorr signatures. Most notable is a commit that allows signing and verifying messages of any length. All current uses of signatures in Bitcoin sign a 32-byte hash, but allowing signing of variable-length data could be useful for applications outside of Bitcoin or to enable a new opcode such as OP_CHECKSIGFROMSTACK to verify signatures created for non-Bitcoin systems. It’s expected that the BIP340 specification of schnorr signatures for Bitcoin will be updated to describe safely signing variable length data.

  • BIPs #943 updates BIP118 to build on soon-to-be activated taproot and tapscript rather than SegWit v0. Additionally, this revision renames the title to SIGHASH_ANYPREVOUT from SIGHASH_NOINPUT to reflect that the sighash flag is now referred to as “ANYPREVOUT” given that while any prevout may potentially be used with the signature, some aspects of the input are still committed to.

  • BTCPay Server #2655 signals to web browsers that they should not send the HTTP referer field when the user clicks on a link to a transaction in a block explorer. This avoids telling the block explorer what BTCPay server the user came from—that information being strong evidence that the server either originated or received the transaction being viewed in the block explorer. Even with this change, users desiring strong privacy should still avoid looking up their own transactions on third-party block explorers.

Footnotes

  1. Using OP_CHECKSIGFROMSTACK (OP_CSFS) to implement the principle feature of proposals like BIP118’s SIGHASH_ANYPREVOUT or BIP119’s OP_CHECKTEMPLATEVERIFY would require more block space than those optimized proposals if scriptpath spending is used. The argument in favor of OP_CSFS is that it allows starting with a generic construction and proving that people will actually use the feature before a consensus change is used to add a more efficient implementation. Additionally, with the introduction of taproot keypath spends, any script can be resolved with the minimal use of block space in some situation, possibly reducing the need for specific constructions that save space in non-optimal situations. 

  2. When Electrum upgraded to segwit v0, it required anyone who wanted to receive to bech32 addresses generate new seeds. This was not technically required but it allowed the authors of Electrum to introduce some new features into their custom seed derivation method. One of those features was ability for a seed version number to specify which scripts a seed is meant to be used with. This allows safe deprecation of old scripts (e.g., a future a version of Electrum may be released that no longer supports receiving to legacy P2PKH addresses).

    Around the same time the Electrum developers were deploying their versioned seeds, Bitcoin Core developers began using output script descriptors to solve the same problem of allowing script deprecation (in addition to solving other problems). The following table compares Electrum’s versioned seeds and Bitcoin Core’s descriptors to the implicit scripts method previously used by both wallets and still in common use among most other wallets.

    Script management Initial backup Introducing new scripts Scanning (bandwidth/CPU cost) Deprecating scripts
    Implicit scripts (e.g. BIP44) Seed words Automatic (no user action required) Must scan for all supported scripts, O(n) No way to warn users that they're using unsupported scripts
    Explicit scripts (versioned seeds) Seed words (includes version bits) User must backup new seed; funds are either partitioned into two separate wallets or user must send funds from the old wallet to the new Only scans for a single script template, O(1) Users warned about unsupported scripts
    Explicit scripts (descriptors) Seed words and descriptor User must back up the new descriptor Only scans for the script templates that were actually used, O(n); n=1 for a new wallet Users warned about unsupported scripts