LearnBitcoin

Bitcoin Dev Archive 2025

Standard Unstructured Annex

7 messages, 20 Mar to 29 Apr 2025. Started by Peter Todd.

Peter Todd (3), Antoine Riard (2), Russell O'Connor (2)

Permalink Original thread on gnusha.org

Peter Todd permalink original

I'm working on adding support for the taproot annex to Libre Relay:

https://github.com/petertodd/bitcoin/commit/04c8e449a34e74e048bf5751d13592a22763ff7e

I'm basing this on Joost Jager's pull-req: https://github.com/bitcoin/bitcoin/pull/27926

Specifically, transactions containing taproot annexes will be standard if:

1) All non-empty annexes start with the byte 0x00, to distinguish them
   from consensus-relevant annexes. This ensures that any use of the
   annex will not conflict with future soft-forks that may assign
   meaning to the annex.
2) All inputs have an annex. This ensures that use of the annex is
   opt-in, preventing transaction pinning attacks in multi-party
   protocols. This requirement may be relaxed in the future, eg to allow
   spends of keyless outputs, and/or if RBF for witness-only
   replacements is implemented.

An example of a transaction meeting these requirements is:

010000000001011a559447098aaa14dec0c62ea55f43f9ce6bda07d1759f11b634334ab9da939b0000000000ffffffff010000000000000000076a05616e6e657802406840b6fa27a00ba001cc92797ce4f3ab7b7a32c21d1fce49e893b42e506bd92e8db187966a84ef799915cf671334cc59779915b192bfb66b2afcf384bb61d0f422500049276d20616e20616e6e6578212041726520796f7520616e20616e6e65783f0000000000

Antoine Riard in reply to Peter Todd permalink original

Hi Peter,

See also that can be relevant for taproot annex support: https://github.com/bitcoin/bips/pull/1381

Quoted text (4 lines)
> 1) All non-empty annexes start with the byte 0x00, to distinguish them
> from consensus-relevant annexes. This ensures that any use of the
> annex will not conflict with future soft-forks that may assign
> meaning to the annex.

So IIUC, it would be 1-byte: 0x00 | <random_data payload>.

Quoted text (5 lines)
> 2) All inputs have an annex. This ensures that use of the annex is
> opt-in, preventing transaction pinning attacks in multi-party
> protocols. This requirement may be relaxed in the future, eg to allow
> spends of keyless outputs, and/or if RBF for witness-only
> replacements is implemented.

I think it's good to start with all inputs have an annex. It avoids the kind of issue, like what if the annex size is inflated to downgrade the feerate of the multi-party transaction (e.g to have a coinjoin stucking in network mempools).

One thing that might be missed, without having looked to the code, is potentially a policy transaction-relay rule to limit the max size of the annex, to avoid the same concern than above. There shouldn't be max limit for now, as normally the annex is not standard at all as a taproot data field.

Best, Antoine OTS hash: 5b620c444896f05d05fe00542a4ac04c44f21684 Le jeudi 20 mars 2025 à 01:02:10 UTC, Peter Todd a écrit :

Quoted text (30 lines)
> I'm working on adding support for the taproot annex to Libre Relay:
>
>
> https://github.com/petertodd/bitcoin/commit/04c8e449a34e74e048bf5751d13592a22763ff7e
>
> I'm basing this on Joost Jager's pull-req:
> https://github.com/bitcoin/bitcoin/pull/27926
>
> Specifically, transactions containing taproot annexes will be standard
> if:
>
> 1) All non-empty annexes start with the byte 0x00, to distinguish them
> from consensus-relevant annexes. This ensures that any use of the
> annex will not conflict with future soft-forks that may assign
> meaning to the annex.
>
> 2) All inputs have an annex. This ensures that use of the annex is
> opt-in, preventing transaction pinning attacks in multi-party
> protocols. This requirement may be relaxed in the future, eg to allow
> spends of keyless outputs, and/or if RBF for witness-only
> replacements is implemented.
>
> An example of a transaction meeting these requirements is:
>
>
> 010000000001011a559447098aaa14dec0c62ea55f43f9ce6bda07d1759f11b634334ab9da939b0000000000ffffffff010000000000000000076a05616e6e657802406840b6fa27a00ba001cc92797ce4f3ab7b7a32c21d1fce49e893b42e506bd92e8db187966a84ef799915cf671334cc59779915b192bfb66b2afcf384bb61d0f422500049276d20616e20616e6e6578212041726520796f7520616e20616e6e65783f0000000000
>
> --
> https://petertodd.org 'peter'[:-1]@petertodd.org
>
Peter Todd in reply to Antoine Riard permalink original

