-
Notifications
You must be signed in to change notification settings - Fork 37.1k
Consensus: Decouple ContextualCheckBlockHeader from checkpoints #5975
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
fixed after a discussion with @theuni on IRC |
@@ -2640,6 +2642,8 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc | |||
if (pindexPrev->nStatus & BLOCK_FAILED_MASK) | |||
return state.DoS(100, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk"); | |||
} | |||
if (!CheckIndexAgainstCheckpoint(pindexPrev, state, params, mapBlockIndex)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't these just return false? state is already set in CheckIndexAgainstCheckpoint().
2 more fixes, ready to squash |
9c38309
to
54f2e9d
Compare
54f2e9d
to
55b98a2
Compare
Needed rebase. |
55b98a2
to
e55ad48
Compare
Somehow I missed this one. Renamed params to chainparams like everywhere else. |
ping @theuni |
@@ -2540,19 +2540,30 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo | |||
return true; | |||
} | |||
|
|||
bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex * const pindexPrev) | |||
static bool CheckIndexAgainstCheckpoint(const CBlockIndex* pindexPrev, CValidationState& state, const CChainParams& chainparams, const BlockMap& mapBlockIndex) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: mapBlockIndex shadows the global, will be confusing when it's used.
ut ack other than the nit |
e55ad48
to
b00583b
Compare
nit solved |
Thanks, looks good. |
assert(pindexPrev); | ||
if (*pindexPrev->phashBlock == chainparams.GetConsensus().hashGenesisBlock) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
b00583b
to
ae6de26
Compare
Needed rebase |
3b008ef
to
6e55325
Compare
@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 |
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 |
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. |
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
It would need to be something like
because pindexPrev shouldn't arrive NULL to ContextualCheckBlockHeader. |
Yes, that looks good. Thanks. |
6e55325
to
102b09b
Compare
Done, changed as suggested by @theuni |
@@ -2715,6 +2712,9 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc | |||
if (pindexPrev->nStatus & BLOCK_FAILED_MASK) | |||
return state.DoS(100, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk"); | |||
} | |||
assert(pindexPrev); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apparently having the check of the global boolean outside of the function is more readable according to @theuni.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I missed this was in AcceptBlockHeader already, and not in ContextualCheckBlockHeader anymore. Looks good.
@sipa I answered to your worries on checking the genesis block. You never answered back so I assume you were satisfied by my answer. |
Untested ACK |
102b09b
to
8d834ec
Compare
Updated without the unused blockIndexMap parameter. |
Sorry: needs rebase after #5927, will merge after that. |
8d834ec
to
425c3a8
Compare
No worries, it was an easy rebase. |
425c3a8 Consensus: Separate CheckIndexAgainstCheckpoint() from ContextualCheckBlockHeader (Jorge Timón)
This appears to have broken running bitcoind with -reindex(!); it appears the |
This fixes an error triggered when running with -reindex after bitcoin#5975
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.