Relax standardness rules regarding CHECKMULTISIG #33755

pull roconnor-blockstream wants to merge 1 commits into bitcoin:master from roconnor-blockstream:multisig-standardness-2025-10 changing 1 files +5 −1
  1. roconnor-blockstream commented at 2:02 pm on October 31, 2025: contributor

    In PR #5247, the STRICTENC standardness rules were tightened with regards to CHECKMULTISIG so that unparsable public keys fail the script when they are encountered. The overall purpose here was to disallow the use of confusing hybrid public keys by policy while keeping policy compatible (i.e., strictly stronger) with consensus rules.

    Comments in PR #5247 note that “I don’t believe it should affect any system in production”; however, this belief is/was false. Counterparty was stuffing data blobs into multisig pubkey lists, but these UTXOs were meant to be spendable because, although some pubkeys were unparsable, other keys were parsable, and the UTXOs were meant to be spent by those valid keys.

    But in tackling the hybrid key issue, PR #5247 disallowed any unparsable keys in multisigs, whether or not they were hybrid, and whether or not the signature was meant to satisfy a hybrid key.

    In production, Counterparty UTXOs were inadvertently caught up in this standardness rule change and became “soft confiscated.” That is, they were no longer spendable by policy but still recoverable if users are able to somehow bypass standardness by mining their transactions themselves, or getting out-of-band assistance from some other miner.

    I understand that Bitcoin Core never intended to “soft confiscate” any UTXOs by policy changes. This change addresses the problem.

    With this change, standardness rules intended for hybrid keys are only checked after passing a signature check in CHECKMULTISIG operations. Failing signature checks revert to their consensus behaviour of testing subsequent public keys.

    Counterparty UTXOs were never intended to make use of hybrid keys and thus shouldn’t have any passing signatures using hybrid keys.

  2. DrahtBot commented at 2:02 pm on October 31, 2025: contributor

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/33755.

    Reviews

    See the guideline for information on the review process. A summary of reviews will appear here.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #33759 (Fix BIP143 standardness rules for CHECKMULTISIG by roconnor-blockstream)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  3. glozow added the label TX fees and policy on Oct 31, 2025
  4. instagibbs commented at 3:35 pm on October 31, 2025: member
    If anyone has documentation showing the format (pre-OP_RETURN) this would be useful.
  5. TheCharlatan commented at 3:58 pm on October 31, 2025: contributor

    If anyone has documentation showing the format (pre-OP_RETURN) this would be useful.

    https://docs.counterparty.io/docs/advanced/protocol/#transactions and https://github.com/CounterpartyXCP/counterparty-core/blob/master/counterparty-core/counterpartycore/lib/api/composer.py#L304 should give an idea. AFAICT the real pubkey goes last.

  6. Relax standardness rules regarding CHECKMULTISIG
    In PR #5247, the STRICTENC standardness rules were tightened with regards to
    CHECKMULTISIG so that unparsable public keys fail the script when they are
    encountered. The overall purpose here was to disallow the use of confusing
    hybrid public keys by policy while keeping policy compatible (i.e., strictly
    stronger) with consensus rules.
    
    Comments in PR #5247 note that "I don't believe it should affect any system in
    production"; however, this belief is/was false. Counterparty was stuffing data
    blobs into multisig pubkey lists, but these UTXOs were meant to be spendable
    because, although some pubkeys were unparsable, other keys were parsable, and
    the UTXOs were meant to be spent by those valid keys.
    
    But in tackling the hybrid key issue, PR #5247 disallowed any unparsable keys in
    multisigs, whether or not they were hybrid, and whether or not the signature was
    meant to satisfy a hybrid key.
    
    In production, Counterparty UTXOs were inadvertently caught up in this
    standardness rule change and became "soft confiscated." That is, they were no
    longer spendable by policy but still recoverable if users are able to somehow
    bypass standardness by mining their transactions themselves, or getting
    out-of-band assistance from some other miner.
    
    I understand that Bitcoin Core never intended to "soft confiscate" any UTXOs by
    policy changes. This change addresses the problem.
    
    With this change, standardness rules intended for hybrid keys are only checked
    after passing a signature check in CHECKMULTISIG operations. Failing signature
    checks revert to their consensus behaviour of testing subsequent public keys.
    
    Counterparty UTXOs were never intended to make use of hybrid keys and thus
    shouldn't have any passing signatures using hybrid keys.
    bbfaed4983
  7. roconnor-blockstream force-pushed on Oct 31, 2025
  8. ajtowns commented at 5:05 pm on October 31, 2025: contributor
    This change affects enforcement of SCRIPT_VERIFY_WITNESS_PUBKEYTYPE which afaics should not be weakened bip143?
  9. roconnor-blockstream commented at 5:33 pm on October 31, 2025: contributor

    @ajtowns I did consider that.

    Firstly we should note that SCRIPT_VERIFY_WITNESS_PUBKEYTYPE and BIP-143 rules regarding compressed public keys are not consensus rules, but policy only. So at least it can be weakened.

    Regarding as to whether it should be weakened: Currently Bitcoin Core’s implementation choice for CHECKMULTISIG is such that once enough signatures match the pubkeys, no further pubkeys in the CHECKMULTISIG stack are inspected for well-formedness policy constraints. That is to say, current policy lets you have uncompressed pubkeys (or at least data that looks like uncompressed pubkeys) on one side of the stack of pubkeys but not the other. This change in policy makes it (more) symmetric so that you can have uncompressed pubkeys (or data that looks like uncompressed pubkeys) on either end of the stack of pubkeys, but those uncompressed pubkeys cannot be used in passing signature checks.

    Now the Counterparty UTXO predates Segwit V0, so we could refactor the code to keep the current asymmetric policy rules regarding Segwit V0 script, and I would be fine with that. However, my current judgement is that, since data-that-looks-like-uncompressed-pubkeys is already allowed on one side of the pubkey stack in Segwit V0 script, it isn’t worth the code complexity to maintain this policy for the sake of Segwit V0 script. There is no real advantage in doing that extra work. If other folks do think it is worthwhile for reasons I cannot imagine, I’m fine with that too.

  10. ajtowns commented at 7:21 pm on October 31, 2025: contributor

    If you’re deliberately changing the standardness rules specified in BIP143, that should be in the PR description, and possibly proposed as an update to the BIP. If you’re not deliberately changing them, they shouldn’t be changed by accident. Personally, I don’t see the justification for changing them here, though I don’t really understand why it was specced as a policy rule rather than a consensus one at the time, either.

    Personally, I don’t really understand the motivation for reconsidering a policy rule that’s been in place for 11 years, either, and for which new adoption would only be less fee efficient than what’s already allowed. If there were real coins locked due to this policy, it seems like they should have been already recovered via getting a non-standard spend mined directly.

  11. roconnor-blockstream commented at 7:36 pm on October 31, 2025: contributor

    I guess we could change BIP143. Currently the text reads:

    Each public key passed to a sigop inside version 0 witness program must be a compressed key: the first byte MUST be either 0x02 or 0x03, and the size MUST be 33 bytes. Transactions that break this rule will not be relayed or mined by default.

    Note that is not how Bitcoin Core implements SCRIPT_VERIFY_WITNESS_PUBKEYTYPE currently as you can pass pubkeys to CHECKMULTISIG that violate this policy when the signature stack is used up before reaching the end of the pubkey stack.

    So the current status is that the SCRIPT_VERIFY_WITNESS_PUBKEYTYPE policy implementation does not match the text of BIP143. So to that extent this PR doesn’t really break anything that isn’t already broken.

    Edit: Or we could change how SCRIPT_VERIFY_WITNESS_PUBKEYTYPE is implement to correctly follow BIP143. I’m fine with that too. Just let me know.

  12. roconnor-blockstream commented at 8:04 pm on October 31, 2025: contributor

    If there were real coins locked due to this policy, it seems like they should have been already recovered via getting a non-standard spend mined directly.

    I don’t know why you would think that they should have already been recovered. You think anyone can just call up a mining pool and get their non-standard transactions mined? How much money needs to be at stake before you can even get a pool’s attention? Or how small in value do UTXOs have to be so that it is okay to soft-confiscate it since it isn’t worth fixing for such a little amount?

    Anyhow, AFAIU Counterparty was using bare multisigs, so in theory we don’t have to speculate and we can just look for such UTXOs that are waiting to be freed. Someone please correct me if I’m wrong and Counterparty was using p2sh multisigs.

    I haven’t checked my IRC logs, but my recollection is the person I was chatting with who had their UTXO’s soft-confiscated by Bitcoin Core’s policy change decided the amount of funds were small and they were not going to pursue it. However what was a small amount of Bitcoin 11 years ago may not be a small amount today.

    Again, this soft-confiscation was inadvertent. PR #5247 was trying to address hybrid keys, not Counterparty UTXOs. An error was made and the result was arguably unjust towards those folks holding those UTXOs.

    Recent posts on the mailing list made me aware that people incorrectly believe that Bitcoin Core has never soft-confiscated folk’s UTXOs before, but I know that isn’t true. I’m not sure what my thinking was at the time, but had I thought there it was a deliberate policy decision against Counterparty transactions. However, upon rereviewing PR #5247 last night I came to understand the policy was never intended to soft-confiscate Counterparty UTXOs. And this morning I realized we can fix this injustice. Better late than never.

    Soft-confiscating these transactions was wrong, and we should fix mistakes if we can when we realize we have made one, even if the mistake was made 11 years ago. This code is the way PR #5247 ought to have been written in the first place.

  13. ajtowns commented at 0:24 am on November 1, 2025: contributor

    If there were real coins locked due to this policy, it seems like they should have been already recovered via getting a non-standard spend mined directly.

    I don’t know why you would think that they should have already been recovered. You think anyone can just call up a mining pool and get their non-standard transactions mined?

    That’s what things like slipstream allow today, so, yes? Template building by hashers also make that more accessible today than previously. In any event, if it’s not worth calling up a single miner and getting it mined, it also doesn’t seem worth changing the default policy for every miner that follows our defaults.

    How much money needs to be at stake before you can even get a pool’s attention? Or how small in value do UTXOs have to be so that it is okay to soft-confiscate it since it isn’t worth fixing for such a little amount?

    I don’t think chastising the reader about confiscating coins is constructive. If you want to make those coins easily accessible now, that’s a fine thing to argue for, but it should be done on its merits, not by attempting to guilt trip people. This PR isn’t passing CI, for instance.

    Anyhow, AFAIU Counterparty was using bare multisigs, so in theory we don’t have to speculate and we can just look for such UTXOs that are waiting to be freed.

    There seem to be six utxos from prior to block 400,000 that currently have a value of more than $100 USD that fit the description here:

    The 3.8M sat output was worth about $11 at the time, so I could quite easily see it having been written off as a loss and access to the corresponding private keys not having been maintained in the meantime.

    There are an additional 15,133 outputs from prior to block 400k that look like they might fit this case, all with between 780 and 30,919 sats, totalling 1.0148,8939 BTC, which had a total value of about $472 if I pick the highest BTC price in the above timeframe. (Or at least there were as at block 897666 which is the utxo data I have handy for analysing. This likely includes some false positives as well, though I think I eliminated most things)

    For comparison, it looks to me like there was 0.9068,0410 BTC (so $422 at the time by the same logic) across perhaps 11k bare multisig addresses that can only be spent via uncompressed pubkeys (eg this looks like ~10M sats worth ~$10k USD today, sent to a 2/3 uncompressed bare multisig, from the same multisig, so at one point certainly spendable).

    Soft-confiscating these transactions was wrong, and we should fix mistakes if we can when we realize we have made one, […]

    Soft-confiscating is always a risk with policy restrictions, but there is also already a straight-forward solution to all problems in that class: talk to a miner directly.

  14. roconnor-blockstream commented at 2:20 am on November 1, 2025: contributor

    Those outputs look like multisigs that are composed out of valid compressed or uncompressed pubkeys, and I believe spending them would pass standardness rules (except for 3482ea1d219120b13f3be49f63fd7079136785dff2bf7487726b640da5876e33:0, which appears to simply be a broken script).

    The UTXO’s I’m looking for would have pubkeys with an invalid prefix, or an invalid length for their prefix.

    Based on the code prior to https://github.com/CounterpartyXCP/counterparty-core/pull/443/commits/f1a8c82914b2f913560496e3d1becc1b63f88118 I would specifically expect a 1-of-3 multisig where at least 1 of the keys is 33 bytes but does not begin with 0x02 or 0x03.

  15. roconnor-blockstream commented at 12:23 pm on November 1, 2025: contributor

    Bitcoin Core relay policy is largely motivated by not relaying third party malleable transactions. There is no reason to relay transactions if they are just going to be modified before they get mined.

    Given the, unfortunately extensive, amount of malleability generally afford by Bitcoin Script’s design, sometimes policy just limits third party malleable transactions to some canonical form, one that minimizes transaction size so that miners are not incentivized to reduce the size further. Hence the policy around canonical pushes and IF arguments, cleanstack, etc.

    Closely related is policy around fee bumping, where policy is addressing abuse from first party malleable transactions to prevent excessively relaying transactions that aren’t going to be mined due to replacement.

    There are a couple of relay policies around soft-fork points. The use of NOPn transactions are banned by policy. Again these forms of script are unused by folks, who have a perfectly good normal NOP operation that they could have used instead. Using OP_NOP7 is either carelessness or maliciousness.

    There is some other policy around OP_RETURN which is about limiting the damage of externalities caused by users who are motivated to store data on the blockchain. This policy was recently improved, so that’s good.

    Then we get to hybrid keys policy…

    Arguably hybrid keys don’t even deserve to be banned by policy to begin with. They are do not cause malleability issues in most practical cases. In particular, their malleability problems are no worse than malleability problems induced by uncompressed pubkeys, which are not banned.

    The main problem with hybrid keys is that they are weird, and that implementers of the Bitcoin protocol are likely to mess it up. Hybrid key policy is there just in case maybe we want to soft-fork them out one day. In my opinion the Bitcoin protocol already has a lot of weirdness in it and is hard to reimplement correctly anyways. Hybrid keys are no more abusive than uncompressed pubkeys and for that reason we are probably never going to soft-fork them out. Folks already are motivated to avoid them for the same reason they avoid uncompressed pubkeys. Similar to using NOP7, users of hybrid keys would just be doing so to be malicious. But unlike NOP7 hybrid keys don’t exist to soft-fork in new behaviour.

    But fine, this PR isn’t proposing the removal of hybrid key policy. Transactions using hybrid keys remain disallowed in this PR.

    The problem is that PR #5247 doesn’t just ban the use of hybrid keys. The implementation goes way overboard and disallows all sorts of data passed to CHECKMULTISIG that isn’t even hybrid keys.

    Okay, but maybe the policy implemented #5247 just happens to be good for other reasons beyond its primary purpose? Isn’t banning arbitrary data in CHECKMULTISIG good? I don’t know if it is good or not, but #5247 doesn’t ban arbitrary data in CHECKMULTISIG. #5247 still allows arbitrary data pushes in CHECKMULTISIG so long as they occur after all the signatures are consumed. So this policy implementation isn’t providing any additional benefits.

    Okay, but at least the policy implemented #5247 isn’t harming anyone right? This is the crux of the problem with #5247: it has harmed Bitcoin users. I cannot think of any other relay policy implemented in Bitcoin Core that has ever disallowed actively used non-malicious transactions before.

    Are the Counterparty transactions that were banned #5247 malicious? Maybe, but I don’t think so. The blockspace used by them are identical to a normal 1-of-3 multisig transaction. In fact, in response to #5247 Counterparty simply reversed the order of their “pubkey” data in their protocol in order to satisfy the restrictions imposed by #5247. (They also did a better job hiding their data pushes look more like pubkeys to prevent further policy interference). So however malicious their transactions are, their replacement is equally malicious and it isn’t banned. Because disallowing “bad data” was never the purpose of #5247, it isn’t surprising that the policy doesn’t stop it.

    But Counterparty adjusting their protocol to comply with #5247 does nothing to help the folks that were already using their older protocol, and is the big problem, and why I think this is, in fact, a big deal. Again, I cannot think of any other relay policy implemented in Bitcoin Core that has ever banned actively used non-malicious, non-malleable transactions before or since.

    It undermines Bitcoin’s premise as permissionless money if every time a user comes up with an novel, safe, secure, non-malicious use of Bitcoin as it is today, they run the risk of their UTXOs being thoughtlessly banned without consideration of their use case.

    And yes #5247 did ban these Counterparty UTXOs without consideration. When petertodd correctly noted “Equally this change may render some users’ funds unspendable, potentially even funds locked in P2SH outputs.” sipa replied “I don’t believe it should affect any system in production, as hybrid pubkeys have been non-standard since v0.8.” No one at the time seemed to be aware that #5247 was affecting in use Counterparty transactions! The PR didn’t just maybe render some users’s funds unspendable, it actually did! sipa also said “AFAIK does not change anything for tx acceptance except in weird checksig+not cases”, but this isn’t a checksig+not case.

    I’m am quite certain that #5247 would have never been accepted in its form had the authors been aware that they were banning actively used non-malicious transaction protocols.

    As far as guilt tripping goes, I personally feel bad that long ago when someone came to me asking for my help in spending their transaction, I had to tell them something like “SFYL, redeeming your UTXO is now banned from the Bitcoin network. You will require miner assistance”. And today I feel much worse now that I understand that the banning of their UTXO was actually unintentional. Had I just dug into the issue a little bit more and seen the orginal purpose of the code, we could have perhaps fixed this policy implementation a long time ago.

    So in summary:

    1. We probably shouldn’t even bother banning hybrid keys by policy, but even this PR still keeps the use of hybrid keys disallowed.
    2. The policy rules implemented in #5247 go well beyond what is necessary to ban hybrid keys, banning other sorts of pubkey arguments within CHECKMULTISIG.
    3. The policy rules implemented in #5247 do not comprehensively protect against all non-pubkey arguments within CHECKMULTISIG and thus are not providing other sorts of relay protection.
    4. Yes we should feel bad when we impose policy restrictions on users that interrupt existing, non-malicious, UTXOs / uses of Bitcoin.
    5. We wouldn’t disallow uncompressed pubkey by policy, and we shouldn’t have disallowed old-style Counterparty transaction. Just because old-style Counterparty transactions are fewer in value and lower in number doesn’t make them unworthy of our consideration.
    6. And we should feel doubly bad when we impose such policy restrictions unintentionally and without consideration for their existing usage.
    7. Folks are trusting Bitcoin with their money and thoughtlessly changing policy out from under them undermines the premise of Bitcoin as a safe, permissionless system for anyone to use.
    8. And we should feel quadruply bad when we do have an opportunity to make the situation right again, no matter how late, and decide not to take it because, well it was just all so long ago.
  16. roconnor-blockstream commented at 12:27 pm on November 1, 2025: contributor
    @TheCharlatan I touch on this in the above, but I do want to explicitly note that the order of public keys that Counterparty uses changed in response to #5247 and the the keys used to be in the other order.

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2025-11-02 18:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me