On Thu, Mar 20, 2025 at 03:47:16PM -0700, Antoine Riard wrote:

Quoted text (4 lines)
> Hi Peter,
>
> See also that can be relevant for taproot annex support:
> https://github.com/bitcoin/bips/pull/1381

Thanks.

Quoted text (6 lines)
> > 1) All non-empty annexes start with the byte 0x00, to distinguish them
> > from consensus-relevant annexes. This ensures that any use of the
> > annex will not conflict with future soft-forks that may assign
> > meaning to the annex.
>
> So IIUC, it would be 1-byte: 0x00 | <random_data payload>.

Correct.

When annex data finally does get a consensus meaning any encoding scheme starting with a non-zero byte will be compatible. Most likely we'll get some tag-length-value encoding scheme.

Applications already using annexes who want to also take advantage of new consensus features will of course have to upgrade their encoding schemes to match. But I think that's fine.

Quoted text (10 lines)
> > 2) All inputs have an annex. This ensures that use of the annex is
> > opt-in, preventing transaction pinning attacks in multi-party
> > protocols. This requirement may be relaxed in the future, eg to allow
> > spends of keyless outputs, and/or if RBF for witness-only
> > replacements is implemented.
>
> I think it's good to start with all inputs have an annex. It avoids
> the kind of issue, like what if the annex size is inflated to downgrade
> the feerate of the multi-party transaction (e.g to have a coinjoin
> stucking in network mempools).

Glad to hear you agree.

Quoted text (5 lines)
> One thing that might be missed, without having looked to the code, is
> potentially a policy transaction-relay rule to limit the max size of the
> annex, to avoid the same concern than above. There shouldn't be max
> limit for now, as normally the annex is not standard at all as a taproot
> data field.

Libre Relay has no limit on OP_Return output size; I'm not going to artificially limit annex usage either. The requirement to opt-in to annex usage should be sufficient.

There is a possibility of a multi-party, annex-using, protocol where someone does a pinning attack by re-signing their transaction with a bigger annex. But witness-RBF in combination with replace-by-fee-rate will fix this, so I'm not concerned. No such protocols actually exist yet anyway, so we can figure that out later.

Antoine Riard in reply to Peter Todd permalink original

Hi Peter,

Quoted text (3 lines)
> Applications already using annexes who want to also take advantage of
> new consensus features will of course have to upgrade their encoding
> schemes to match. But I think that's fine.

Yes, I agree. I believe there is one more thing to falicitate any future potential encoding scheme transition for application.

I.e you have the 1-byte : 0x00 | <random_payload_data>, and you could have a an application-only versioning of the <random_payload_data> with one more 1-byte, to give the evolvability to application to experiment with multiple parsing format.

So you would have "1-byte" 0x00 | "random_payload_data" where "random_payload_data" is defined as 1-byte: <version_number> | "random_payload_data". That version number shall only have application meaning, no consensus, it's just some kind of clear domain separation. AFAICT, the version number could be always retrofitted for a non-0x00 tag-length-value consensus meaning.

If it can be useful in any way, an old annex branch with a try of TLV: https://github.com/ariard/bitcoin/commit/84a897feb20c7df813e236d6bf98b69e241a4530

IMHO, this was a very positive thing for taproot to have a lot of versioning and upgradeability paths (e.g leaves version, pubkey type, etc).

Quoted text (5 lines)
> There is a possibility of a multi-party, annex-using, protocol where
> someone does a pinning attack by re-signing their transaction with a
> bigger annex. But witness-RBF in combination with replace-by-fee-rate
> will fix this, so I'm not concerned. No such protocols actually exist
> yet anyway, so we can figure that out later.

Correct given it's opt-in and that there will be witness-RBF support.

Note, for witness support, where IIUC you have wtxidB allowed to replace wtxidB if wtxidA's feerate > wtxidB and if annex size is unbounded, I think it works for multi-party protocols.

For witness re-composition problems, see: https://github.com/bitcoin/bitcoin/pull/19645#issuecomment-677955391

Best, Antoine OTS hash: 30c270434ccb4b50a4a65b40bcdc014b8ef863df8e5e425732c1b385e71b680c Le lundi 24 mars 2025 à 22:00:51 UTC, Peter Todd a écrit :

