-
Notifications
You must be signed in to change notification settings - Fork 37.7k
Sanity assert GetAncestor() != nullptr where appropriate #24804
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
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.
A couple of initial comments. Minor detail, please don't use @-usernames in the PR description.
Concept ACK with some suggestions for the lines touched here suggested diff for your perusal
diff --git a/src/consensus/tx_verify.cpp b/src/consensus/tx_verify.cpp
index 4f00d6e094..eb731ba205 100644
--- a/src/consensus/tx_verify.cpp
+++ b/src/consensus/tx_verify.cpp
@@ -76,7 +80,7 @@ std::pair<int, int64_t> CalculateSequenceLocks(const CTransaction &tx, int flags
assert(ancestor != nullptr);
- int64_t nCoinTime = ancestor->GetMedianTimePast();
+ const int64_t nCoinTime = ancestor->GetMedianTimePast();
// NOTE: Subtract 1 to maintain nLockTime semantics
diff --git a/src/consensus/tx_verify.h b/src/consensus/tx_verify.h
index 1209c0faa5..1386b029f5 100644
--- a/src/consensus/tx_verify.h
+++ b/src/consensus/tx_verify.h
@@ -446,17 +446,16 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
BOOST_CHECK(!TestSequenceLocks(CTransaction{tx})); // Sequence locks fail
- const int SEQUENCE_LOCK_TIME = 512; // Sequence locks pass 512 seconds later
- for (int i = 0; i < CBlockIndex::nMedianTimeSpan; ++i)
- m_node.chainman->ActiveChain().Tip()->GetAncestor(m_node.chainman->ActiveChain().Tip()->nHeight - i)->nTime += SEQUENCE_LOCK_TIME; //Trick the MedianTimePast
-
- {
+ const int SEQUENCE_LOCK_TIME{512}; // Sequence locks pass 512 seconds later
+ for (int i = 0; i < CBlockIndex::nMedianTimeSpan; ++i) {
+ m_node.chainman->ActiveChain().Tip()->GetAncestor(m_node.chainman->ActiveChain().Tip()->nHeight - i)->nTime += SEQUENCE_LOCK_TIME; // Trick the MedianTimePast
CBlockIndex* active_chain_tip = m_node.chainman->ActiveChain().Tip();
- BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, prevheights, CreateBlockIndex(active_chain_tip->nHeight + 1, active_chain_tip))); // Sequence locks pass 512 seconds later
+ BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, prevheights, CreateBlockIndex(active_chain_tip->nHeight + 1, active_chain_tip)));
}
- for (int i = 0; i < CBlockIndex::nMedianTimeSpan; ++i)
- m_node.chainman->ActiveChain().Tip()->GetAncestor(m_node.chainman->ActiveChain().Tip()->nHeight - i)->nTime -= SEQUENCE_LOCK_TIME; //undo tricked MTP
+ for (int i = 0; i < CBlockIndex::nMedianTimeSpan; ++i) {
+ m_node.chainman->ActiveChain().Tip()->GetAncestor(m_node.chainman->ActiveChain().Tip()->nHeight - i)->nTime -= SEQUENCE_LOCK_TIME; // undo tricked MTP
+ }
// absolute height locked
@@ -501,9 +500,9 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 3U);
- // However if we advance height by 1 and time by 512, all of them should be mined
- for (int i = 0; i < CBlockIndex::nMedianTimeSpan; ++i)
- {
+ // However, if we advance height by 1 and time by SEQUENCE_LOCK_TIME, all of
+ // them should be mined.
+ for (int i = 0; i < CBlockIndex::nMedianTimeSpan; ++i) {
CBlockIndex* ancestor = m_node.chainman->ActiveChain().Tip()->GetAncestor(m_node.chainman->ActiveChain().Tip()->nHeight - i);
assert(ancestor != nullptr);
ancestor->nTime += SEQUENCE_LOCK_TIME; // Trick the MedianTimePast
diff --git a/src/versionbits.cpp b/src/versionbits.cpp
index 9218c6bf26..934bfb015f 100644
--- a/src/versionbits.cpp
+++ b/src/versionbits.cpp
@@ -109,10 +109,6 @@ BIP9Stats AbstractThresholdConditionChecker::GetStateStatisticsFor(const CBlockI
// Find how many blocks are in the current period
int blocks_in_period = 1 + (pindex->nHeight % stats.period);
- // Find beginning of period
- const CBlockIndex* pindexEndOfPrevPeriod = pindex->GetAncestor(pindex->nHeight - ((pindex->nHeight + 1) % stats.period));
- assert(pindexEndOfPrevPeriod != nullptr);
- stats.elapsed = pindex->nHeight - pindexEndOfPrevPeriod->nHeight;
// Reset signalling_blocks |
d297649
to
dcaae44
Compare
Thank you for your review @jonatack, I have addressed your comments. |
44f4141
to
e3250c5
Compare
e3250c5
to
93e516d
Compare
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.
A few suggestions
index a8701cc9aa..c03e975c03 100644
--- a/src/consensus/tx_verify.cpp
+++ b/src/consensus/tx_verify.cpp
@@ -75,7 +75,7 @@ std::pair<int, int64_t> CalculateSequenceLocks(const CTransaction &tx, int flags
int nCoinHeight = prevHeights[txinIndex];
if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) {
- const int64_t nCoinTime = Assert(block.GetAncestor(std::max(nCoinHeight - 1, 0)))->GetMedianTimePast();
+ const int64_t nCoinTime{Assert(block.GetAncestor(std::max(nCoinHeight - 1, 0)))->GetMedianTimePast()};
// NOTE: Subtract 1 to maintain nLockTime semantics
// BIP 68 relative lock times have the semantics of calculating
// the first block or time at which the transaction would be
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index 78bc93c3d4..1d7eb80d78 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -448,14 +448,17 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
const int SEQUENCE_LOCK_TIME = 512; // Sequence locks pass 512 seconds later
for (int i = 0; i < CBlockIndex::nMedianTimeSpan; ++i)
- m_node.chainman->ActiveChain().Tip()->GetAncestor(m_node.chainman->ActiveChain().Tip()->nHeight - i)->nTime += SEQUENCE_LOCK_TIME; //Trick the MedianTimePast
+ m_node.chainman->ActiveChain().Tip()->GetAncestor(m_node.chainman->ActiveChain().Tip()->nHeight - i)->nTime += SEQUENCE_LOCK_TIME; // Trick the MedianTimePast
{
CBlockIndex* active_chain_tip = m_node.chainman->ActiveChain().Tip();
- BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, prevheights, CreateBlockIndex(active_chain_tip->nHeight + 1, active_chain_tip))); // Sequence locks pass 512 seconds later
+ BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, prevheights, CreateBlockIndex(active_chain_tip->nHeight + 1, active_chain_tip)));
}
- for (int i = 0; i < CBlockIndex::nMedianTimeSpan; ++i)
- m_node.chainman->ActiveChain().Tip()->GetAncestor(m_node.chainman->ActiveChain().Tip()->nHeight - i)->nTime -= SEQUENCE_LOCK_TIME; //undo tricked MTP
+ for (int i = 0; i < CBlockIndex::nMedianTimeSpan; ++i) {
+ CBlockIndex* ancestor = m_node.chainman->ActiveChain().Tip()->GetAncestor(m_node.chainman->ActiveChain().Tip()->nHeight - i);
+ assert(ancestor != nullptr);
+ ancestor->nTime -= SEQUENCE_LOCK_TIME; // undo tricked MTP
+ }
// absolute height locked
tx.vin[0].prevout.hash = txFirst[2]->GetHash();
9f9361f
to
977b6b1
Compare
Seems like there is a bug in the CI? I ran the tests on my fork and passed all tests |
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
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. |
ACK 977b6b1 |
…function and NONFATAL_UNREACHABLE macro ee02c8b util/check: Add CHECK_NONFATAL identity function, NONFATAL_UNREACHABLE AND UNREACHABLE macros (Aurèle Oulès) Pull request description: This PR replaces the macro `CHECK_NONFATAL` with an identity function. I simplified the usage of `CHECK_NONFATAL` where applicable in `src/rpc`. This function is useful in sanity checks for RPC and command-line interfaces. Context: bitcoin/bitcoin#24804 (comment). Also adds `UNREACHABLE_NONFATAL` macro. ACKs for top commit: jonatack: ACK ee02c8b MarcoFalke: ACK ee02c8b 🍨 Tree-SHA512: 3cba09223cd7b22e62fe5d0b46c4a024c1d9957d4268ba6d3fb07fcc0a5854fc0886bb3266184e6a7df5df91373b3e84edd6adf6999c4e934aeef8c043b01aa2
977b6b1
to
54070a5
Compare
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.
Left some nits
9075d79
to
a06141f
Compare
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.
LGTM, modulo since the commit is authored by @adamjonas, you could change the first "Co-Authored-By:" in the commit message to yourself.
a06141f
to
c0fcbb7
Compare
ACK c0fcbb7 If you have to retouch, maybe consider --- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -1619,8 +1619,8 @@ static RPCHelpMan getchaintxstats()
const CBlockIndex& past_block{*CHECK_NONFATAL(pindex->GetAncestor(pindex->nHeight - blockcount))};
- int nTimeDiff = pindex->GetMedianTimePast() - past_block.GetMedianTimePast();
- int nTxDiff = pindex->nChainTx - past_block.nChainTx;
+ const int64_t nTimeDiff{pindex->GetMedianTimePast() - past_block.GetMedianTimePast()};
+ const int nTxDiff = pindex->nChainTx - past_block.nChainTx;
@@ -1772,8 +1772,8 @@ static RPCHelpMan getblockstats()
- const CBlock block = GetBlockChecked(chainman.m_blockman, &pindex);
- const CBlockUndo blockUndo = GetUndoChecked(chainman.m_blockman, &pindex);
+ const CBlock& block = GetBlockChecked(chainman.m_blockman, &pindex);
+ const CBlockUndo& blockUndo = GetUndoChecked(chainman.m_blockman, &pindex); |
b0c9d04
to
260a05d
Compare
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.
ACK 260a05d with a couple more suggestions
Add sanity asserts for return value of `CBlockIndex::GetAncestor()` where appropriate. In validation.cpp `CheckSequenceLocks`, check the return value of `tip->GetAncestor(maxInputHeight)` stored into `lp->maxInputBlock`. If it ever returns `nullptr` because the ancestor isn't found, it's going to be a bad bug to keep going, since a `LockPoints` object with the `maxInputBlock` member set to `nullptr` signifies no relative lock time. In the other places, the added asserts would prevent accidental dereferencing of a null pointer which is undefined behavior. Co-Authored-By: Aurèle Oulès <aurele@oules.com> Co-Authored-By: danra <danra@users.noreply.github.com>
260a05d
to
308dd2e
Compare
ACK 308dd2e |
Summary: Add sanity asserts for return value of `CBlockIndex::GetAncestor()` where appropriate. In validation.cpp `CheckSequenceLocks`, check the return value of `tip->GetAncestor(maxInputHeight)` stored into `lp->maxInputBlock`. If it ever returns `nullptr` because the ancestor isn't found, it's going to be a bad bug to keep going, since a `LockPoints` object with the `maxInputBlock` member set to `nullptr` signifies no relative lock time. In the other places, the added asserts would prevent accidental dereferencing of a null pointer which is undefined behavior. Co-Authored-By: Aurèle Oulès <aurele@oules.com> Co-Authored-By: danra <danra@users.noreply.github.com> This is a backport of [[bitcoin/bitcoin#24804 | core#24804]] Test Plan: `ninja all check-all` Reviewers: #bitcoin_abc, Fabien Reviewed By: #bitcoin_abc, Fabien Subscribers: Fabien Differential Revision: https://reviews.bitcoinabc.org/D13242
Re-opening #17232. I have rebased the PR and addressed jonatack's nit suggestions.
Add sanity asserts for return value of
CBlockIndex::GetAncestor()
where appropriate.In validation.cpp
CheckSequenceLocks
, check the return value oftip->GetAncestor(maxInputHeight)
stored intolp->maxInputBlock
. If it ever returnsnullptr
because the ancestor isn't found, it's going to be a bad bug to keep going, since aLockPoints
object with themaxInputBlock
member set tonullptr
signifies no relative lock time.In the other places, the added asserts would prevent accidental dereferencing of a null pointer which is undefined behavior.
Co-Authored-By: Adam Jonas jonas@chaincode.com
Co-Authored-By: danra danra@users.noreply.github.com