Consensus: Decouple ContextualCheckBlockHeader from checkpoints #5975

pull jtimon wants to merge 1 commits into bitcoin:master from jtimon:consensus_checkpoints changing 1 files +19 −16
  1. jtimon commented at 4:08 PM on April 6, 2015: contributor

    By separating a new CheckIndexAgainstCheckpoint() from ContextualCheckBlockHeader(). @theuni you will probably be interested in this since you were doing some work on the checkpoints. I hope it doesn't conflict with what you've done.

    The checkpoints shouldn't be used to check a new block header. Instead, they should be used to check the index (the chain) that it's going to be used to check new block header.

  2. laanwj added the label Improvement on Apr 7, 2015
  3. jtimon commented at 1:26 PM on April 8, 2015: contributor

    fixed after a discussion with @theuni on IRC Now CheckIndexAgainstCheckpoint() takes CChainParams instead of uint256& hashGenesisBlock as parameter to avoid conflicts with work that he is doing in parallel related to checkpoints. Ready for squash. #5968 and #5970 probably need to be adapted to CheckIndexAgainstCheckpoint depending on CChainParams.

  4. jtimon cross-referenced this on Apr 8, 2015 from issue Chainparams: Refactor: Decouple IsSuperMajority from Params() by jtimon
  5. in src/main.cpp:None in 7461d64d85 outdated
    2641 | @@ -2640,6 +2642,8 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc
    2642 |          if (pindexPrev->nStatus & BLOCK_FAILED_MASK)
    2643 |              return state.DoS(100, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk");
    2644 |      }
    2645 | +    if (!CheckIndexAgainstCheckpoint(pindexPrev, state, params, mapBlockIndex))
    


    theuni commented at 4:35 PM on April 8, 2015:

    Shouldn't these just return false? state is already set in CheckIndexAgainstCheckpoint().

  6. jtimon commented at 5:12 PM on April 8, 2015: contributor

    2 more fixes, ready to squash

  7. jtimon force-pushed on Apr 8, 2015
  8. jtimon force-pushed on Apr 8, 2015
  9. jtimon force-pushed on Apr 9, 2015
  10. jtimon force-pushed on Apr 9, 2015
  11. jtimon cross-referenced this on Apr 10, 2015 from issue DEPENDENT: API: Expose bitcoinconsensus_verify_header() in libconsensus by jtimon
  12. jtimon force-pushed on Apr 15, 2015
  13. jtimon commented at 12:00 PM on April 15, 2015: contributor

    Needed rebase.

  14. jtimon force-pushed on Apr 19, 2015
  15. jtimon commented at 9:35 PM on April 19, 2015: contributor

    Somehow I missed this one. Renamed params to chainparams like everywhere else.

  16. jtimon commented at 10:01 AM on April 22, 2015: contributor

    ping @theuni

  17. in src/main.cpp:None in e55ad48336 outdated
    2539 | @@ -2540,19 +2540,30 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
    2540 |      return true;
    2541 |  }
    2542 |  
    2543 | -bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex * const pindexPrev)
    2544 | +static bool CheckIndexAgainstCheckpoint(const CBlockIndex* pindexPrev, CValidationState& state, const CChainParams& chainparams, const BlockMap& mapBlockIndex)
    


    theuni commented at 10:28 PM on April 22, 2015:

    nit: mapBlockIndex shadows the global, will be confusing when it's used.

  18. theuni commented at 11:14 PM on April 22, 2015: member

    ut ack other than the nit

  19. jtimon force-pushed on Apr 22, 2015
  20. jtimon commented at 11:32 PM on April 22, 2015: contributor

    nit solved

  21. jtimon cross-referenced this on Apr 23, 2015 from issue MOVEONLY: Consensus: Move most of consensus functions (pre-block) by jtimon
  22. theuni commented at 9:06 PM on April 23, 2015: member

    Thanks, looks good.

  23. jtimon cross-referenced this on Apr 24, 2015 from issue Decouple checkpoints from Params() by theuni
  24. in src/main.cpp:None in b00583b134 outdated
    2547 | -    uint256 hash = block.GetHash();
    2548 | -    if (hash == consensusParams.hashGenesisBlock)
    2549 | -        return true;
    2550 | -
    2551 |      assert(pindexPrev);
    2552 | +    if (*pindexPrev->phashBlock == chainparams.GetConsensus().hashGenesisBlock)
    


    sipa commented at 10:11 AM on April 24, 2015:

    I'd rather keep comparisons with the genesis block out of the "checkpoints" logic. That's purely philosophical, but we may get rid of checkpoints at some point, though the genesis block will always remain part of consensus.


    jtimon commented at 10:11 AM on April 25, 2015:

    Well, the question is, should we validate the genesis block? I don't think so, the genesis block is hardcoded, no need to check it redundantly from many computers. So this is more moving that check out of consensus than "moving it to the checkpoints logic".

    But of course, if your the tip of the chain index you're using (your pindexPrev) is the genesis block (that is, if you're validating the second block), you can skip the other checkpoint tests.

    What you want to check is that your chain index contains the genesis block. Or with checkpoints, you may even want to just check that your chain index contains the previous checkpoint (you have to be certain that all your checkpoints contain the genesis block when your hardcode them). In that sense you can see the genesis block just as the oldest checkpoint possible.

    But thanks for bringing this up, this is the only change in logic and what needs discussion.

  25. jtimon cross-referenced this on Apr 24, 2015 from issue MOVEONLY-ish: Move most block header validation function defintions to consensus/blockverify.cpp by jtimon
  26. jtimon force-pushed on May 6, 2015
  27. jtimon commented at 10:45 AM on May 6, 2015: contributor

    Needed rebase

  28. jtimon force-pushed on May 6, 2015
  29. jtimon force-pushed on May 6, 2015
  30. theuni commented at 4:29 PM on May 6, 2015: member

    @jtimon I think #6055 was a big improvement in readability for the checkpoint functions because it moved the "what if checkpoints aren't enabled" case out of the actual checkpoint logic. This would undo some of that.

    How about removing the early return from CheckIndexAgainstCheckpoint() and instead calling into it like if (fCheckpointsEnabled && !CheckIndexAgainstCheckpoint(...)) ?

  31. jtimon commented at 4:52 PM on May 6, 2015: contributor

    I disagree that this undoes part of #6055 but I'm ok with your proposed alternative. I thought about it too but I didn't wanted to take the assert(pindexPrev); out of the function as well.

  32. theuni commented at 5:09 PM on May 6, 2015: member

    Sorry, that was poorly worded. It wouldn't undo any of #6055, but it would negate one of the beneficial side-effects of it.

    As for not removing the assert, I don't follow. pindexPrev is used whether checkpoints are enabled or not, so relying on the assert in CheckIndexAgainstCheckpoint() even if checkpoints are disabled makes no sense to me.

  33. jtimon commented at 5:15 PM on May 6, 2015: contributor

    I still disagree that it is removing one of the beneficial side effects of it, I don't think the negated condition is less readable...

    Anyway, what I mean is that if I want to maintain it almost equivalent (is not completely equivalent functionally because I'm changing the genesis check as discussed in the outdated comment by @sipa), I can't do just

    if (fCheckpointsEnabled && !CheckIndexAgainstCheckpoint(...))
    

    It would need to be something like

    assert(pindexPrev);
    if (fCheckpointsEnabled && !CheckIndexAgainstCheckpoint(...))
    

    because pindexPrev shouldn't arrive NULL to ContextualCheckBlockHeader. But I'm fine with that, should I change it to that, then?

  34. theuni commented at 5:27 PM on May 6, 2015: member

    Yes, that looks good. Thanks.

  35. jtimon force-pushed on May 6, 2015
  36. jtimon commented at 5:44 PM on May 6, 2015: contributor

    Done, changed as suggested by @theuni

  37. in src/main.cpp:None in 102b09bff5 outdated
    2711 | @@ -2715,6 +2712,9 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc
    2712 |          if (pindexPrev->nStatus & BLOCK_FAILED_MASK)
    2713 |              return state.DoS(100, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk");
    2714 |      }
    2715 | +    assert(pindexPrev);
    


    sipa commented at 11:10 PM on May 7, 2015:

    Any reason why the checkpoints check is moved?

    I think it's harmless to do so, but I was wondering if there is a reason.


    jtimon commented at 10:28 AM on May 8, 2015:

    Apparently having the check of the global boolean outside of the function is more readable according to @theuni.


    theuni commented at 7:39 PM on May 9, 2015:

    @sipa if you're referring to fCheckpointsEnabled moving out of CheckIndexAgainstCheckpoint(), I requested that to reduce the side-effects of CheckIndexAgainstCheckpoint(). Imo if possible the checkpoint functions should be side-effect free so that we know it's consensus-safe to simply not call them at all.


    sipa commented at 11:30 PM on May 9, 2015:

    I'm referring to the fCheckpointsEnabled conditional. Just to the fact that the checkpoints-checking point in this function moving.


    jtimon commented at 12:45 PM on May 10, 2015:

    @sipa I'm still not sure what you mean. The checkpoints checks are moved out of ContextualCheckBlockHeader to keep them out of consensus. Then is moved up in the functions, because you should have your index checked before checking a new block, maybe they can be moved upper (and earlier in time) later. I suspect the index is checked in this way redundantly. If this is an issue I can maintain the calls to CheckIndexAgainstCheckpoint right before the calls to ContextualCheckBlockHeader.


    sipa commented at 8:39 PM on May 10, 2015:

    Sorry, I missed this was in AcceptBlockHeader already, and not in ContextualCheckBlockHeader anymore. Looks good.

  38. in src/main.cpp:None in 102b09bff5 outdated
    2823 | @@ -2824,8 +2824,11 @@ bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDis
    2824 |  
    2825 |  bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex * const pindexPrev, bool fCheckPOW, bool fCheckMerkleRoot)
    2826 |  {
    2827 | +    const CChainParams& chainparams = Params();
    2828 |      AssertLockHeld(cs_main);
    2829 | -    assert(pindexPrev == chainActive.Tip());
    2830 | +    assert(pindexPrev && pindexPrev == chainActive.Tip());
    2831 | +    if (fCheckpointsEnabled && !CheckIndexAgainstCheckpoint(pindexPrev, state, chainparams, block.GetHash(), mapBlockIndex))
    2832 | +        return error("%s: CheckIndexAgainstCheckpoint(): %s", __func__, state.GetRejectReason().c_str());
    


    sipa commented at 3:07 AM on May 8, 2015:

    No need to print an error in this case; it's perfectly legitimate that this fails.

    EDIT: Hmm, the rest of the checks prints stuff too. Never mind then, but I think we should fix that independently (there are probably already issues about that).


    jtimon commented at 10:32 AM on May 8, 2015:

    Yes I'm trying to move the errors up (because logging errrors shouldnt be done in consensus, but one step at a time. That is the kind of change that is better done after the moveonly, hopefully, one day...

  39. jtimon commented at 10:34 AM on May 8, 2015: contributor

    @sipa I answered to your worries on checking the genesis block. You never answered back so I assume you were satisfied by my answer.

  40. sipa cross-referenced this on May 10, 2015 from issue Reduce checkpoints' effect on consensus. by sipa
  41. sipa commented at 9:30 PM on May 10, 2015: member

    Untested ACK

  42. jtimon force-pushed on May 27, 2015
  43. jtimon commented at 1:45 PM on May 27, 2015: contributor

    Updated without the unused blockIndexMap parameter. It may take long until it gets used so better to just introduce it at that point.

  44. laanwj commented at 8:42 AM on June 10, 2015: member

    Sorry: needs rebase after #5927, will merge after that.

  45. Consensus: Separate CheckIndexAgainstCheckpoint() from ContextualCheckBlockHeader 425c3a87ff
  46. jtimon force-pushed on Jun 10, 2015
  47. jtimon commented at 11:13 AM on June 10, 2015: contributor

    No worries, it was an easy rebase.

  48. laanwj merged this on Jun 10, 2015
  49. laanwj closed this on Jun 10, 2015

  50. laanwj referenced this in commit 1fea667216 on Jun 10, 2015
  51. sdaftuar commented at 6:56 PM on June 16, 2015: member

    This appears to have broken running bitcoind with -reindex(!); it appears the assert(pindexPrev) in AcceptBlockHeader can be reached when processing the genesis block from disk. Can be reproduced by running qa/rpc-tests/reindex.py.

  52. sdaftuar cross-referenced this on Jun 16, 2015 from issue Reindex broken in master by sdaftuar
  53. laanwj cross-referenced this on Jun 17, 2015 from issue test: Move reindex test to standard tests by laanwj
  54. jtimon referenced this in commit 460c57e049 on Jun 17, 2015
  55. jtimon cross-referenced this on Jun 17, 2015 from issue Bugfix: Don't check the genesis block header before accepting it by jtimon
  56. jtimon commented at 7:30 PM on June 17, 2015: contributor

    @sdaftuar created #6299 to fix the bug.

  57. jtimon referenced this in commit b6e00e8f13 on Jun 18, 2015
  58. jtimon referenced this in commit 36c97b4e5d on Jun 20, 2015
  59. str4d cross-referenced this on Feb 14, 2017 from issue Bitcoin 0.12 misc PRs 1 by str4d
  60. zkbot referenced this in commit df07f9ad23 on Feb 15, 2017
  61. bitcoin 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-05-20 06:55 UTC