Quoted text (58 lines)
>
> On Thu, Mar 20, 2025 at 03:47:16PM -0700, Antoine Riard wrote:
> > Hi Peter,
> >
> > See also that can be relevant for taproot annex support:
> > https://github.com/bitcoin/bips/pull/1381
>
> Thanks.
>
> > > 1) All non-empty annexes start with the byte 0x00, to distinguish them
> > > from consensus-relevant annexes. This ensures that any use of the
> > > annex will not conflict with future soft-forks that may assign
> > > meaning to the annex.
> >
> > So IIUC, it would be 1-byte: 0x00 | <random_data payload>.
>
> Correct.
>
> When annex data finally does get a consensus meaning any encoding scheme
> starting with a non-zero byte will be compatible. Most likely we'll get
> some tag-length-value encoding scheme.
>
> Applications already using annexes who want to also take advantage of
> new consensus features will of course have to upgrade their encoding
> schemes to match. But I think that's fine.
>
> > > 2) All inputs have an annex. This ensures that use of the annex is
> > > opt-in, preventing transaction pinning attacks in multi-party
> > > protocols. This requirement may be relaxed in the future, eg to allow
> > > spends of keyless outputs, and/or if RBF for witness-only
> > > replacements is implemented.
> >
> > I think it's good to start with all inputs have an annex. It avoids
> > the kind of issue, like what if the annex size is inflated to downgrade
> > the feerate of the multi-party transaction (e.g to have a coinjoin
> > stucking in network mempools).
>
> Glad to hear you agree.
>
> > One thing that might be missed, without having looked to the code, is
> > potentially a policy transaction-relay rule to limit the max size of the
> > annex, to avoid the same concern than above. There shouldn't be max
> > limit for now, as normally the annex is not standard at all as a taproot
> > data field.
>
> Libre Relay has no limit on OP_Return output size; I'm not going to
> artificially limit annex usage either. The requirement to opt-in to
> annex usage should be sufficient.
>
> There is a possibility of a multi-party, annex-using, protocol where
> someone does a pinning attack by re-signing their transaction with a
> bigger annex. But witness-RBF in combination with replace-by-fee-rate
> will fix this, so I'm not concerned. No such protocols actually exist
> yet anyway, so we can figure that out later.
>
> --
> https://petertodd.org 'peter'[:-1]@petertodd.org
>
Russell O'Connor in reply to Peter Todd permalink original

Can you provide more details on how all inputs having an annex prevents transaction pinning attacks in multi-party protocols?

From my naive understanding, in multi-party protocols one party can grief by inflating the weight of their annex and broadcast their heavier / lower-fee rate version of the transaction, and having an annex in all inputs does not help this because one party can still change their own annex, resign, and broadcast their heavier transaction.

However, I'm not up to date on the latest details about full RBF and pinning attacks, so there is a good chance I'm missing something here.

On Wed, Mar 19, 2025 at 9:02 PM Peter Todd <pete@petertodd•org> wrote:

Quoted text (39 lines)
> I'm working on adding support for the taproot annex to Libre Relay:
>
>
> https://github.com/petertodd/bitcoin/commit/04c8e449a34e74e048bf5751d13592a22763ff7e
>
> I'm basing this on Joost Jager's pull-req:
> https://github.com/bitcoin/bitcoin/pull/27926
>
> Specifically, transactions containing taproot annexes will be standard
> if:
>
> 1) All non-empty annexes start with the byte 0x00, to distinguish them
>    from consensus-relevant annexes. This ensures that any use of the
>    annex will not conflict with future soft-forks that may assign
>    meaning to the annex.
>
> 2) All inputs have an annex. This ensures that use of the annex is
>    opt-in, preventing transaction pinning attacks in multi-party
>    protocols. This requirement may be relaxed in the future, eg to allow
>    spends of keyless outputs, and/or if RBF for witness-only
>    replacements is implemented.
>
> An example of a transaction meeting these requirements is:
>
>
> 010000000001011a559447098aaa14dec0c62ea55f43f9ce6bda07d1759f11b634334ab9da939b0000000000ffffffff010000000000000000076a05616e6e657802406840b6fa27a00ba001cc92797ce4f3ab7b7a32c21d1fce49e893b42e506bd92e8db187966a84ef799915cf671334cc59779915b192bfb66b2afcf384bb61d0f422500049276d20616e20616e6e6578212041726520796f7520616e20616e6e65783f0000000000
>
> --
> https://petertodd.org 'peter'[:-1]@petertodd.org
>
> --
> You received this message because you are subscribed to the Google Groups
> "Bitcoin Development Mailing List" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to bitcoindev+unsubscribe@googlegroups•com.
> To view this discussion visit
> https://groups.google.com/d/msgid/bitcoindev/Z9tg-NbTNnYciSOh%40petertodd.org
> .
>
Russell O'Connor in reply to Russell O'Connor permalink original

