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:
0x01
or0x01A
where A is a 32-bytes string. I think that A is a Schnorr tweaked public key, namely the x-axis component of the pointQ=P+hash(P||h)⋅P
, where P is a Schnorr public key (see 7 for a description on tweaked key) andh
is the hash of some scripts
(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?). Callx
the private key, soxG=P
, whereG
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.
- A signature
(R,s)
(made by internal private keyx
that corresponds top
) appears in the partd
above. This signature commits to all outputs, to all inputs' amounts but not to any reference to the previous inputs; thehash_type
of the signature should be0xc0
, that corresponds toSIGHASH_ANYPREVOUTANYSCRIPT
(actually,SIGHASH_ANYPREVOUT
commits to the inputs' references, as I understood; see 9). - Now, in the script
s
should appear a sort ofOP_CHECKSIG
, that checks the signature(R,s)
against the internal pubkeyp
.
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 signatureSIGHASH_NONE|ANYONECANPAY
in the case that the input is P2PKH, or the witness, if the input is segwit, that should contain again someSIGHASH_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?