I am entered the world of bitcoin recently and currently I am studying the broad area of covenants (that are gaining more attention from the community, see 1). In this context, certainly the BIP-0118 is relevant.

Assume hypothetically that BIP-118 is active, suppose that a payee wants to precompile a transaction tx with ANYPREVOUT. The transaction tx makes no explicit reference to any input to be spent and will be presented later to the payer to be signed. Assume that tx is built to consume an unspent output of the payer and the amount is completely transferred to the payee, without change. So, tx will have one input and one output. I would like to understand how this transaction tx should look like and how this should be used in practice. I discuss below my idea about, hope to find someone that corrects me or improve my understanding. In the following, we assume that the fees are zero.

As I understood, tx produces a P2TR output that is spendable only via the script-path (see taproot BIPs 3, 4 and 5 or 6 for a brief anatomy of P2TR outputs or inputs). The receiver address is a new type of address, that has this two possible forms:

  1. 0x01 or
  2. 0x01A where A is a 32-bytes string. I think that A is a Schnorr tweaked public key, namely the x-axis component of the point Q=P+hash(P||h)⋅P, where P is a Schnorr public key (see 7 for a description on tweaked key) and h is the hash of some script s (in general, h is the Merkle root of some Merkle tree, but I guess that in our case the Merkle tree consists in just one point/leaf, is this correct?). Call x the private key, so xG=P, where G is a generator of the elliptic curve.

Suppose for now that we deal with addresses of the form as in 2. So the payee address is version 1 segwit, and the witness program (the output of tx) has more or less the following form:

<h1> <h2> 0x01 <h3>

where h1 (int 64) is the amount in sat, h2 (var int) is the length of the following item and h3 is a 32-bytes string that represents the x-axis of the tweaked pubkey Q.

For spending the tx output is necessary to present a witness, that, by construction, has (strictly) more than 2 elements, see 8. In particular, the witness has the form:

<n> <d> <s> <c>

where n is the number of witness elements, d is the data for the following item s, that is the script (such hashed gives the h used to tweak the the pubkey) and c is the control block. The control block is of the form

0xc0 <p> <b>

where 0xc0 is the leaf version (didn't really understand it, has something to do with the idea "leave possibility to future upgrades", like the version byte of segwit?), p is the internal pub key, namely the x-axis of P and b should be a sequence of hashes that are used to reconstruct the merkel tree. So, in our case, b=h?

So far, hasn't appeared yet anything that tells us that the part of the transaction that is signed (by x, the internal private key of the payee?) does not include any reference to a previous input (even though it should include the input amount, the function that calculates this part of the message signed should be SigMsg118(hash_type,ext_flag) ). So, I suppose that the script s does the ANYPREVOUT-job in the following way.

  1. A signature (R,s) (made by internal private key x that corresponds to p) appears in the part d above. This signature commits to all outputs, to all inputs' amounts but not to any reference to the previous inputs; the hash_type of the signature should be 0xc0, that corresponds to SIGHASH_ANYPREVOUTANYSCRIPT (actually, SIGHASH_ANYPREVOUT commits to the inputs' references, as I understood; see 9).
  2. Now, in the script s should appear a sort of OP_CHECKSIG, that checks the signature (R,s) against the internal pubkey p.

Nevertheless, p appears in the control block c, that is after s, and actually the pubkey p is a data for the script and should appear also in d. There is something that I am missing in the logic.

So far, I discussed how to spend the output of the transaction tx that uses ANYPREVOUT. But before this, tx has to be validated and for doing so, it must consume some input. As mentioned in the beginning of the question, once tx is created as above, it is sent to the the payer, that puts the inputs's missing data. So, he adds to tx the following:

  • the inputs' reference, namely a previous transaction hash and the index of the unspent output that it is going to be consumed;
  • the signature of the input with sighash-type SIGHASH_NONE|ANYONECANPAY. For instance, the unlocking script with a signature SIGHASH_NONE|ANYONECANPAY in the case that the input is P2PKH, or the witness, if the input is segwit, that should contain again some SIGHASH_NONE|ANYONECANPAY-part (actually it can be any king of input, not just P2PKH or P2WPKH)

Now, there is one more problem, namely that the payer is supposed to have an unspent output of the exact value of the funds he wants to send to the payee. Suppose that this is not the case and the payer has only unspent outputs of larger amounts. So, a change is needed and the transaction tx will have two outputs as before. The change is an output as before, that requires the machinery of BIP-118 to be spent. So, it is correct to say that the payer signs the transaction only if his wallet is BIP-118-aware?

One last question. In 10, Michael Folkson kindly explained me how BIP-118 deals with public keys of the form 0x01. But how they are supposed to work in this context? How all the machinery I discussed above works with BIP-118 1-byte public keys?

  • 1
    I'll make some edits later but where you say "address" you should be saying "public key". BIP118 defines a new public key type but doesn't make any changes to the address format (bech32m). Jul 29, 2022 at 10:15
  • I think you misunderstand sighash flags too. "The transaction tx makes no explicit reference to any input to be spent and will be presented later to the payer to be signed." The signer will choose to use a sighash flag like ANYPREVOUT (or SIGHASH_SINGLE, SIGHASH_ANYONECANPAY etc) at signing time and that will determine what the signer needs to sign. The transaction isn't constructed to be an ANYPREVOUT transaction and then presented to the signer. A transaction always needs inputs to spend but whether the signer signs those specific inputs is the question here. Aug 1, 2022 at 11:21
  • The functionality we want for protocols like eltoo is for that signature to be reused in a new transaction with different inputs without requiring a new signature. Aug 1, 2022 at 11:27
  • 1
    There can only be an ANYPREVOUT signature spending via the script path not the key path, yes. But there can be a non-ANYPREVOUT signature spending via the key path still. So in the unlikely scenario that the script path implementation was botched you could still spend from the key path with a non-ANYPREVOUT signature (assuming that a spendable key path had been encoded into the address) Aug 1, 2022 at 16:39
  • 1
    Right in protocols like Lightning and eltoo'd Lightning they require communication between Alice and Bob. In your example Alice needs to know the script that Bob encoded into the outputs of tx0 to be able to construct a transaction that spends those outputs. Aug 1, 2022 at 17:51


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.