Ah nevermind, I get it now.

The contrapositive of this proposed standardness rule is that if one annex is empty, then all annexes must be empty. Therefore if on participants signs an empty annex, then standardness would imply that all the annexes must be empty.

On Mon, Apr 28, 2025 at 12:13 PM Russell O'Connor <roconnor@blockstream•com> wrote:

Quoted text (54 lines)
> Can you provide more details on how all inputs having an annex prevents
> transaction pinning attacks in multi-party protocols?
>
> From my naive understanding, in multi-party protocols one party can grief
> by inflating the weight of their annex and broadcast their heavier /
> lower-fee rate version of the transaction, and having an annex in all
> inputs does not help this because one party can still change their own
> annex, resign, and broadcast their heavier transaction.
>
> However, I'm not up to date on the latest details about full RBF and
> pinning attacks, so there is a good chance I'm missing something here.
>
> On Wed, Mar 19, 2025 at 9:02 PM Peter Todd <pete@petertodd•org> wrote:
>
>> I'm working on adding support for the taproot annex to Libre Relay:
>>
>>
>> https://github.com/petertodd/bitcoin/commit/04c8e449a34e74e048bf5751d13592a22763ff7e
>>
>> I'm basing this on Joost Jager's pull-req:
>> https://github.com/bitcoin/bitcoin/pull/27926
>>
>> Specifically, transactions containing taproot annexes will be standard
>> if:
>>
>> 1) All non-empty annexes start with the byte 0x00, to distinguish them
>>    from consensus-relevant annexes. This ensures that any use of the
>>    annex will not conflict with future soft-forks that may assign
>>    meaning to the annex.
>>
>> 2) All inputs have an annex. This ensures that use of the annex is
>>    opt-in, preventing transaction pinning attacks in multi-party
>>    protocols. This requirement may be relaxed in the future, eg to allow
>>    spends of keyless outputs, and/or if RBF for witness-only
>>    replacements is implemented.
>>
>> An example of a transaction meeting these requirements is:
>>
>>
>> 010000000001011a559447098aaa14dec0c62ea55f43f9ce6bda07d1759f11b634334ab9da939b0000000000ffffffff010000000000000000076a05616e6e657802406840b6fa27a00ba001cc92797ce4f3ab7b7a32c21d1fce49e893b42e506bd92e8db187966a84ef799915cf671334cc59779915b192bfb66b2afcf384bb61d0f422500049276d20616e20616e6e6578212041726520796f7520616e20616e6e65783f0000000000
>>
>> --
>> https://petertodd.org 'peter'[:-1]@petertodd.org
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "Bitcoin Development Mailing List" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to bitcoindev+unsubscribe@googlegroups•com.
>> To view this discussion visit
>> https://groups.google.com/d/msgid/bitcoindev/Z9tg-NbTNnYciSOh%40petertodd.org
>> .
>>
>
Peter Todd in reply to Russell O'Connor permalink original

On Mon, Apr 28, 2025 at 12:25:08PM -0400, Russell O'Connor wrote:

Quoted text (6 lines)
> Ah nevermind, I get it now.
>
> The contrapositive of this proposed standardness rule is that if one annex
> is empty, then all annexes must be empty.  Therefore if on participants
> signs an empty annex, then standardness would imply that all the annexes
> must be empty.

You're almost correct.

There is a consensus distinction between having an annex, and not having an annex at all. That means a zero-byte annex is different from not having an annex at all.

So with my proposed rule, inputs can either have no annex at all (the standard status quo), or an annex of zero or more bytes.

If any input has an annex, *all* inputs must have an annex. However, for efficiency, they're allowed to have a completely empty, zero-byte, annex. So basically an empty annex is just the defined way for an input to sign their approval of the use of annexes in that transaction (and subsequent tx pinning risk).