Fix OP_CHECKSIG bug with OP_PUSHDATA #349

pull vegard wants to merge 1 commits into bitcoin:master from vegard:checksig-fix changing 2 files +18 −2
  1. vegard commented at 2:26 PM on June 26, 2011: contributor

    To delete the signature from scriptSig, OP_CHECKSIG constructs a new CScript object from the signature found on the stack and then looks for an exact copy of this object in scriptSig.

    However, if the original signature was pushed using OP_PUSHDATA and the signature is short enough to be pushed using one of the 1-75 opcodes, the two objects will not match and the signature verification will fail even though the values are the same.

    This patch fixes this by comparing the data-pushing opcode's payload only (excluding the opcode itself).

    I've tested this with valid testnet transactions, which are verified correctly.

    As this is my first bitcoin patch and it touches a rather sensitive part of the code, please review/test it for yourselves as well!

  2. Fix OP_CHECKSIG bug with OP_PUSHDATA
    To delete the signature from scriptSig, OP_CHECKSIG constructs a new
    CScript object from the signature found on the stack and then looks for
    an exact copy of this object in scriptSig.
    
    However, if the original signature was pushed using OP_PUSHDATA and the
    signature is short enough to be pushed using one of the 1-75 opcodes,
    the two objects will not match and the signature verification will fail
    even though the values are the same.
    
    This patch fixes this by comparing the data-pushing opcode's payload
    only (excluding the opcode itself).
    
    I've tested this with valid testnet transactions, which are verified
    correctly.
    1e668a631d
  3. gavinandresen commented at 12:34 AM on June 27, 2011: contributor

    This makes me very, very nervous. I want OP_CHECKSIG unit tests before touching this.

  4. gmaxwell commented at 8:46 AM on July 18, 2011: contributor

    Yea, so — since Luke-jr's pool accepts non-standard transactions I thought I'd suggest that he block these transactions until its fixed. Because if one is done under the old style, and then is spent and the spend validates (but won't validate under the fix) the behavior will become unfixable. Or unfixable without hacks.

    Luke asserted that it's already unfixable: If it's fixed, then at any time someone can produce either the old or the new style and the chain will irreparably split for old and new clients. Even if the new one becomes longer, the split will remain because the two interpretations of the signature are mutually exclusive.

    I didn't have a really good answer to this— it sounds right to me. Is there any way to fix this that doesn't create a split hazard? ... other than perhaps a hack that specifies the old behavior until some sufficiently far future block number, and the new behavior after it, so that enough clients can be updated before the flag day that an intentionally triggered split isn't an issue. (and, hopefully none of the old style make it into the chain before the flag day, so that the legacy code can simply be dropped once the flag day is sufficiently buried)

  5. gavinandresen commented at 8:56 AM on July 18, 2011: contributor

    Do we need to fix this? If you want to generate valid OP_CHECKSIG transactions, why can't you just use one of the 1-75 opcodes instead of OP_PUSHDATA1/2/4?

    And aren't ECDSA signatures always a fixed length (or is there more funky DER encoding going on...)?

  6. vegard commented at 9:07 AM on July 18, 2011: contributor

    On 18 July 2011 10:46, gmaxwell reply@reply.github.com wrote:

    Yea, so —  since Luke-jr's pool accepts non-standard transactions I thought I'd suggest that he block these transactions until its fixed.  Because if one is done under the old style, and then is spent and the spend validates (but won't validate under the fix) the behavior will become unfixable. Or unfixable without hacks.

    My patch doesn't make any currently valid transactions invalid. But it does make some invalid transactions valid.

    This is just a compatibility issue with other clients/implementations of the scripting engine that arises from an ambiguity in the protocol.

    Another way to solve this is to standardise that OP_PUSHDATA1 must never push less than 76 bytes, OP_PUSHDATA2 must never push less than 256 bytes, etc.

  7. gmaxwell commented at 11:14 PM on July 23, 2011: contributor

    This could also be addresses by making sure the new cscript object is constructed the same was as the prior one.

    This would require more code, but I think it would be more robust against implementation differences.

  8. groffer commented at 6:53 AM on August 3, 2011: none

    Wouldn't it be better to just add documentation to the effect that scripts should always use the shortest sequence for pushing data? Isn't that easier/safer than trying to change the validation rules?

  9. gavinandresen commented at 3:37 PM on August 9, 2011: contributor

    Consensus seems to be that standardizing OP_PUSHDATA1 mush never push less than 76 bytes / etc is the right way to go. I'm going to close this.

  10. gavinandresen closed this on Aug 9, 2011

  11. dexX7 referenced this in commit 21aa7cda5c on Apr 24, 2016
  12. ptschip referenced this in commit 31c95a4a7a on Mar 8, 2017
  13. hanchon referenced this in commit b2f5fdd31e on Aug 17, 2017
  14. lateminer referenced this in commit 7ee0c3f03a on Oct 16, 2019
  15. rajarshimaitra referenced this in commit 1e35cacba5 on Aug 5, 2021
  16. DrahtBot locked this on Sep 8, 2021

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: 2026-04-21 21:16 UTC

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