Fix overly eager BIP30 bypass #12204

pull morcos wants to merge 1 commits into bitcoin:master from morcos:bip30bypassfix changing 1 files +54 −1
  1. morcos commented at 6:57 PM on January 16, 2018: member

    In #6931 we introduced a possible consensus breaking change by misunderstanding how completely BIP 34 obviated the need for BIP 30. Unfixed, this could break consensus after block height about 1.9M. Explained in code comment.

    h/t @sdaftuar

  2. in src/validation.cpp:1886 in 9ab7fe0b3f outdated
    1881 | +    // The second case is block 176,684 which has an indicated block height of
    1882 | +    // 490,897. Unfortunately this issue was not discovered until about 2 weeks
    1883 | +    // before block 490,897 so there was not much opportunity to address this
    1884 | +    // case other than to carefully analyze it and determine it would not be a
    1885 | +    // problem. Block 490,897 was, in fact, mined with a different coinbase
    1886 | +    // than 176,684, but it is important to note that even if it hadn't
    


    instagibbs commented at 7:37 PM on January 16, 2018:

    Maybe put "block" in front of blocks being named by number. (and everywhere else)

    I was reading it as the the height in coinbase aka the number 176,684 in the block's coinbase at height 490,897.

  3. in src/validation.cpp:1868 in 9ab7fe0b3f outdated
    1863 | +    // the BIP34 height of 227,931 which have a scriptSig with a valid-looking
    1864 | +    // BIP34 height for a later block height. These coinbases run the risk of
    1865 | +    // being duplicated when we reach that later block height. An exhaustive
    1866 | +    // search of all mainnet coinbases before the BIP34 height which have a
    1867 | +    // scriptSig indicating a later block height reveals 2 cases where the later
    1868 | +    // block height is before 1,983,702.
    


    ryanofsky commented at 8:20 PM on January 16, 2018:

    Is the significance of 1,938,702 just that it is the third lowest height found encoded in the old coinbases? The sentence doesn't say where 1,938,702 comes from, and this is written like it should be obvious what the number means.

    If it is just the third lowest height found in the search, I think it would be clearer to say something like "An exhaustive search of all blocks before the BIP34 height found that the lowest height values indicated in coinbase scriptSigs were: 209,921, 490,897, and 1,983,702."

  4. in src/validation.cpp:1862 in 9ab7fe0b3f outdated
    1857 | @@ -1858,12 +1858,58 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
    1858 |      // before the first had been spent.  Since those coinbases are sufficiently buried its no longer possible to create further
    1859 |      // duplicate transactions descending from the known pairs either.
    1860 |      // If we're on the known chain at height greater than where BIP34 activated, we can save the db accesses needed for the BIP30 check.
    1861 | +
    1862 | +    // The exception to this logic is if there are coinbases from blocks before
    


    jnewbery commented at 9:07 PM on January 16, 2018:

    Rather than start your new comment explaining where the previous comment is incorrect, I think it makes sense to remove/reword the paragraph above.

    I also think it would make the whole comment clearer if you explicitly introduced terminology at the top of the comment. Something like:

    - block height: the height of the block in the blockchain
    - coinbase height: the height indicated in the coinbase transaction's scriptSig under BIP34 rules.
    
    All blocks with block height >= 227,931 must have coinbase height equal to block height. This is a consensus rule.
    

    rather than sprinkling the rest of the comment with multiple terms for the same concept: a scriptSig with a valid-looking BIP34 height..., scriptSig indicating..., indicated block height, coinbase with indicated height.


    morcos commented at 4:30 PM on January 25, 2018:

    I think it is useful to understand the basic logic that BIP 34 implies BIP 30 is met and doesn't need to be checked. But then understand why it's not quite that simple. It also matches the historical evolution of the code. So I left this comment as correction to the previous one.

  5. jnewbery commented at 9:15 PM on January 16, 2018: member

    concept ACK 9ab7fe0b3f50b2cc3514975b26eb7c63134bdd40.

    I'm currently running my own analysis of pre-BIP34 blocks to make sure that it agrees with what you found. It would be good to have a gist showing those results with code so other people can easily validate for themselves.

    In general, I'm not sure whether code comments are appropriate for such a long and nuanced description. It certainly breaks up the flow of the ConnectBlock(). However, more verbose is generally better than less, and I don't have a better suggestion of where to put this level of comment that would stay maintained with the code.

  6. in src/validation.cpp:1871 in 9ab7fe0b3f outdated
    1866 | +    // search of all mainnet coinbases before the BIP34 height which have a
    1867 | +    // scriptSig indicating a later block height reveals 2 cases where the later
    1868 | +    // block height is before 1,983,702.
    1869 | +
    1870 | +    // There are many cases which indicate block height 1,983,702 or later, so
    1871 | +    // we simply remove the optimiztion to skip BIP30 checking for blocks at
    


    jimpo commented at 1:26 AM on January 17, 2018:

    typo: optimization

  7. gmaxwell commented at 11:32 AM on January 17, 2018: contributor

    Concept ACK.

  8. TheBlueMatt commented at 8:59 PM on January 17, 2018: member

    code-level utACK, modulo comment comments.

  9. MarcoFalke commented at 11:49 PM on January 18, 2018: member

    Concept ACK. Though, I have never checked if any of the heights or hashes make sense. Wouldn't it help review if #6931 or this pull actually included the code that was used to determine those magic numbers?

  10. jnewbery commented at 10:25 PM on January 19, 2018: member

    My analysis matches yours exactly. The pre-BIP34 blocks with coinbase height > block height are (in ascending order):

    block_height | coinbase_height 209920 | 209921 176684 | 490897 164384 | 1983702 169895 | 3708179 <---- I expect to be dead before this height ....

    so you're right that the only heights that we should care about are 209921, 490897 and 1983702.

  11. jnewbery commented at 10:44 PM on January 19, 2018: member

    If anyone wants to re-run the analysis, the gist with my code is here: https://gist.github.com/jnewbery/df0a98f3d2fea52e487001bf2b9ef1fd

    (this is quite slow since it's hitting the RPC interface 3 times for each block. It'd be faster to deserialize block files directly, patch bitcoind to print this data itself, or use BlockSci or a similar block analysis tool)

  12. achow101 commented at 6:06 AM on January 20, 2018: member

    code utACK, haven't actually read through the whole comment.

    I agree with the above analysis that block 1983702 is the lowest block height that we need to worry about. We could soft fork in something prior to that block to guarantee that the txids will be different, e.g. block height in the nLockTime field.

  13. fanquake added the label Consensus on Jan 22, 2018
  14. morcos force-pushed on Jan 25, 2018
  15. morcos commented at 4:28 PM on January 25, 2018: member

    Comment updated to hopefully be clearer. Code unchanged.

    For reference here is how I double checked the possible violations. I patched bitcoind with this snippet and then ran with -reindex-chainstate.

    @@ -1724,6 +1724,16 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd
                     }
                 }
             }
    +        if (block.vtx[0]->vin[0].scriptSig.size() >= 4 && block.vtx[0]->vin[0].scriptSig[0] == 3) {
    +            std::vector<unsigned char> vch;
    +            for (int i=1;i<4;i++)
    +                vch.push_back( block.vtx[0]->vin[0].scriptSig[i]);
    +            CScriptNum height(vch,false);
    +            int height_indicated = height.getint();
    +            if (height_indicated > pindex->nHeight) {
    +                fprintf(stdout,"Potential future duplicate: block %d has indicated height %d\n",pindex->nHeight,height_indicated);
    +            }
    +        }
         }
     
         // Start enforcing BIP68 (sequence locks) and BIP112 (CHECKSEQUENCEVERIFY) using versionbits logic.
    
  16. jnewbery commented at 7:16 PM on January 26, 2018: member

    Tested ACK 3f3b991

  17. laanwj commented at 3:48 PM on February 8, 2018: member

    Looks sensible to me. Although I think we should definitely make this a chain parameter, or at least define a constant, instead of hardcoding this magic number:

    Optional TODO: Have BIP30 checking activate at a per chain block height.
    

    I don't think we're in enough of a hurry here to skip that.

  18. morcos commented at 3:04 PM on February 15, 2018: member

    @laanwj I'm happy to define it as a constant locally, but it seems like adding it as a chain parameter just adds unnecessary cruft to the code. This is such an obscure (and irrelevant for decades) element of the consensus that it seems better to keep it entirely contained to one spot in the code base, so it doesn't occupy mental energy in other places. That said, will defer to your judgement...

    EDIT: Or if we think testnet3 will get longer than 1.9 million blocks, then I suppose that's an argument for per chain so we don't do unnecessary calculations on testnet3.

  19. laanwj commented at 6:01 PM on February 15, 2018: member

    Nono I'm OK with that, but if we actively argue against making it a chain parameter we should remove the TODO as well, otherwise it's inviting someone else to make that change. My only point is that there is no hurry to merge this, so no reason to leave unfinished TODOs in the code.

  20. Fix overly eager BIP30 bypass 5b8b387752
  21. morcos force-pushed on Feb 15, 2018
  22. morcos commented at 6:35 PM on February 15, 2018: member

    updated to a constant and removed optional TODO, I believe its better to keep this mess contained to one section of the code

  23. jnewbery commented at 2:49 PM on February 16, 2018: member

    utACK 5b8b387752e8c493a8e87795ae6ddb78b45b1a5d

    Difference is that there is now a constexpr int BIP34_IMPLIES_BIP30_LIMIT and the comment has been updated.

    Travis failed because of a timeout. I'll kick it.

  24. sdaftuar commented at 2:11 PM on March 7, 2018: member

    ACK

  25. laanwj merged this on Mar 7, 2018
  26. laanwj closed this on Mar 7, 2018

  27. laanwj referenced this in commit 3fa24bb217 on Mar 7, 2018
  28. furszy referenced this in commit 85b5f2eb83 on Aug 2, 2020
  29. Stamek referenced this in commit 87ced407c7 on Aug 22, 2020
  30. jasonbcox referenced this in commit 4a728f1473 on Oct 31, 2020
  31. PastaPastaPasta referenced this in commit 5d90db11a0 on Jun 27, 2021
  32. PastaPastaPasta referenced this in commit 99db01e5cd on Jun 28, 2021
  33. PastaPastaPasta referenced this in commit 1026aba5f4 on Jun 28, 2021
  34. PastaPastaPasta referenced this in commit bd203ede2e on Jun 28, 2021
  35. PastaPastaPasta referenced this in commit 22c1d77c23 on Jun 29, 2021
  36. MarcoFalke 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-22 12:15 UTC

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