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
Rework validation logic for assumeutxo #27746
Rework validation logic for assumeutxo #27746
Conversation
Great! Thanks for this. I'm active in these neighborhoods today as well, since adding some |
beb5334
to
379467a
Compare
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. 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. |
The first two commits up to f50fa24 look good to me. How do you see the division of labor between
In any case moving |
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.
If you can split 534b6f9 in ~half that would make it a bit easier to review. Maybe start with anything that's trivial to move, and then do the more involved changes in the second commit.
src/validation.cpp
Outdated
// that build on blocks for which we actually have all the data, while the | ||
// snapshot chainstate (if we have one) is able to build on blocks that are | ||
// missing but for which BLOCK_ASSUME_VALID is set. | ||
// So this is broken right now. XXX |
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.
534b6f9 if it's broken in master, can we fix it before refactoring? Alternatively there could be a This will be fixed in the next commit
comment.
I'm also confused by the comment. TryAddBlockIndexCandidate
is only called from ReceivedBlockTransactions
after it sets BLOCK_VALID_TRANSACTIONS
. So are you saying we're currently too strict? Was there a regression somewhere?
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 that comment was confusing. I dropped it, and instead change the behavior around managing setBlockIndexCandidates
in the last two commits.
I think master has a couple bugs. When we start up, in LoadBlockIndex()
we weren't adding blocks that have been downloaded and have more work than the background chainstate's tip to setBlockIndexCandidates
, which prevents those blocks from being validated and connected on startup. Also, because AcceptBlock()
is a member of Chainstate
, it's at best confusing to reason about whether a block that would advance the tip of a chainstate would always be added to a chainstate's setBlockIndexCandidates
(it depends on yet-more logic around where a block came from and guessing about which chainstate might need it).
The new code tries to simplify things by establishing that the background chainstate is only trying to connect blocks towards the snapshot block, and that all blocks for which we HAVE_DATA and have more work than the background chainstate's tip (and which are ancestors of the snapshot block) will be added to the background chainstate's setBlockIndexCandidates
. Also, the logic bug in LoadBlockIndex
should be fixed in the last commit here.
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.
re: #27746 (comment)
I think master has a couple bugs.
I'm curious if there is actually more than one bug. The one bug I know about is the bug introduced
0fd599a
from #23174 where LoadBlockIndex
is misinterpreting the BLOCK_ASSUMED_VALID
flag, and setting first_assumed_valid_height
to the height of the first assumed valid block, instead of the height of the first block after the last assumed valid block (i.e. the snapshot height). I think it's pretty bad that we didn't catch this bug in review, or push for a more realistic test that would have caught it, or followed up on the suggestion from Marco #23174 (comment) to just add blocks to setBlockIndexCandidates
linearly, which is what this PR does, and is much more straightforward.
Are there other known bugs? Are the changes to AcceptBlock
meant to fix a bug or more to prevent a potential bug? Does the change to ChainstateManager::ReceivedBlockTransactions
fix a bug? It seems like maybe it could prevent inappropriate blocks being added as candidates to the background chainstate, but it's not clear.
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 guess the fairest thing to say is that the changes to AcceptBlock()
are to prevent a future bug -- it's possible that we could write code that somehow gets it right, but the design of selectively adding blocks to one chainstate's block index, and not the other, is one that I found very confusing.
As an example, if you took #24008 (which proposed logic for determining which chainstate to invoke AcceptBlock() on) and combined that with changing the logic in AcceptBlock()
so that the background chainstate wouldn't bother processing blocks that are past the snapshot base, then that would be problematic if we were to allow pruning the snapshot-based-chain while the background sync is running (because according to the logic in #24008, if the block is already on the active chain, then we give it to the background chainstate to process). That's 2 hypotheticals so certainly this is speculative, but I think that those changes would all make sense on their own, so the fact that they fail to compose with the code in master is a sign to me that we should take a different design.
I think of I think |
379467a
to
a959bf6
Compare
a959bf6
to
0c44733
Compare
0c44733
to
bccd618
Compare
bccd618
to
48de8dc
Compare
48de8dc
to
89e8826
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.
Concept ACK
src/validation.cpp
Outdated
// The active chainstate should always add entries that have more work than the tip. | ||
// For the background chainstate, we only consider connecting blocks | ||
// towards the snapshot base. | ||
bool is_bg_chainstate = m_chainman.IsSnapshotActive() && m_chainman.IsBackgroundChainstate(this) && !m_disabled; |
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.
how about inserting and returning here in the !is_bg_chainstate
case, so that we can skip the GetAncestor()
call when dealing with the snapshot chainstate?
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.
Agreed, good idea.
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.
If you retouch, I think you can simply say bool is_bg_chainstate = this != &ActiveChainstate();
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.
Good idea -- and it looks like my code here is wrong anyway, because if we're a disabled background chainstate, then we'll be adding blocks to setBlockIndexCandidates as long as they have more work than the tip!
89e8826
to
f02125f
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 f02125f
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.
Partial code review ACK f02125f. I've looked at most of this, but not the whole thing yet, and all the changes seem very nice. This should help avoid bugs and make assumeutxo code more maintainable. I think it would be good to clean up documentation as part of this too. Here are documentation changes I would suggest:
--- a/doc/design/assumeutxo.md
+++ b/doc/design/assumeutxo.md
@@ -17,10 +17,9 @@ respectively generate and load UTXO snapshots. The utility script
- A new block index `nStatus` flag is introduced, `BLOCK_ASSUMED_VALID`, to mark block
index entries that are required to be assumed-valid by a chainstate created
- from a UTXO snapshot. This flag is mostly used as a way to modify certain
+ from a UTXO snapshot. This flag is used as a way to modify certain
CheckBlockIndex() logic to account for index entries that are pending validation by a
- chainstate running asynchronously in the background. We also use this flag to control
- which index entries are added to setBlockIndexCandidates during LoadBlockIndex().
+ chainstate running asynchronously in the background.
- The concept of UTXO snapshots is treated as an implementation detail that lives
behind the ChainstateManager interface. The external presentation of the changes
diff --git a/src/chain.h b/src/chain.h
index f5dd0fd31514..cb8bc7f04792 100644
--- a/src/chain.h
+++ b/src/chain.h
@@ -113,10 +113,10 @@ enum BlockStatus : uint32_t {
BLOCK_VALID_TRANSACTIONS = 3,
//! Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends, BIP30.
- //! Implies all parents are also at least CHAIN.
+ //! Implies all parents are either at least VALID_CHAIN, or are ASSUMED_VALID
BLOCK_VALID_CHAIN = 4,
- //! Scripts & signatures ok. Implies all parents are also at least SCRIPTS.
+ //! Scripts & signatures ok. Implies all parents are either at least VALID_SCRIPTS, or are ASSUMED_VALID.
BLOCK_VALID_SCRIPTS = 5,
//! All validity bits.
@@ -134,10 +134,18 @@ enum BlockStatus : uint32_t {
BLOCK_OPT_WITNESS = 128, //!< block data in blk*.dat was received with a witness-enforcing client
/**
- * If set, this indicates that the block index entry is assumed-valid.
- * Certain diagnostics will be skipped in e.g. CheckBlockIndex().
- * It almost certainly means that the block's full validation is pending
- * on a background chainstate. See `doc/design/assumeutxo.md`.
+ * If ASSUMED_VALID is set, it means that this block has not been validated
+ * and has validity status less than VALID_SCRIPTS. Also that it has
+ * descendant blocks with VALID_SCRIPTS set, because they were validated
+ * based on an assumeutxo snapshot.
+ *
+ * When an assumeutxo snapshot is loaded, the ASSUMED_VALID flag is added to
+ * unvalidated blocks below the snapshot height. Then, as the background
+ * validation progresses, and these blocks are validated, the ASSUMED_VALID
+ * flags are removed. See `doc/design/assumeutxo.md` for details.
+ *
+ * This flag is only used to implement checks in CheckBlockIndex() and
+ * should not be used elsewhere.
*/
BLOCK_ASSUMED_VALID = 256,
};
re: PR description #27746 (comment)
base block is: the block hash
Grammar here seems off, maybe replace with "base block, and the base block hash"
re: PR description #27746 (comment)
This code needs a lot of cleanup and test fixes and so I've marked it as a draft -- help from reviewers would be welcome!
Could drop this part since PR seems to be a good state to review and merge.
re: #27746 (comment)
I think AcceptBlock could also be a static function in validation.cpp
IMO, would be nice make it a standalone function (static or not). Unless a function is really tied to one particular class or needs access to its private state, better for it just be standalone and use the public interface.
@@ -138,16 +134,15 @@ BOOST_AUTO_TEST_CASE(chainstatemanager_rebalance_caches) | |||
|
|||
// Create a snapshot-based chainstate. | |||
// | |||
Chainstate& c2 = WITH_LOCK(cs_main, return manager.ActivateExistingSnapshot(&mempool, GetRandHash())); |
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.
In commit "Tighten requirements for adding elements to setBlockIndexCandidates" (b0b48b3)
Note for reviewers: A real hash is being passed instead of GetRandHash() now, because of discussion #27746 (comment), because ActivateExistingSnapshot
should not be expected to work when called with an invalid blockhash even if it does work now.
src/validation.h
Outdated
void UpdateSnapshotBaseEntry(const CBlockIndex *entry) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) | ||
{ m_snapshot_entry = entry; } | ||
|
||
//! Track the snapshot entry |
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.
In commit "Explicitly track snapshot block header when using multiple chainstates" (d2ccbd3)
I don't think adding this Chainstate::m_snapshot_entry
variable is a good idea. I don't like how it has different meanings for different chainstates (starting point of validation for the snapshot chainstate, and ending point for the background chainstate), and the lack of documentation, and the complicated initialization which happens in the Chainstate constructor for the snapshot chainstate, but also in ActivateSnapshot
for both chainstates, and then again in LoadBlockIndex
for both chainstates, and pointedly not in ActivateExistingSnapshot
according to a new comment there saying it will be initialized later... It just seems like a lot of complexity for new variable which is redundant with the existing m_from_snapshot_blockhash
variable and is only used one place, in Chainstate::TryAddBlockIndexCandidate
.
I think it would be better if Chainstate::TryAddBlockIndexCandidate
just used snapshot chainstate's m_from_snapshot_blockhash
value directly. Or if that is too inefficient, we could add a m_from_snapshot_blockindex
member that mirrors m_from_snapshot_blockhash
and is const and could be initialized straightforwardly in the ChainState
constructor.
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 think I concur with @ryanofsky here. I'll have to double check, but in actual usage in #27596, I think I found that the one usage of this had another (existing) way of getting at this data. I'm afk for a few days, but will verify when I get back.
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 agree with your criticisms that the way this is written is pretty confusing (it took me a while to get it right in the first place, and I found this hard to reason about).
I wanted to capture the idea that the hash m_from_snapshot_blockhash
must always be in our block index, so that we never have to worry when we look it up in the block index that it might be missing, and we have to deal with a nullptr case.
However, I couldn't see how to make it a const that is straightforwardly initialized in Chainstate
, because there are two different cases to consider (activating a snapshot for the first time, versus detecting that we have a snapshot on restart).
Also, while this PR introduces one place where this CBlockIndex is used, I expect that we'll use it again in the net_processing
code which will download blocks toward the snapshot base.
Here are a few options I can think of to improve this:
- just look the hash up every time we need to use it (both in
TryAddBlockIndexCandidate
and wherever it is needed innet_processing
, likely one additional place), avoiding the storage of redundant information - lazily fill it in so that we only look it up once, and then use the looked-up value for future requests
- move the knowledge of the snapshot base to
ChainstateManager
, so that we don't store redundant information in both chainstates (this could be done along with either of the first two ideas, I think?)
EDIT: Gah, I just noticed ChainstateManager::GetSnapshotBaseBlock()
, didn't realize we already had that. I think I know what to do now to fix this!
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.
re: #27746 (comment)
EDIT: Gah, I just noticed ChainstateManager::GetSnapshotBaseBlock(), didn't realize we already had that. I think I know what to do now to fix this!
Thanks, I didn't realize how clunky ChainstateManager initialization was when I made that suggestion. Particularly how it allowed construction with that snapshot block that wasn't actually in the index. I think initialization can definitely be simplified later. But even without doing that I experimented a little and came up with a change that adds CS::SnapshotBase()
and CSM::ActiveSnapshotBase()
methods that I think should provide a good interface for external code to use, while allowing us to clean up the internal representation and init process later:
--- a/src/validation.h
+++ b/src/validation.h
@@ -528,12 +528,8 @@ protected:
//! is set to true on the snapshot chainstate.
bool m_disabled GUARDED_BY(::cs_main) {false};
- void UpdateSnapshotBaseEntry(const CBlockIndex *entry) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
- { m_snapshot_entry = entry; }
-
- //! Track the snapshot entry
- const CBlockIndex* m_snapshot_entry GUARDED_BY(::cs_main) {nullptr};
-
+ //! Cached result of LookupBlockIndex(*m_from_snapshot_blockhash)
+ const CBlockIndex* m_cached_snapshot_base GUARDED_BY(::cs_main) {nullptr};
public:
//! Reference to a BlockManager instance which itself is shared across all
@@ -586,6 +582,13 @@ public:
*/
const std::optional<uint256> m_from_snapshot_blockhash;
+ /**
+ * The base of the snapshot this chainstate was created from.
+ *
+ * nullptr if this chainstate was not created from a snapshot.
+ */
+ const CBlockIndex* SnapshotBase() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
+
//! Return true if this chainstate relies on blocks that are assumed-valid. In
//! practice this means it was created based on a UTXO snapshot.
bool reliesOnAssumedValid() { return m_from_snapshot_blockhash.has_value(); }
@@ -1093,6 +1096,11 @@ public:
return m_snapshot_chainstate && m_ibd_chainstate && m_ibd_chainstate->m_disabled;
}
+ const CBlockIndex* ActiveSnapshotBase() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
+ {
+ return m_active_chainstate ? m_active_chainstate->SnapshotBase() : nullptr;
+ }
+
/**
* Import blocks from an external file
*
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -1579,9 +1579,13 @@ Chainstate::Chainstate(
m_chainman(chainman),
m_from_snapshot_blockhash(from_snapshot_blockhash)
{
- if (m_from_snapshot_blockhash) {
- m_snapshot_entry = WITH_LOCK(::cs_main, return m_chainman.m_blockman.LookupBlockIndex(*m_from_snapshot_blockhash));
- }
+}
+
+const CBlockIndex* Chainstate::SnapshotBase()
+{
+ if (!m_from_snapshot_blockhash) return nullptr;
+ if (!m_cached_snapshot_base) m_cached_snapshot_base = Assert(m_chainman.m_blockman.LookupBlockIndex(*m_from_snapshot_blockhash));
+ return m_cached_snapshot_base;
}
void Chainstate::InitCoinsDB(
@@ -3423,8 +3427,9 @@ void Chainstate::TryAddBlockIndexCandidate(CBlockIndex* pindex)
// For the background chainstate, we only consider connecting blocks
// towards the snapshot base (which can't be nullptr or else we'll
// never make progress).
- assert(m_snapshot_entry != nullptr);
- if (m_snapshot_entry->GetAncestor(pindex->nHeight) == pindex) {
+ const CBlockIndex* snapshot_base{m_chainman.ActiveSnapshotBase()};
+ assert(snapshot_base != nullptr);
+ if (snapshot_base->GetAncestor(pindex->nHeight) == pindex) {
setBlockIndexCandidates.insert(pindex);
}
}
@@ -4416,14 +4421,6 @@ bool ChainstateManager::LoadBlockIndex()
bool ret{m_blockman.LoadBlockIndexDB()};
if (!ret) return false;
- // If we already have 2 chainstates, then we need to update the
- // snapshot base to point to the correct block entry.
- if (IsSnapshotActive()) {
- CBlockIndex *entry = m_blockman.LookupBlockIndex(*SnapshotBlockhash());
- m_ibd_chainstate->UpdateSnapshotBaseEntry(entry);
- m_snapshot_chainstate->UpdateSnapshotBaseEntry(entry);
- }
-
m_blockman.ScanAndUnlinkAlreadyPrunedFiles();
std::vector<CBlockIndex*> vSortedByHeight{m_blockman.GetAllBlockIndices()};
@@ -5142,8 +5139,6 @@ bool ChainstateManager::ActivateSnapshot(
m_snapshot_chainstate->CoinsTip().DynamicMemoryUsage() / (1000 * 1000));
this->MaybeRebalanceCaches();
-
- m_ibd_chainstate->m_snapshot_entry = m_snapshot_chainstate->m_snapshot_entry;
}
return true;
}
@@ -5623,8 +5618,6 @@ Chainstate& ChainstateManager::ActivateExistingSnapshot(CTxMemPool* mempool, uin
std::make_unique<Chainstate>(mempool, m_blockman, *this, base_blockhash);
LogPrintf("[snapshot] switching active chainstate to %s\n", m_snapshot_chainstate->ToString());
m_active_chainstate = m_snapshot_chainstate.get();
- // Note: m_snapshot_entry will be populated after the block index is
- // loaded; see ChainstateManager::LoadBlockIndex.
return *m_snapshot_chainstate;
}
src/validation.cpp
Outdated
// that build on blocks for which we actually have all the data, while the | ||
// snapshot chainstate (if we have one) is able to build on blocks that are | ||
// missing but for which BLOCK_ASSUME_VALID is set. | ||
// So this is broken right now. XXX |
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.
re: #27746 (comment)
I think master has a couple bugs.
I'm curious if there is actually more than one bug. The one bug I know about is the bug introduced
0fd599a
from #23174 where LoadBlockIndex
is misinterpreting the BLOCK_ASSUMED_VALID
flag, and setting first_assumed_valid_height
to the height of the first assumed valid block, instead of the height of the first block after the last assumed valid block (i.e. the snapshot height). I think it's pretty bad that we didn't catch this bug in review, or push for a more realistic test that would have caught it, or followed up on the suggestion from Marco #23174 (comment) to just add blocks to setBlockIndexCandidates
linearly, which is what this PR does, and is much more straightforward.
Are there other known bugs? Are the changes to AcceptBlock
meant to fix a bug or more to prevent a potential bug? Does the change to ChainstateManager::ReceivedBlockTransactions
fix a bug? It seems like maybe it could prevent inappropriate blocks being added as candidates to the background chainstate, but it's not clear.
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.
Comments around 768690b.
It would be nice if the documentation for setBlockIndexCandidates
and m_blocks_unlinked
explained their purpose (as opposed to merely describing what's in them).
/**
* The set of all CBlockIndex entries that are - or recently
* were - candidates for a new tip. These are as good as our
* current tip or better, and must either have BLOCK_VALID_TRANSACTIONS
* (for itself and all ancestors) *or* BLOCK_ASSUMED_VALID (if using
* background chainstates). Entries may be failed, though, and
* pruning nodes may be missing the data for the block.
*/
… setBlockIndexCandidates
/**
* CBlockIndex entries removed from setBlockIndexCandidates due
* to pruned data for themselves or their ancestors.
*/
… m_blocks_unlinked`
(The above still doesn't satisfyingly explain why we hold them in m_blocks_unlinked
rather than treat them as any other block index entry. I assume it's because we use the list to proactively aks for these blocks?)
Suggested documentation for TryAddBlockIndexCandidate
:
/**
* Add CBlockIndex entry to setBlockIndexCandidates if it has more
* work than the current tip. For the background chainstate, we only
* consider connecting blocks towards the snapshot base
*/
// If we have an assumeutxo-based chainstate, then the snapshot | ||
// block will be a candidate for the tip, but it may not be | ||
// VALID_TRANSACTIONS (eg if we haven't yet downloaded the block), | ||
// so we special-case the snapshot block as a potential candidate |
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.
768690b: Maybe clarify that initially this only applies to the snapshot chainstate, which uses the base block as its starting point. For the background chainstate, as well an active chainstate not created from a snapshot, GetSnapshotBaseBlock()
is nullptr
so the special-case won't apply. But the background state will consider it a candidate once it's been downloaded.
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.
re: #27746 (comment)
GetSnapshotBaseBlock()
isnullptr
so the special-case won't apply
I may be misunderstanding, but I don't think it's true that GetSnapshotBaseBlock
is null for the background chainstate. This is a ChainstateManager method, so GetSnapshotBaseBlock
is going to be non-null if any snapshot is loaded, and this code will try to add the snapshot block to both chainstates, even though it's not needed for the background chainstate. It might be clearer if the code narrowed the special case, and only added the snapshot block to the snapshot chainstate where it was actually needed, not to both chainstates. But that might make the code more complicated.
I do think it might be better if the comment said "assumeutxo snapshot chainstate" instead of "assumeutxo-based chainstate" to be more specific about when this special case is needed, but I don't think it need to go into detail about other cases where the check is harmless and not needed.
@@ -412,7 +412,7 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_activate_snapshot, SnapshotTestSetup) | |||
//! - Then mark a region of the chain BLOCK_ASSUMED_VALID and introduce a second chainstate | |||
//! that will tolerate assumed-valid blocks. Run LoadBlockIndex() and ensure that the first |
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.
//!
//! - Run LoadBlockIndex() and ensure that setBlockIndexCandidates of the first ...
// The assumed-valid tolerant chain has the assumed valid base as a | ||
// candidate, but otherwise has none of the assumed-valid (which do not | ||
// HAVE_DATA) blocks as candidates. | ||
BOOST_CHECK_EQUAL(cs2.setBlockIndexCandidates.count(validated_tip), 0); | ||
BOOST_CHECK_EQUAL(cs2.setBlockIndexCandidates.count(assumed_tip), 1); |
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.
768690b: this had me confused, but it's because the test considers a scenario where the snapshot base block has been downloaded. It could be nice to include the moment before it's downloaded where this should be 0
.
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.
re: #27746 (comment)
768690b: this had me confused, but it's because the test considers a scenario where the snapshot base block has been downloaded. It could be nice to include the moment before it's downloaded where this should be
0
.
This review comment does not match my understanding. The snapshot block is assumed_base
at height 39 and it does not have data. This line is checking assumed_tip
block at height 100 which does have data.
I think all the variable names in this test are pretty confusing, and it would probably be clearer if blocks were referred to directly by height, but that's the was the test style, so it's not changing.
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.
@@ -3920,13 +3922,13 @@ bool Chainstate::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockV | |||
// process an unrequested block if it's new and has enough work to | |||
// advance our tip, and isn't too many blocks ahead. | |||
bool fAlreadyHave = pindex->nStatus & BLOCK_HAVE_DATA; | |||
bool fHasMoreOrSameWork = (m_chain.Tip() ? pindex->nChainWork >= m_chain.Tip()->nChainWork : true); | |||
bool fHasMoreOrSameWork = (ActiveTip() ? pindex->nChainWork >= ActiveTip()->nChainWork : true); |
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.
d0d40ea Maybe add: Background validation always ignores unrequested blocks.
@@ -3974,7 +3977,7 @@ bool Chainstate::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockV | |||
|
|||
// Header is valid/has work, merkle tree and segwit merkle tree are good...RELAY NOW | |||
// (but if it does not build on our best tip, let the SendMessages loop relay it) |
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.
d0d40ea: // We don't relay background validation blocks.
re: #27746 (review)
I also found this pretty confusing when I was reviewing it and found a helpful explanation here: https://en.bitcoin.it/wiki/Bitcoin_Core_0.11_(ch_6):_The_Blockchain. The description of
So I think the map just exists for efficiency, not to proactively do anything. It would be great to improve documentation in the actual code, though. |
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.
Code review ACK a733dd7. Just suggested changes since the last review. There are various small things that could be followed up on, but I think this is ready for merge.
// If we have an assumeutxo-based chainstate, then the snapshot | ||
// block will be a candidate for the tip, but it may not be | ||
// VALID_TRANSACTIONS (eg if we haven't yet downloaded the block), | ||
// so we special-case the snapshot block as a potential candidate |
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.
re: #27746 (comment)
GetSnapshotBaseBlock()
isnullptr
so the special-case won't apply
I may be misunderstanding, but I don't think it's true that GetSnapshotBaseBlock
is null for the background chainstate. This is a ChainstateManager method, so GetSnapshotBaseBlock
is going to be non-null if any snapshot is loaded, and this code will try to add the snapshot block to both chainstates, even though it's not needed for the background chainstate. It might be clearer if the code narrowed the special case, and only added the snapshot block to the snapshot chainstate where it was actually needed, not to both chainstates. But that might make the code more complicated.
I do think it might be better if the comment said "assumeutxo snapshot chainstate" instead of "assumeutxo-based chainstate" to be more specific about when this special case is needed, but I don't think it need to go into detail about other cases where the check is harmless and not needed.
// The assumed-valid tolerant chain has the assumed valid base as a | ||
// candidate, but otherwise has none of the assumed-valid (which do not | ||
// HAVE_DATA) blocks as candidates. | ||
BOOST_CHECK_EQUAL(cs2.setBlockIndexCandidates.count(validated_tip), 0); |
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.
In commit "Fix initialization of setBlockIndexCandidates when working with multiple chainstates" (768690b)
Would be good to directly verify the snapshot block is included:
// block before the snapshot is excluded (as well as earlier blocks)
BOOST_CHECK_EQUAL(cs2.setBlockIndexCandidates.count(assumed_base->pprev), 0);
// snapshot block is included (as well as later blocks)
BOOST_CHECK_EQUAL(cs2.setBlockIndexCandidates.count(assumed_base), 1);
// The assumed-valid tolerant chain has the assumed valid base as a | ||
// candidate, but otherwise has none of the assumed-valid (which do not | ||
// HAVE_DATA) blocks as candidates. | ||
BOOST_CHECK_EQUAL(cs2.setBlockIndexCandidates.count(validated_tip), 0); | ||
BOOST_CHECK_EQUAL(cs2.setBlockIndexCandidates.count(assumed_tip), 1); |
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.
re: #27746 (comment)
768690b: this had me confused, but it's because the test considers a scenario where the snapshot base block has been downloaded. It could be nice to include the moment before it's downloaded where this should be
0
.
This review comment does not match my understanding. The snapshot block is assumed_base
at height 39 and it does not have data. This line is checking assumed_tip
block at height 100 which does have data.
I think all the variable names in this test are pretty confusing, and it would probably be clearer if blocks were referred to directly by height, but that's the was the test style, so it's not changing.
@@ -412,7 +412,7 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_activate_snapshot, SnapshotTestSetup) | |||
//! - Then mark a region of the chain BLOCK_ASSUMED_VALID and introduce a second chainstate | |||
//! that will tolerate assumed-valid blocks. Run LoadBlockIndex() and ensure that the first | |||
//! chainstate only contains fully validated blocks and the other chainstate contains all blocks, | |||
//! even those assumed-valid. | |||
//! except those marked assume-valid, because those entries don't HAVE_DATA. |
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.
In commit "Fix initialization of setBlockIndexCandidates when working with multiple chainstates" (768690b)
I think it's a little misleading to say the other chainstate contains all block except those marked assume-valid because:
- It actually does contain one block marked assumed-valid, which is the snapshot base (block 39)
- It also excludes other blocks which are not assumed-valid because they don't have more work than the tip (blocks 1-19)
I think this comment could incorporate sjors suggestion above and just say "Run LoadBlockIndex() and ensure that setBlockIndexCandidates of the first chainstate only contains blocks leading to the snapshot base, and that setBlockIndexCandidates of the second chainstate only contains blocks following the snapshot base."
Or could leave out the details and say "Run LoadBlockIndex() and check setBlockIndexCandidates of both chainstates."
@@ -113,10 +113,10 @@ enum BlockStatus : uint32_t { | |||
BLOCK_VALID_TRANSACTIONS = 3, |
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.
re: #27746 (comment)
0ce805b: why isn't
BLOCK_VALID_TRANSACTIONS
also alternativelyASSUMED_VALID
?
I'm not sure what this review comment is asking. The code comment above still seems accurate to me, but it maybe it could be improved.
Post-merge ACK a733dd7 Very happy with the separation of concerns between blockstorage and validation. |
Post-merge code review ACK a733dd7 I also synced and kept a node running for a few days with the status of my previous ACK and didn't see anything unusual. |
…ChainstateManager This change makes IsInitialBlockDownload and NotifyHeaderTip functions no longer tied to individual Chainstate objects. It makes them work with the ChainstateManager object instead so code is simpler and it is no longer possible to call them incorrectly with an inactive Chainstate. This change also makes m_cached_finished_ibd caching easier to reason about, because now there is only one cached value instead of two (for background and snapshot chainstates) so the cached IBD state now no longer gets reset when a snapshot is loaded. There should be no change in behavior because these functions were always called on the active ChainState objects. These changes were discussed previously bitcoin#27746 (comment) and bitcoin#27746 (comment) as possible followups for that PR.
…ChainstateManager This change makes IsInitialBlockDownload and NotifyHeaderTip functions no longer tied to individual Chainstate objects. It makes them work with the ChainstateManager object instead so code is simpler and it is no longer possible to call them incorrectly with an inactive Chainstate. This change also makes m_cached_finished_ibd caching easier to reason about, because now there is only one cached value instead of two (for background and snapshot chainstates) so the cached IBD state now no longer gets reset when a snapshot is loaded. There should be no change in behavior because these functions were always called on the active ChainState objects. These changes were discussed previously bitcoin#27746 (comment) and bitcoin#27746 (comment) as possible followups for that PR.
…ChainstateManager This change makes IsInitialBlockDownload and NotifyHeaderTip functions no longer tied to individual Chainstate objects. It makes them work with the ChainstateManager object instead so code is simpler and it is no longer possible to call them incorrectly with an inactive Chainstate. This change also makes m_cached_finished_ibd caching easier to reason about, because now there is only one cached value instead of two (for background and snapshot chainstates) so the cached IBD state now no longer gets reset when a snapshot is loaded. There should be no change in behavior because these functions were always called on the active ChainState objects. These changes were discussed previously bitcoin#27746 (comment) and bitcoin#27746 (comment) as possible followups for that PR.
…ChainstateManager This change makes IsInitialBlockDownload and NotifyHeaderTip functions no longer tied to individual Chainstate objects. It makes them work with the ChainstateManager object instead so code is simpler and it is no longer possible to call them incorrectly with an inactive Chainstate. This change also makes m_cached_finished_ibd caching easier to reason about, because now there is only one cached value instead of two (for background and snapshot chainstates) so the cached IBD state now no longer gets reset when a snapshot is loaded. There should be no change in behavior because these functions were always called on the active ChainState objects. These changes were discussed previously bitcoin#27746 (comment) and bitcoin#27746 (comment) as possible followups for that PR.
…ChainstateManager This change makes IsInitialBlockDownload and NotifyHeaderTip functions no longer tied to individual Chainstate objects. It makes them work with the ChainstateManager object instead so code is simpler and it is no longer possible to call them incorrectly with an inactive Chainstate. This change also makes m_cached_finished_ibd caching easier to reason about, because now there is only one cached value instead of two (for background and snapshot chainstates) so the cached IBD state now no longer gets reset when a snapshot is loaded. There should be no change in behavior because these functions were always called on the active ChainState objects. These changes were discussed previously bitcoin#27746 (comment) and bitcoin#27746 (comment) as possible followups for that PR.
…ChainstateManager This change makes IsInitialBlockDownload and NotifyHeaderTip functions no longer tied to individual Chainstate objects. It makes them work with the ChainstateManager object instead so code is simpler and it is no longer possible to call them incorrectly with an inactive Chainstate. This change also makes m_cached_finished_ibd caching easier to reason about, because now there is only one cached value instead of two (for background and snapshot chainstates) so the cached IBD state now no longer gets reset when a snapshot is loaded. There should be no change in behavior because these functions were always called on the active ChainState objects. These changes were discussed previously bitcoin#27746 (comment) and bitcoin#27746 (comment) as possible followups for that PR.
…NotifyHeaderTip not require a Chainstate 94a98fb assumeutxo cleanup: Move IsInitialBlockDownload & NotifyHeaderTip to ChainstateManager (Ryan Ofsky) Pull request description: This change makes `IsInitialBlockDownload` and `NotifyHeaderTip` functions no longer tied to individual `Chainstate` objects. It makes them work with the `ChainstateManager` object instead so code is simpler and it is no longer possible to call them incorrectly with an inactive `Chainstate`. This change also makes `m_cached_finished_ibd` caching easier to reason about, because now there is only one cached value instead of two (for background and snapshot chainstates) so the cached IBD state now no longer gets reset when a snapshot is loaded. There should be no change in behavior because these functions were always called on the active `ChainState` objects. These changes were discussed previously bitcoin/bitcoin#27746 (comment) and bitcoin/bitcoin#27746 (comment) as possible followups for that PR. ACKs for top commit: MarcoFalke: re-ACK 94a98fb 🐺 naumenkogs: ACK 94a98fb dergoegge: reACK 94a98fb Tree-SHA512: 374d6e5c9bbc7564c143f634bd709a4e8f4a42c8d77e7a8554c832acdcf60fa2a134f3ea10827db1a1e0191006496329c0ebf5c64f3ab868398c3722bb7ff56f
…ChainstateManager This change makes IsInitialBlockDownload and NotifyHeaderTip functions no longer tied to individual Chainstate objects. It makes them work with the ChainstateManager object instead so code is simpler and it is no longer possible to call them incorrectly with an inactive Chainstate. This change also makes m_cached_finished_ibd caching easier to reason about, because now there is only one cached value instead of two (for background and snapshot chainstates) so the cached IBD state now no longer gets reset when a snapshot is loaded. There should be no change in behavior because these functions were always called on the active ChainState objects. These changes were discussed previously bitcoin/bitcoin#27746 (comment) and bitcoin/bitcoin#27746 (comment) as possible followups for that PR.
// VALID_TRANSACTIONS (eg if we haven't yet downloaded the block), | ||
// so we special-case the snapshot block as a potential candidate | ||
// here. | ||
if (pindex == GetSnapshotBaseBlock() || |
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.
In commit "Fix initialization of setBlockIndexCandidates when working with multiple chainstates" (768690b)
It looks like there may be a bug in this code because this pindex == GetSnapshotBaseBlock()
special case will add the snapshot block to setBlockIndexCandidates
whether or not it has data, but there is also an assert in FindMostWorkChain
which asserts that blocks in setBlockIndexCandidates
do have data:
Line 2914 in c5a63ea
assert(pindexTest->HaveTxsDownloaded() || pindexTest->nHeight == 0); |
I think it's not possible to hit this assert for the snapshot chainstate, but it may be possible to hit this assert for the background chainstate.
For the snapshot chainstate, I think the assert won't be reached because after the snapshot is loaded the Chainstate::LoadChainTip
function should immediately set the chain tip to the snapshot block index:
Line 4153 in c5a63ea
m_chain.SetTip(*pindex); |
so the m_chain.Contains(pindexTest)
check before the assert will be false and the assert will not run:
Lines 2913 to 2914 in c5a63ea
while (pindexTest && !m_chain.Contains(pindexTest)) { | |
assert(pindexTest->HaveTxsDownloaded() || pindexTest->nHeight == 0); |
But for the background chainstate, it seems possible assert could be hit if FindMostWorkChain
is called before the snapshot block is downloaded.
In any case, this special pindex == GetSnapshotBaseBlock()
case seems overbroad. It seems like it should only apply to the snapshot chainstate, not the background chainstate, and I'm not actually sure why it is necessary to have at all if Chainstate::LoadChainTip
is already going to set the snapshot block as the snapshot chainstate tip.
I think the interaction between these checks and the checks inside the TryAddBlockIndexCandidate
are also unnecessarily confusing, and it would be nice whether there is a bug or not to move all the move all the checks inside TryAddBlockIndexCandidate
and call it unconditionally. This should make it easeir to avoid adding the snapshot block the background chainstate candidate set before it is downloaded. It would also be great to drop the snapshot block special case entirely if it is not needed.
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.
It looks like there may be a bug in this code because this pindex == GetSnapshotBaseBlock() special case will add the snapshot block to setBlockIndexCandidates whether or not it has data, but there is also an assert in FindMostWorkChain which asserts that blocks in setBlockIndexCandidates do have data:
bitcoin/src/validation.cpp
Line 2914 in c5a63eaassert(pindexTest->HaveTxsDownloaded() || pindexTest->nHeight == 0);I think it's not possible to hit this assert for the snapshot chainstate, but it may be possible to hit this assert for the background chainstate.
If I'm reading FindMostWorkChain()
correctly, this assert won't be hit for a background chainstate, because the second clause of this condition
while (pindexTest && !m_chain.Contains(pindexTest)) {
will exclude the snapshot base block from consideration without data (since it is not in the background chainstate's m_chain
until it is actually downloaded, and so has data). So as far as I can tell, there's no bug here - but I'm glad you're double checking this; the setBlockIndexCandidates
code is very confusing indeed, and I'm amenable to any way we can make it more easily understandable.
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.
re: #27746 (comment)
The way I'm reading e code:
Lines 2913 to 2914 in c5a63ea
while (pindexTest && !m_chain.Contains(pindexTest)) { | |
assert(pindexTest->HaveTxsDownloaded() || pindexTest->nHeight == 0); |
If a snapshot is loaded and pindexTest
points to the snapshot block and the snapshot block is not yet downloaded, and m_chain
is the background chain, then m_chain.Contains(pindexTest)
will be false, so the while loop condition will be true, and the assert could be be hit.
You seem to be saying that m_chain.Contains(pindexTest)
will be false, so the while condition won't be hit?
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'm sorry, my previous comment was more or less incorrect. Another reason why the assert you mention doesn't pose a problem is because, confusingly, HaveTxsDownloaded()
is just an alias for nChainTx != 0
. Since we manually set nChainTx for the snapshot base block (315586f) this check (again, very confusingly) passes. At some point long ago I made a note somewhere about fixing that method's misleading name...
So the long story short is that FindMostWorkChain()
eventually works for the background chainstate because it detects, correctly, that there are blocks with missing data between the IBD tip and the snapshot base, and correctly rewinds m_chain
back to the actual IBD tip. I think when @sdaftuar first proposed this change I was confused about why the LoadBlockIndex()
simplification could actually work, and this is the 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.
So the long story short is that FindMostWorkChain() eventually works for the background chainstate because it detects, correctly, that there are blocks with missing data between the IBD tip and the snapshot base, and correctly rewinds m_chain back to the actual IBD tip.
Again I'm wrong: snapshot base block never makes it into background chainstate's m_chain
because LoadChainTip()
(when called from the init code in src/node/chainstate.cpp
) sets the background chainstate's tip to the correct IBD tip (on the basis of the coinscache GetBestBlock()
), which is before the snapshot base block.
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.
Thanks, I missed that HaveTxsDownloaded was checking nChainTx
not nTx
.
I guess the main thing I'm confused about now is why this pindex == GetSnapshotBaseBlock() ||
special case is needed at all? If LoadChainTip()
already sets the snapshot block to be the snapshot tip, why does the snapshot block need to be added to the candidate set?
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 guess the main thing I'm confused about now is why this pindex == GetSnapshotBaseBlock() || special case is needed at all? If LoadChainTip() already sets the snapshot block to be the snapshot tip, why does the snapshot block need to be added to the candidate set?
I'm not sure if there's a more fundamental reason, but various assertions fail if this case is stripped out of LoadBlockIndex(); e.g. the !setBlockIndexCandidates.empty()
assertion fails during PruneBlockIndexCandidates()
if this special case is not included.
The true purpose of setBlockIndexCandidates has always been somewhat mysterious to me, but the most essential use seems to be in FindMostWorkChain(), to supply candidates for activation in ActivateBestChain()
.
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've added some documentation for HaveTxsDownloaded()
(9f9ffb6), and I'm happy to add more for the confusing process discussed above.
…ChainstateManager This change makes IsInitialBlockDownload and NotifyHeaderTip functions no longer tied to individual Chainstate objects. It makes them work with the ChainstateManager object instead so code is simpler and it is no longer possible to call them incorrectly with an inactive Chainstate. This change also makes m_cached_finished_ibd caching easier to reason about, because now there is only one cached value instead of two (for background and snapshot chainstates) so the cached IBD state now no longer gets reset when a snapshot is loaded. There should be no change in behavior because these functions were always called on the active ChainState objects. These changes were discussed previously bitcoin#27746 (comment) and bitcoin#27746 (comment) as possible followups for that PR.
Release note for changing -permitbaremultisig config default to false Remove unused MessageStartChars parameters from BlockManager methods tracepoints: Disables `-Wgnu-zero-variadic-macro-arguments` to compile without warnings Fixes #26916 by disabling the warning `-Wgnu-zero-variadic-macro-arguments` when clang is used as the compiler. lint: drop DIR_IWYU global lint: remove lint-logs.py lint: remove /* Continued */ markers from codebase refactor: fix unterminated LogPrintf()s tidy: Integrate bicoin-tidy clang-tidy plugin Enable `bitcoin-unterminated-logprintf`. Co-authored-by: Cory Fields <cory-nospam-@coryfields.com> doc: remove Fedora libdb4-*-devel install docs These are no-longer installable on any recent Fedora (33+). Remove the install instructions. Fix the typo in the Ubuntu/Debian instructions. refactor: Wrap DestroyDB in dbwrapper helper Wrap leveldb::DestroyDB in a helper function without exposing leveldb-specifics. Also, add missing optional include. The context of this commit is an effort to decouple the dbwrapper header file from leveldb includes. To this end, the includes are moved to the dbwrapper implementation file. This is done as part of the kernel project to reduce the number of required includes for users of the kernel. refactor: Split dbwrapper CDBBatch::Write implementation Keep the generic serialization in the header, while moving leveldb-specifics to the implementation file. The context of this commit is an effort to decouple the dbwrapper header file from leveldb includes. To this end, the includes are moved to the dbwrapper implementation file. This is done as part of the kernel project to reduce the number of required includes for users of the kernel. refactor: Split dbwrapper CDBatch::Erase implementation Keep the generic serialization in the header, while moving leveldb-specifics to the implementation file. The context of this commit is an effort to decouple the dbwrapper header file from leveldb includes. To this end, the includes are moved to the dbwrapper implementation file. This is done as part of the kernel project to reduce the number of required includes for users of the kernel. refactor: Pimpl leveldb::batch for CDBBatch Hide the leveldb::WriteBatch member variable with a pimpl in order not to expose it directly in the header. Also move CDBBatch::Clear to the dbwrapper implementation to use the new impl_batch. The context of this commit is an effort to decouple the dbwrapper header file from leveldb includes. To this end, the includes are moved to the dbwrapper implementation file. This is done as part of the kernel project to reduce the number of required includes for users of the kernel. refactor: Split dbwrapper CDBIterator::Seek implementation Keep the generic serialization in the header, while moving leveldb-specifics to the implementation file. The context of this commit is an effort to decouple the dbwrapper header file from leveldb includes. To this end, the includes are moved to the dbwrapper implementation file. This is done as part of the kernel project to reduce the number of required includes for users of the kernel. refactor: Split dbwrapper CDBIterator::GetKey implementation Keep the generic serialization in the header, while moving leveldb-specifics to the implementation file. The context of this commit is an effort to decouple the dbwrapper header file from leveldb includes. To this end, the includes are moved to the dbwrapper implementation file. This is done as part of the kernel project to reduce the number of required includes for users of the kernel. refactor: Split dbwrapper CDBIterator::GetValue implementation Keep the generic serialization in the header, while moving leveldb-specifics to the implementation file. The context of this commit is an effort to decouple the dbwrapper header file from leveldb includes. To this end, the includes are moved to the dbwrapper implementation file. This is done as part of the kernel project to reduce the number of required includes for users of the kernel. refactor: Pimpl leveldb::Iterator for CDBIterator Hide the leveldb::Iterator member variable with a pimpl in order not to expose it directly in the header. Also, move CDBWrapper::NewIterator to the dbwrapper implementation to use the pimpl for CDBIterator initialziation. The context of this commit is an effort to decouple the dbwrapper header file from leveldb includes. To this end, the includes are moved to the dbwrapper implementation file. This is done as part of the kernel project to reduce the number of required includes for users of the kernel. refactor: Split dbwrapper CDBWrapper::Read implementation Keep the generic serialization in the header, while moving leveldb-specifics to the implementation file. The context of this commit is an effort to decouple the dbwrapper header file from leveldb includes. To this end, the includes are moved to the dbwrapper implementation file. This is done as part of the kernel project to reduce the number of required includes for users of the kernel. refactor: Fix logging.h includes These were uncovered as missing by the next commit. refactor: Split dbwrapper CDBWrapper::Exists implementation Keep the generic serialization in the header, while moving leveldb-specifics to the implementation file. The context of this commit is an effort to decouple the dbwrapper header file from leveldb includes. To this end, the includes are moved to the dbwrapper implementation file. This is done as part of the kernel project to reduce the number of required includes for users of the kernel. refactor: Move HandleError to dbwrapper implementation Make it a static function in dbwrapper.cpp, since it is not used elsewhere and when left in the header, would expose a leveldb type. The context of this commit is an effort to decouple the dbwrapper header file from leveldb includes. To this end, the includes are moved to the dbwrapper implementation file. This is done as part of the kernel project to reduce the number of required includes for users of the kernel. refactor: Split dbwrapper CDBWrapper::EstimateSize implementation Keep the generic serialization in the header, while moving leveldb-specifics to the implementation file. Since CharCast is no longer needed in the header, move it to the implementation file. The context of this commit is an effort to decouple the dbwrapper header file from leveldb includes. To this end, the includes are moved to the dbwrapper implementation file. This is done as part of the kernel project to reduce the number of required includes for users of the kernel. refactor: Move CDBWrapper leveldb members to their own context struct The context of this commit is an effort to decouple the dbwrapper header file from leveldb includes. To this end, the includes are moved to the dbwrapper implementation file. This is done as part of the kernel project to reduce the number of required includes for users of the kernel. build: Remove leveldb from BITCOIN_INCLUDES Since leveldb is no longer in our header tree, move its include flags to whereever dbwrapper.cpp is built. refactor: Correct dbwrapper key naming The ss- prefix should connotate a DataStream variable. Now that these variables are byte spans, drop the prefix. ci: Use qemu-user through container engine doc: document PeerManager::Options members net processing: clamp -maxorphantx to uint32_t bounds net processing: clamp -blockreconstructionextratxn to uint32_t bounds Also changes max_extra_txs into a uint32_t to avoid platform-specific behaviour doc: Add release note crypto: remove outdated variant of ChaCha20Poly1305 AEAD Remove the variant of ChaCha20Poly1305 AEAD that was previously added in anticipation of BIP324 using it. BIP324 was updated to instead use rekeying wrappers around otherwise unmodified versions of the ChaCha20 stream cipher and the ChaCha20Poly1305 AEAD as specified in RFC8439. crypto: add the ChaCha20Poly1305 AEAD as specified in RFC8439 This adds an implementation of the ChaCha20Poly1305 AEAD exactly matching the version specified in RFC8439 section 2.8, including tests and official test vectors. crypto: add FSChaCha20, a rekeying wrapper around ChaCha20 This adds the FSChaCha20 stream cipher as specified in BIP324, a wrapper around the ChaCha20 stream cipher (specified in RFC8439 section 2.4) which automatically rekeys every N messages, and manages the nonces used for encryption. Co-authored-by: dhruv <856960+dhruv@users.noreply.github.com> crypto: add FSChaCha20Poly1305, rekeying wrapper around ChaCha20Poly1305 This adds the FSChaCha20Poly1305 AEAD as specified in BIP324, a wrapper around the ChaCha20Poly1305 AEAD (as specified in RFC8439 section 2.8) which automatically rekeys every N messages, and automatically increments the nonce every message. bench: add benchmark for FSChaCha20Poly1305 Add a benchmark for FSChaCha20Poly1305 encryption, so the overhead of key generation and authentication can be observed for various message sizes. crypto: support split plaintext in ChaCha20Poly1305 Encrypt/Decrypt Add BIP324Cipher, encapsulating key agreement, derivation, and stream/AEAD ciphers Co-authored-by: dhruv <856960+dhruv@users.noreply.github.com> tests: add decryption test to bip324_tests doc: use llvm-config for bitcoin-tidy example An LLVM installation will have `llvm-config` available to query for info. Ask it for the `--cmakedir`, and use that in our bitcoin-tidy example, rather than listing multiple different (potential) paths per distro/OS etc. bitcoin-tidy: fix macOS build LLVM uses these options for building as well, so there's precedent. Also fix the shared library extension which was incorrectly being set to dylib test: locked_wallet, skip default fee estimation Same as we do with the nodes default wallets. No test case on this file is meant to exercise fee estimation. fuzz: coins_view: correct an incorrect assertion It is incorrect to assert that `cache.HaveCoin()` will always be `true` if `backend.HaveCoin()` is. The coin could well have been marked as spent in the cache but not yet flushed, in which case `cache.HaveCoin()` would return `false`. Note this was never hit because `exists_using_have_coin_in_backend` is currently never `true` (it's the default implementation of `CCoinsView`. However this might change if we were to add a target where the backend is a `CCoinsViewDB`. fuzz: coins_view: remove an incorrect assertion Again, this was not hit because the default implementation of `CCoinsView` return `false` for `GetCoin`. crypto: BIP324 ciphersuite follow-up follow-up to #28008. * move `dummy_tag` variable in FSChaCha20Poly1305 crypto_tests outside of the loop to be reused every time * use easy to read `cipher.last()` in `AEADChaCha20Poly1305::Decrypt()` * comment for initiator in `BIP324Cipher::Initialize()` * systematically damage ciphertext with bit positions in bip324_tests * use 4095 max bytes for aad in bip324 fuzz test refactor: add missing headers for BIP324 ciphersuite ci: Drop no longer needed `macos_sdk_cache` It has been cached in the Docker image since https://github.com/bitcoin/bitcoin/pull/27028. ci: Drop BASE_SCRATCH_DIR from LIBCXX_DIR Using a hard-coded path avoids non-determinism issues and improves CI UX. ci: Only create folders when needed Now that container volumes are used, the folders are no longer mounted. They are only needed when running without a container engine (docker, podman). ci: Use hard-coded root path for CI containers ci: Run "macOS native x86_64" job on GitHub Actions Also, the "macOS native arm64" task has been removed from Cirrus CI. Remove unused boost signals2 from torcontrol iwyu on torcontrol Replace LocaleIndependentAtoi with ToIntegral No need for saturating behavior when the int is composed of 3 digits. remove unused limits.h include in compat.h Sort includes in compat.h Can be reviewed with: --color-moved=blocks --color-moved-ws=ignore-all-space --ignore-all-space test: check backup from `migratewallet` can be successfully restored ci: Fix macOS-cross SDK rsync This should fix the macOS-cross build on Cirrus CI containers. Locally this was already working, because the SDK was cached in /ci_container_base/ in the image, which is also the folder used for a later CI run. However, on Cirrus CI, when using an image *and* a custom BASE_ROOT_DIR, the SDK will not be found in /ci_base_install/, nor in BASE_ROOT_DIR. Fix this by normalizing *all* folders to /ci_container_base/. ci: Avoid error on macOS native This avoids "mkdir: /ci_container_base: Read-only file system" mempool_entry: add mempool entry sequence number validation: when adding txs due to a block reorg, allow immediate relay net_processing: drop m_recently_announced_invs bloom filter Rather than using a bloom filter to track announced invs, simply allow a peer to request any tx that entered the mempool prior to the last INV message we sent them. This also obsoletes the UNCONDITIONAL_RELAY_DELAY. net_processing: don't add txids to m_tx_inventory_known_filter We no longer have m_recently_announced_invs, so there is no need to add txids to m_tx_inventory_known_filter to dedupe that filter. test: Check tx from disconnected block is immediately requestable Check that peers can immediately request txs from blocks that have been reorged out and are now in our mempool. net_processing: Clean up INVENTORY_BROADCAST_MAX constants mempool_entry: improve struct packing ci: Move tidy to persistent worker refactor: Remove PERSISTENT_WORKER_* yaml templates * PERSISTENT_WORKER_TEMPLATE_ENV is not needed at all, because RESTART_CI_DOCKER_BEFORE_RUN is already set on the persistent worker. * PERSISTENT_WORKER_TEMPLATE can be replaced by pinning the previous_releases task to a type of worker. This should make the CI performance more consistent. Move MANDATORY_SCRIPT_VERIFY_FLAGS from script/standard.h to policy/policy.h Remove ScriptHash from CScriptID constructor Replaces the constructor in CScriptID that converts a ScriptHash with a function ToScriptID that does the same. This prepares for a move of CScriptID to avoid a circular dependency. Move CScriptID to script.{h/cpp} CScriptID should be next to CScript just as CKeyID is next to CPubKey Move Taproot{SpendData/Builder} to signingprovider.{h/cpp} TaprootSpendData and TaprootBuilder are used in signing in SigningProvider contexts, so they should live near that. Move CTxDestination to its own file CTxDestination is really our internal representation of an address and doesn't really have anything to do with standard script types, so move them to their own file. MOVEONLY: Move datacarrier defaults to policy.h Clean up things that include script/standard.h Remove standard.h from files that don't use anything in it, and include it in files that do. Clean up script/standard.{h/cpp} includes Rename script/standard.{cpp/h} to script/solver.{cpp/h} Since script/standard only contains things that are used by the Solver and its callers, rename the files to script/solver. Rework receive buffer pushback Co-authored-by: Anthony Towns <aj@erisian.com.au> test: Fix intermittent issue in mining_getblocktemplate_longpoll.py Bugfix: RPC: Remove quotes from non-string oneline descriptions RPC/rpcdoccheck: Error if a oneline_description has a quote for a non-string RPC/Mining: Document template_request better for getblocktemplate ci: Ensure that only a single workflow processes `github.ref` at a time ci: Refactor: Remove CI_USE_APT_INSTALL rpc: remove one more quote from non-string oneline description This fixes a silent conflict betwen #28123 and #27460 crypto: refactor ChaCha20 classes to use Span<std::byte> interface random: simplify FastRandomContext::randbytes using fillrand crypto: require key on ChaCha20 initialization fuzz: support std::byte in Consume{Fixed,Variable}LengthByteVector tests: miscellaneous hex / std::byte improvements crypto: make ChaCha20::SetKey wipe buffer doc: Fix bitcoin-unterminated-logprintf tidy comments * Move module description from test to LogPrintfCheck * Add test doc * Remove unused comment, see https://github.com/bitcoin/bitcoin/pull/26296/files#r1279351539 refactor: Enforce C-str fmt strings in WalletLogPrintf() refactor: Enable all clang-tidy plugin bitcoin tests This makes it easier to add new ones without having to modify this file every time. bitcoin-tidy: Apply bitcoin-unterminated-logprintf to spkm as well ci: Add missing ${CI_RETRY_EXE} before curl ci: Add missing amd64 to win64-cross task Also, do the same for android, which also fails. assumeutxo cleanup: Move IsInitialBlockDownload & NotifyHeaderTip to ChainstateManager This change makes IsInitialBlockDownload and NotifyHeaderTip functions no longer tied to individual Chainstate objects. It makes them work with the ChainstateManager object instead so code is simpler and it is no longer possible to call them incorrectly with an inactive Chainstate. This change also makes m_cached_finished_ibd caching easier to reason about, because now there is only one cached value instead of two (for background and snapshot chainstates) so the cached IBD state now no longer gets reset when a snapshot is loaded. There should be no change in behavior because these functions were always called on the active ChainState objects. These changes were discussed previously https://github.com/bitcoin/bitcoin/pull/27746#discussion_r1246868905 and https://github.com/bitcoin/bitcoin/pull/27746#discussion_r1237552792 as possible followups for that PR. ci: Disable cache save for pull requests in GitHub Actions Otherwise, multiple pull requests fill GitHub Actions cache quota shortly. tx fees, policy: doc: update and delete unnecessary comment test: ensure acceptstalefeeestimates is supported only on regtest chain test: fix 'unknown named parameter' test in `wallet_basic` Fixes loop when testing an unknown named parameter. Remove unused includes from txmempool.h ... and move them to where they are really needed. This was found by IWYU: txmempool.h should remove these lines: - #include <random.h> // lines 29-29 - class CBlockIndex; // lines 43-43 - class Chainstate; // lines 45-45 Also, move the stdlib section to the right place. Can be reviewed with: --color-moved=dimmed-zebra move-only: Create src/kernel/mempool_removal_reason.h This is needed for a future commit. Can be reviewed with: --color-moved=dimmed-zebra Remove unused includes from blockfilter.h This removes unused includes, primitives/block found manually, and the others by iwyu: blockfilter.h should remove these lines: - #include <serialize.h> // lines 16-16 - #include <undo.h> // lines 18-18 Remove unused includes from wallet.cpp This removes unused includes, such as undo.h or txmempool.h from wallet.cpp. Also, add missing ones, according to IWYU. test: Support riscv64 in get_previous_releases.py refactor: Add missing includes Refactor: Remove confusing static_cast guix: pre time-machine bump changes (Windows) Split out of #27897. This is some refactoring to the Windows Guix build that facilitates bumping our Guix time-machine. Namely, avoiding `package-with-extra-configure-variable`, which is non-functional in the newer time-machine, see https://issues.guix.gnu.org/64436. At the same time, consolidate our Windows GCC build into mingw-w64-base-gcc. Rename `gcc-10-remap-guix-store.patch` to avoid changing it whenever GCC changes. We move the old `building-on` inside `explicit-cross-configure`, so that non-windows builds continue to work. Note that `explicit-cross-configure` will be going away entirely (see #27897). [test framework] make it easier to fast-forward setmocktime Have each TestNode keep track of the last timestamp it called setmocktime with, and add a bumpmocktime() function to bump by a number of seconds. Makes it easy to fast forward n seconds without keeping track of what the last timestamp was. [functional test] transaction orphan handling ci: Switch remaining tasks to self-hosted This allows to drop unused templates, such as cirrus_ephemeral_worker_template_env, or container_depends_template. Also, ccache_cache, previous_releases_cache, and base_depends_built_cache can be dropped, because the caching is done in container volumes on the self-hosted runners. ci: Remove distro-name from task name The exact distro name should not be important. Also, it is easy to find out, if needed. Thus, remove it to avoid bloat and maintenance overhead having to keep it in sync. doc, policy: Clarify comment on STANDARD_SCRIPT_VERIFY_FLAGS Make post-p2sh consensus rules mandatory for tx relay Update help text for spend and rawtransaction rpcs fixing typo guix: consolidate glibc 2.27 package Refactor our glibc 2.27 to be a single 'package', and avoid the use of `package-with-extra-configure-variable`. This also lets us drop the `enable_werror` workaround, and just use --disable-werror directly. Employ the same workaround as the Guix glibc, to avoid a "permission denied" failure during build: ```bash make subdir=sunrpc -C sunrpc ..=../ subdir_install make[2]: Entering directory '/tmp/guix-build-glibc-cross-x86_64-linux-gnu-2.27.drv-0/source/sunrpc' .././scripts/mkinstalldirs /gnu/store/ga8jciqrd5lh52m572x3mk4q1smf5agq-glibc-cross-x86_64-linux-gnu-2.27/include/rpc mkdir -p -- /gnu/store/ga8jciqrd5lh52m572x3mk4q1smf5agq-glibc-cross-x86_64-linux-gnu-2.27/include/rpc /gnu/store/kvpvk5wh70wdbjnr83hh85rg22ysxm9h-coreutils-8.32/bin/install -c -m 644 rpc/netdb.h /gnu/store/ga8jciqrd5lh52m572x3mk4q1smf5agq-glibc-cross-x86_64-linux-gnu-2.27/include/rpc/netdb.h .././scripts/mkinstalldirs /gnu/store/ga8jciqrd5lh52m572x3mk4q1smf5agq-glibc-cross-x86_64-linux-gnu-2.27/include/nfs mkdir -p -- /gnu/store/ga8jciqrd5lh52m572x3mk4q1smf5agq-glibc-cross-x86_64-linux-gnu-2.27/include/nfs /gnu/store/kvpvk5wh70wdbjnr83hh85rg22ysxm9h-coreutils-8.32/bin/install -c -m 644 ../sysdeps/unix/sysv/linux/nfs/nfs.h /gnu/store/ga8jciqrd5lh52m572x3mk4q1smf5agq-glibc-cross-x86_64-linux-gnu-2.27/include/nfs/nfs.h /gnu/store/kvpvk5wh70wdbjnr83hh85rg22ysxm9h-coreutils-8.32/bin/install -c -m 644 /tmp/guix-build-glibc-cross-x86_64-linux-gnu-2.27.drv-0/build/gnu/lib-names-64.h /gnu/store/ga8jciqrd5lh52m572x3mk4q1smf5agq-glibc-cross-x86_64-linux-gnu-2.27/include/gnu/lib-names-64.h /gnu/store/kvpvk5wh70wdbjnr83hh85rg22ysxm9h-coreutils-8.32/bin/install -c -m 644 etc.rpc /etc/rpc /gnu/store/kvpvk5wh70wdbjnr83hh85rg22ysxm9h-coreutils-8.32/bin/install: cannot create regular file '/etc/rpc': Permission denied make[2]: *** [Makefile:197: /etc/rpc] Error 1 ``` guix: consolidate Linux GCC package Refactor our Linux GCC to be a single 'package', and avoid the use of `package-with-extra-configure-variable`. ci: Limit scope of some env vars No need to have a larger scope than needed. Can be reviewed with --color-moved=dimmed-zebra ci: Start with clean env This should help to avoid non-determinism. ci: Remove no longer applicable section This fails with: "Error: determining starting point for build: no FROM statement found" test: Fix intermittent issue in mempool_reorg ci: Use concurrency for pull requests only Otherwise, any previously pending workflow will be canceled on the following push. test: wallet_backup.py, fix intermittent failure in "restore using dumped wallet" The failure arises because the test expects 'init_wallet()' (the test framework function) creating a wallet with no keys. However, the function also imports the deterministic private key used to receive the coinbase coins. This causes a race within the "restore using dumped wallet" case, where we intend to have a new wallet (with no existing keys) to test the 'importwallet()' RPC result. The reason behind the intermittent failures might be other peers delivering the chain right after node2 startup (sync of the validation queue included) and prior to the 'node2.getbalance()' check. test: previous releases: speed up fetching sources with shallow clone For the sake of building previous releases, fetching the whole history of the repository for each version seems to be overkill as it takes much more time, bandwidth and disk space than necessary. Create a shallow clone instead with history truncated to the one commit of the version tag, which is directly checked out in the same command. This has the nice side-effect that we can remove the extra `git checkout` step after as it's not needed anymore. Note that it might look confusing to pass a _tag_ to a parameter named `--branch`, but the git-clone manpage explicitly states that this is supported. ci: Add missing docker.io prefix to CI_IMAGE_NAME_TAG rpc: Add MaybeArg() and Arg() default helper refactor: merge transport serializer and deserializer into Transport class This allows state that is shared between both directions to be encapsulated into a single object. Specifically the v2 transport protocol introduced by BIP324 has sending state (the encryption keys) that depends on received messages (the DH key exchange). Having a single object for both means it can hide logic from callers related to that key exchange and other interactions. net: add V1Transport lock protecting receive state Rather than relying on the caller to prevent concurrent calls to the various receive-side functions of Transport, introduce a private m_cs_recv inside the implementation to protect the lock state. Of course, this does not remove the need for callers to synchronize calls entirely, as it is a stateful object, and e.g. the order in which Receive(), Complete(), and GetMessage() are called matters. It seems impossible to use a Transport object in a meaningful way in a multi-threaded way without some form of external synchronization, but it still feels safer to make the transport object itself responsible for protecting its internal state. refactor: rename Transport class receive functions Now that the Transport class deals with both the sending and receiving side of things, make the receive side have function names that clearly indicate they're about receiving. * Transport::Read() -> Transport::ReceivedBytes() * Transport::Complete() -> Transport::ReceivedMessageComplete() * Transport::GetMessage() -> Transport::GetReceivedMessage() * Transport::SetVersion() -> Transport::SetReceiveVersion() Further, also update the comments on these functions to (among others) remove the "deserialization" terminology. That term is better reserved for just the serialization/deserialization between objects and bytes (see serialize.h), and not the conversion from/to wire bytes as performed by the Transport. net: abstract sending side of transport serialization further This makes the sending side of P2P transports mirror the receiver side: caller provides message (consisting of type and payload) to be sent, and then asks what bytes must be sent. Once the message has been fully sent, a new message can be provided. This removes the assumption that P2P serialization of messages follows a strict structure of header (a function of type and payload), followed by (unmodified) payload, and instead lets transports decide the structure themselves. It also removes the assumption that a message must always be sent at once, or that no bytes are even sent on the wire when there is no message. This opens the door for supporting traffic shaping mechanisms in the future. net: make V1Transport implicitly use current chainparams The rest of net.cpp already uses Params() to determine chainparams in many places (and even V1Transport itself does so in some places). Since the only chainparams dependency is through the message start characters, just store those directly in the transport. fuzz: add bidirectional fragmented transport test This adds a simulation test, with two V1Transport objects, which send messages to each other, with sending and receiving fragmented into multiple pieces that may be interleaved. It primarily verifies that the sending and receiving side are compatible with each other, plus a few sanity checks. net: measure send buffer fullness based on memory usage This more accurately captures the intent of limiting send buffer size, as many small messages can have a larger overhead that is not counted with the current approach. It also means removing the dependency on the header size (which will become a function of the transport choice) from the send buffer calculations. net: move message conversion to wire bytes from PushMessage to SocketSendData This furthers transport abstraction by removing the assumption that a message can always immediately be converted to wire bytes. This assumption does not hold for the v2 transport proposed by BIP324, as no messages can be sent before the handshake completes. This is done by only keeping (complete) CSerializedNetMsg objects in vSendMsg, rather than the resulting bytes (for header and payload) that need to be sent. In SocketSendData, these objects are handed to the transport as permitted by it, and sending out the bytes the transport tells us to send. This also removes the nSendOffset member variable in CNode, as keeping track of how much has been sent is now a responsability of the transport. This is not a pure refactor, and has the following effects even for the current v1 transport: * Checksum calculation now happens in SocketSendData rather than PushMessage. For non-optimistic-send messages, that means this computation now happens in the network thread rather than the message handler thread (generally a good thing, as the message handler thread is more of a computational bottleneck). * Checksum calculation now happens while holding the cs_vSend lock. This is technically unnecessary for the v1 transport, as messages are encoded independent from one another, but is untenable for the v2 transport anyway. * Statistics updates about per-message sent bytes now happen when those bytes are actually handed to the OS, rather than at PushMessage time. refactor: make Transport::ReceivedBytes just return success/fail fuzz: coinselection, add `CreateCoins` Move coins creation for a specific function. It allows us to use it in other parts of the code. fuzz: coinselection, add coverage for `EligibleForSpending` fuzz: coinselection, add coverage for `AddInputs` fuzz: coinselection, add coverage for `GetShuffledInputVector`/`GetInputSet` fuzz: coinselection, add coverage for `Merge` fuzz: coinselection, improve `ComputeAndSetWaste` Instead of using `cost_of_change` for `min_viable_change` and `change_cost`, and 0 for `change_fee`, use values from `coin_params`. The previous values don't generate any effects that is relevant for that context. fuzz: coinselection, compare `GetSelectedValue` with target The valid results should have a target below the sum of the selected inputs amounts. Also, it increases the minimum value for target to make it more realistic. fuzz: coinselection, BnB should never produce change fuzz: coinselection, fix `m_cost_of_change` `m_cost_of_change` must not be generated randomly independent from m_change_fee. This commit changes it to set it up according to `wallet/spend`. doc: Improve documentation of rpcallowip rpchelp Closes #21070 v21.0 introduced a behaviour changed noted in #21070 where using a config value `rpcallowip=::0` no longer also permitted ipv4 ip addresses. The rpc_bind.py functional test covers this new behaviour already by checking that the list of bind addresses exactly matches what is expected so this commit only updates the documentation. rpc: add test-only sendmsgtopeer rpc This rpc can be used when we want a node to send a message, but cannot use a python P2P object, for example for testing of low-level net transport behavior. test: add basic tests for sendmsgtopeer to rpc_net.py test: add functional test for deadlock situation guix: backport glibc patch to fix powerpc build Do this prior to bumping the time-machine, to avoid the following build failure: ```bash /tmp/guix-build-glibc-cross-powerpc64le-linux-gnu-2.27.drv-0/build/string/memset-power8.o.dt -MT /tmp/guix-build-glibc-cross-powerpc64le-linux-gnu-2.27.drv-0/build/string/memset-power8.o ../sysdeps/powerpc/powerpc64/power4/memcmp.S: Assembler messages: ../sysdeps/powerpc/powerpc64/power4/memcmp.S:87: Error: unrecognized opcode: `ldbrx' ../sysdeps/powerpc/powerpc64/power4/memcmp.S:88: Error: unrecognized opcode: `ldbrx' ../sysdeps/powerpc/powerpc64/power4/memcmp.S:112: Error: unrecognized opcode: `ldbrx' ``` See: https://sourceware.org/git/?p=glibc.git;a=commit;h=9250e6610fdb0f3a6f238d2813e319a41fb7a810. https://github.com/gcc-mirror/gcc/commit/e154242724b084380e3221df7c08fcdbd8460674. guix: update python-oscrypto to 1.3.0 This is required for bumping the time-machine, for compatibility with OpenSSL: oscrypto: openssl backend, 1.2.1, /tmp/guix-build-python-oscrypto-1.2.1.drv-0/source/oscrypto Traceback (most recent call last): File "/tmp/guix-build-python-oscrypto-1.2.1.drv-0/source/oscrypto/_openssl/_libcrypto_ctypes.py", line 304, in <module> libcrypto.EVP_PKEY_size.argtypes = [ File "/gnu/store/9dkl9fnidcdpw19ncw5pk0p7dljx7ijb-python-3.10.7/lib/python3.10/ctypes/__init__.py", line 387, in __getattr__ func = self.__getitem__(name) File "/gnu/store/9dkl9fnidcdpw19ncw5pk0p7dljx7ijb-python-3.10.7/lib/python3.10/ctypes/__init__.py", line 392, in __getitem__ func = self._FuncPtr((name_or_ordinal, self)) AttributeError: /gnu/store/2hr7w64zhr6jjznidyc2xi40d5ynhj9c-openssl-3.0.8/lib/libcrypto.so.3: undefined symbol: EVP_PKEY_size. Did you mean: 'EVP_PKEY_free'? guix: update time-machine to 160f78a4d92205df986ed9efcce7d3aac188cb24 In our time-machine environment this changes the following: GCC 10.3.0 -> 10.4.0 Binutils 2.37 -> 2.38 Linux Libre Headers 5.15.37 -> 5.15.127 git 2.36.0 -> 2.41.0 mingw-w64 8.0.0 -> 11.0.1 NSIS 3.05 -> 3.09 xorriso 1.5.2 -> 1.5.6.pl02 Python 3.9 -> 3.10.7 Python-asn1crypto 1.4.0 -> 1.5.1 GCC 12.3.0 becomes available. LLVM 15.0.7 becomes available. guix: use cross-* keyword arguments Using the new time-machine results in warnings about consistently using keyword arguments: ```bash guix environment: warning: 'cross-kernel-headers' must be used with keyword arguments guix environment: warning: 'cross-libc' must be used with keyword arguments ``` guix: drop NSIS patch now that we use 3.09 See https://sourceforge.net/p/nsis/bugs/1283/. guix: drop Windows broken-longjmp.patch This is no-longer required, now that we are building using GCC 10.4.0. depends: use LLVM/Clang 15.0.6 for macOS cross-compile There is no x86_64 binaries for 15.0.7. guix: use clang-toolchain-15 for macOS compilation ci: Run "Win64 native" job on GitHub Actions refactor: Use HashWriter over legacy CHashWriter refactor: Use HashWriter over legacy CHashWriter (via SerializeHash) config: default acceptnonstdtxn=0 on all chains Previously, the default for acceptnonstdtxn defaulted to 0 on all chains except testnet. Change this to be consistent across all chains, and remove the parameter from chainparams entirely. doc: Release notes for testnet defaulting to -acceptnonstdtxn=0 script: replace deprecated pkg_resources with importlib.metadata in our python linter: ``` ./test/lint/lint-python.py:12: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html import pkg_resources ``` The importlib.metadata library was added in Python 3.8, which is currently our minimum-supported Python version. For more details about importlib.metadata, see https://docs.python.org/3/library/importlib.metadata.html ci, windows: Do not run extended functional tests for pull requests This change is intended to speed up the CI feedback for pull requests. test: Support powerpc64le in get_previous_releases.py guix: remove GCC 10 workaround from NSIS Fixed upstream in 3.06, see https://github.com/kichik/nsis/commit/229b6136c41ba5caba25936f4927476d20aa283f. https://sourceforge.net/p/nsis/bugs/1248/ doc: Remove sudo from command that is already run as root ci: Remove /ro_base bind mount Just set the bind mount to BASE_READ_ONLY_DIR, which allows to drop one line of code and makes the code easier to understand. ci: Remove unused TEST_RUNNER_ENV="LC_ALL=C" from s390x task gui: make '-min' minimize wallet loading dialog When '-min' is enabled, no loading dialog should be presented on screen during startup. doc: Fill in the required skills in the good_first_issue template [log] include wtxid in tx {relay,validation,orphanage} logging [log] add category TXPACKAGES for orphanage and package relay [log] add more logs related to orphan handling - Whenever a tx is erased. Allows somebody to see which transactions have been erased due to expiry/overflow, not just how many. - Whenever a tx is added to a peer's workset. - AcceptToMemoryPool when a tx is accepted, mirroring the one logged for a tx received from a peer. This allows someone to see all of the transactions that are accepted to mempool just by looking for ATMP logs. - MEMPOOLREJ when a tx is rejected, mirroring the one logged for a tx received from a peer. This allows someone to see all of the transaction rejections by looking at MEMPOOLREJ logs. [doc] move comment about AlreadyHaveTx DoS score to the right place This comment isn't in the right place, as detection of a tx in recent_rejects would cause the function to exit much earlier. Move the comment to the right place and tweak the first sentence for accuracy. ci: Avoid oversubscription in functional tests on Windows ci: Avoid saving the same Ccache cache This occurred when a job was being rerun. log: Print error message when coindb is in inconsistent state qt: Translation updates from Transifex The diff is generated by executing the `update-translations.py` script. qt: Bump Transifex slug for 26.x qt: Update translation source file The diff is generated by executing `make -C src translate`. removed StrFormatInternalBug quote delimitation ci: Bump `actions/checkout` version See: https://github.com/actions/checkout/releases/tag/v4.0.0 test: p2p: check that `getaddr` msgs are only responded once per connection test: remove fixed timeouts from feature_config_args They cannot be scaled by the timeout_factor option and can therefore cause timeouts in slow environments. They are also not necessary for the test, since they measure time frome startup until a debug message is encountered, which is not restricted to 1 minute by any internal logic within bitcoind. ci: Asan with -ftrivial-auto-var-init=pattern Squashed 'src/secp256k1/' changes from c545fdc374..199d27cea3 199d27cea3 Merge bitcoin-core/secp256k1#1415: release: Prepare for 0.4.0 16339804c9 release: Prepare for 0.4.0 d9a85065a9 changelog: Catch up in preparation of release 0b4640aedd Merge bitcoin-core/secp256k1#1413: ci: Add `release` job 8659a01714 ci: Add `release` job f9b38894ba ci: Update `actions/checkout` version 727bec5bc2 Merge bitcoin-core/secp256k1#1414: ci/gha: Add ARM64 QEMU jobs for clang and clang-snapshot 2635068abf ci/gha: Let MSan continue checking after errors in all jobs e78c7b68eb ci/Dockerfile: Reduce size of Docker image further 2f0d3bbffb ci/Dockerfile: Warn if `ulimit -n` is too high when running Docker 4b8a647ad3 ci/gha: Add ARM64 QEMU jobs for clang and clang-snapshot 6ebe7d2bb3 ci/Dockerfile: Always use versioned clang packages 65c79fe2d0 Merge bitcoin-core/secp256k1#1412: ci: Switch macOS from Ventura to Monterey and add Valgrind c223d7e33d ci: Switch macOS from Ventura to Monterey and add Valgrind ea26b71c3a Merge bitcoin-core/secp256k1#1411: ci: Make repetitive command the default one cce0456304 ci: Make repetitive command the default one 317a4c48f0 ci: Move `git config ...` to `run-in-docker-action` 4d7fe60905 Merge bitcoin-core/secp256k1#1409: ci: Move remained task from Cirrus to GitHub Actions 676ed8f9cf ci: Move "C++ (public headers)" from Cirrus to GitHub Actions 61fc3a2dc8 ci: Move "C++ -fpermissive..." from Cirrus to GitHub Actions d51fb0a533 ci: Move "MSan" from Cirrus to GitHub Actions c22ac27529 ci: Move sanitizers task from Cirrus to GitHub Actions 26a989924b Merge bitcoin-core/secp256k1#1410: ci: Use concurrency for pull requests only ee1be62d84 ci: Use concurrency for pull requests only 6ee14550c8 Merge bitcoin-core/secp256k1#1406: ci, gha: Move more non-x86_64 tasks from Cirrus CI to GitHub Actions fc3dea29ea ci: Move "ppc64le: Linux..." from Cirrus to GitHub Actions 7782dc8276 ci: Move "ARM64: Linux..." from Cirrus to GitHub Actions 0a16de671c ci: Move "ARM32: Linux..." from Cirrus to GitHub Actions ea33914e00 ci: Move "s390x (big-endian): Linux..." from Cirrus to GitHub Actions 880be8af99 ci: Move "i686: Linux (Debian stable)" from Cirrus to GiHub Actions 2e6cf9bae5 Merge bitcoin-core/secp256k1#1396: ci, gha: Add "x86_64: Linux (Debian stable)" GitHub Actions job 5373693e45 Merge bitcoin-core/secp256k1#1405: ci: Drop no longer needed workaround ef9fe959de ci: Drop no longer needed workaround e10878f58e ci, gha: Drop `driver-opts.network` input for `setup-buildx-action` 4ad4914bd1 ci, gha: Add `retry_builder` Docker image builder 6617a620d9 ci: Remove "x86_64: Linux (Debian stable)" task from Cirrus CI 03c9e6508c ci, gha: Add "x86_64: Linux (Debian stable)" GitHub Actions job ad3e65d9fe ci: Remove GCC build files and sage to reduce size of Docker image 6b9507adf6 Merge bitcoin-core/secp256k1#1398: ci, gha: Add Windows jobs based on Linux image 87d35f30c0 ci: Rename `cirrus.sh` to more general `ci.sh` d6281dd008 ci: Remove Windows tasks from Cirrus CI 2b6f9cd546 ci, gha: Add Windows jobs based on Linux image 48b1d939b5 Merge bitcoin-core/secp256k1#1403: ci, gha: Ensure only a single workflow processes `github.ref` at a time 0ba2b94551 Merge bitcoin-core/secp256k1#1373: Add invariant checking for scalars 060e32cb60 Merge bitcoin-core/secp256k1#1401: ci, gha: Run all MSVC tests on Windows natively de657c2044 Merge bitcoin-core/secp256k1#1062: Removes `_fe_equal_var`, and unwanted `_fe_normalize_weak` calls (in tests) bcffeb14bc Merge bitcoin-core/secp256k1#1404: ci: Remove "arm64: macOS Ventura" task from Cirrus CI c2f6435802 ci: Add comment about switching macOS to M1 on GHA later 4a24fae0bc ci: Remove "arm64: macOS Ventura" task from Cirrus CI b0886fd35c ci, gha: Ensure only a single workflow processes `github.ref` at a time 3d05c86d63 Merge bitcoin-core/secp256k1#1394: ci, gha: Run "x86_64: macOS Ventura" job on GitHub Actions d78bec7001 ci: Remove Windows MSVC tasks from Cirrus CI 3545dc2b9b ci, gha: Run all MSVC tests on Windows natively 5d8fa825e2 Merge bitcoin-core/secp256k1#1274: test: Silent noisy clang warnings about Valgrind code on macOS x86_64 8e54a346d2 ci, gha: Run "x86_64: macOS Ventura" job on GitHub Actions b327abfcea Merge bitcoin-core/secp256k1#1402: ci: Use Homebrew's gcc in native macOS task d62db57427 ci: Use Homebrew's gcc in native macOS task 54058d16fe field: remove `secp256k1_fe_equal_var` bb4efd6404 tests: remove unwanted `secp256k1_fe_normalize_weak` call eedd781085 Merge bitcoin-core/secp256k1#1348: tighten group magnitude limits, save normalize_weak calls in group add methods (revival of #1032) b2f6712dd3 Merge bitcoin-core/secp256k1#1400: ctimetests: Use new SECP256K1_CHECKMEM macros also for ellswift 9c91ea41b1 ci: Enable ellswift module where it's missing db32a24761 ctimetests: Use new SECP256K1_CHECKMEM macros also for ellswift ce765a5b8e Merge bitcoin-core/secp256k1#1399: ci, gha: Run "SageMath prover" job on GitHub Actions 8408dfdc4c Revert "ci: Run sage prover on CI" c8d9914fb1 ci, gha: Run "SageMath prover" job on GitHub Actions 8d2960c8e2 Merge bitcoin-core/secp256k1#1397: ci: Remove "Windows (VS 2022)" task from Cirrus CI f1774e5ec4 ci, gha: Make MSVC job presentation more explicit 5ee039bb58 ci: Remove "Windows (VS 2022)" task from Cirrus CI 96294c00fb Merge bitcoin-core/secp256k1#1389: ci: Run "Windows (VS 2022)" job on GitHub Actions a2f7ccdecc ci: Run "Windows (VS 2022)" job on GitHub Actions 374e2b54e2 Merge bitcoin-core/secp256k1#1290: cmake: Set `ENVIRONMENT` property for examples on Windows 1b13415df9 Merge bitcoin-core/secp256k1#1391: refactor: take use of `secp256k1_scalar_{zero,one}` constants (part 2) a1bd4971d6 refactor: take use of `secp256k1_scalar_{zero,one}` constants (part 2) b7c685e74a Save _normalize_weak calls in group add methods c83afa66e0 Tighten group magnitude limits 26392da2fb Merge bitcoin-core/secp256k1#1386: ci: print $ELLSWIFT in cirrus.sh d23da6d557 use secp256k1_scalar_verify checks 4692478853 ci: print $ELLSWIFT in cirrus.sh c7d0454932 add verification for scalars c734c64278 Merge bitcoin-core/secp256k1#1384: build: enable ellswift module via SECP_CONFIG_DEFINES ad152151b0 update max scalar in scalar_cmov_test and fix schnorrsig_verify exhaustive test 78ca880788 build: enable ellswift module via SECP_CONFIG_DEFINES 0e00fc7d10 Merge bitcoin-core/secp256k1#1383: util: remove unused checked_realloc b097a466c1 util: remove unused checked_realloc 2bd5f3e618 Merge bitcoin-core/secp256k1#1382: refactor: Drop unused cast 4f8c5bd761 refactor: Drop unused cast 173e8d061a Implement current magnitude assumptions 49afd2f5d8 Take use of _fe_verify_magnitude in field_impl.h 4e9661fc42 Add _fe_verify_magnitude (no-op unless VERIFY is enabled) 690b0fc05a add missing group element invariant checks 175db31149 ci: Drop no longer needed `PATH` variable update on Windows 116d2ab3df cmake: Set `ENVIRONMENT` property for examples on Windows cef373997c cmake, refactor: Use helper function instead of interface library 747ada3587 test: Silent noisy clang warnings about Valgrind code on macOS x86_64 git-subtree-dir: src/secp256k1 git-subtree-split: 199d27cea32203b224b208627533c2e813cd3b21 scripted-diff: Use blocks_path where possible -BEGIN VERIFY SCRIPT- sed -i 's|].chain_path, .blocks.|].blocks_path|g' $(git grep -l chain_path) -END VERIFY SCRIPT- index: Drop legacy -txindex check move-only: Move CBlockTreeDB to node/blockstorage The block index (CBlockTreeDB) is required to write and read blocks, so move it to blockstorage. This allows to drop the txdb.h include from `node/blockstorage.h`. Can be reviewed with: --color-moved=dimmed-zebra --color-moved-ws=ignore-all-space Fixup style of moved code Can be reviewed with --word-diff-regex=. scripted-diff: Rename CBlockTreeDB -> BlockTreeDB -BEGIN VERIFY SCRIPT- sed -i 's|CBlockTreeDB|BlockTreeDB|g' $( git grep -l CBlockTreeDB ) -END VERIFY SCRIPT- build: use -muse-unaligned-vector-move for Windows We currently work around a longstanding GCC issue with aligned vector instructions, in our release builds, by patching the behaviour we want into GCC (see discussion in #24736). A new option now exists in the binutils assembler, `-muse-unaligned-vector-move`, which should also achieve the behaviour we want (at least for our code). This was added in the 2.38 release, see https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=c8480b58e1968f209b6365af7422678f348222c2. ```bash x86: Add -muse-unaligned-vector-move to assembler Unaligned load/store instructions on aligned memory or register are as fast as aligned load/store instructions on modern Intel processors. Add a command-line option, -muse-unaligned-vector-move, to x86 assembler to encode encode aligned vector load/store instructions as unaligned vector load/store instructions. ``` Even if we introduce this option into our build system, we'll have to maintain our GCC patching, as we want all code that ends up in the binary, to avoid these instructions. However, there may be some value in adding the option, as it could be an improvement for someone building (bitcoind.exe) with an unpatched compiler. test: Combine sync_send_with_ping and sync_with_ping miniscript: make GetStackSize independent of P2WSH context It was taking into account the P2WSH script push in the number of stack elements. miniscript: introduce a helper to get the maximum witness size Similarly to how we compute the maximum stack size. Also note how it would be quite expensive to recompute it recursively by accounting for different ECDSA signature sizes. So we just assume high-R everywhere. It's only a trivial difference anyways. descriptor: introduce a method to get the satisfaction size In the wallet code, we are currently estimating the size of a signed input by doing a dry run of the signing logic. This is unnecessary as all outputs we are able to sign for can be represented by a descriptor, and we can derive the size of a satisfaction ("signature") from the descriptor itself directly. In addition, this approach does not scale: getting the size of a satisfaction through a dry run of the signing logic is only possible for the most basic scripts. This commit introduces the computation of the size of satisfaction per descriptor. It's a bit intricate for 2 main reasons: - We want to conserve the behaviour of the current dry-run logic used by the wallet that sometimes assumes ECDSA signatures will be low-r, sometimes not (when we don't create them). - We need to account for the witness discount. A single descriptor may sometimes benefit of it, sometimes not (for instance `pk()` if used as top-level versus if used inside `wsh()`). script/signingprovider: introduce a MultiSigningProvider It is sometimes useful to interface with multiple signing providers at once. For instance when inferring a descriptor with solving information being provided from multiple sources (see next commit). Instead of inneficiently copying the information from one provider into the other, introduce a new signing provider that takes a list of pointers to existing providers. wallet: use descriptor satisfaction size to estimate inputs size Instead of using the dummysigner to compute a placeholder satisfaction, infer a descriptor on the scriptPubKey of the coin being spent and use the estimation of the satisfaction size given by the descriptor directly. Note this (almost, see next paragraph) exactly conserves the previous behaviour. For instance CalculateMaximumSignedInputSize was previously assuming the input to be spent in a transaction that spends at least one Segwit coin, since it was always accounting for the serialization of the number of witness elements. In this commit we use a placeholder for the size of the serialization of the witness stack size (1 byte). Since the logic in this commit is already tricky enough to review, and that it is only a very tiny approximation not observable through the existing tests, it is addressed in the next commit. wallet: accurately account for the size of the witness stack When estimating the maximum size of an input, we were assuming the number of elements on the witness stack could be encode in a single byte. This is a valid approximation for all the descriptors we support (including P2WSH Miniscript ones), but may not hold anymore once we support Miniscript within Taproot descriptors (since the max standard witness stack size of 100 gets lifted). It's a low-hanging fruit to account for it correctly, so just do it now. fuzz: introduce and use `ConsumePrivateKey` helper doc: s/--no-substitute/--no-substitutes in guix/INSTALL Replace READWRITEAS macro with AsBase wrapping function Co-authored-by: Pieter Wuille <pieter@wuille.net> Rename CSerAction* to Action* This allows new code, added in the next commit, to conform to the coding guideline: No C-prefix for class names. Support for serialization parameters The moved part can be reviewed with the git options --ignore-all-space --color-moved=dimmed-zebra --color-moved-ws=ignore-all-space (Modified by Marco Falke) Co-authored-by: Pieter Wuille <pieter@wuille.net> Use serialization parameters for CAddress serialization This also cleans up the addrman (de)serialization code paths to only allow `Disk` serialization. Some unit tests previously forced a `Network` serialization, which does not make sense, because Bitcoin Core in production will always `Disk` serialize. This cleanup idea was suggested by Pieter Wuille and implemented by Anthony Towns. Co-authored-by: Pieter Wuille <pieter@wuille.net> Co-authored-by: Anthony Towns <aj@erisian.com.au> test: add tests that exercise WithParams() Co-authored-by: Vasil Dimov <vd@FreeBSD.org> Remove unused legacy CHashVerifier depends: libtapi 1300.0.6.5 depends: cctools 986 & ld64 711 test: remove unused variables in `p2p_invalid_block` fuzz: add ConstructPubKeyBytes function Today, this code only has one spot where it needs well-formed pubkeys, but future PRs will want to reuse this code. Add a function which creates a well-formed byte array that can be turned into a pubkey. It is not required that the pubkey is valid, just that it can be recognized as a compressed or uncompressed pubkey. Note: while the main intent of this commit is to wrap the existing logic into a function, it also switches to `PickValueFromArray` so that we are only choosing one of 0x04, 0x06, or 0x07. The previous code, `ConsumeIntegralInRange` would have also picked 0x05, which is not definied in the context of compressed vs uncompressed keys. See https://bitcoin.stackexchange.com/questions/57855/c-secp256k1-what-do-prefixes-0x06-and-0x07-in-an-uncompressed-public-key-signif for more details. net: add have_next_message argument to Transport::GetBytesToSend() Before this commit, there are only two possibly outcomes for the "more" prediction in Transport::GetBytesToSend(): * true: the transport itself has more to send, so the answer is certainly yes. * false: the transport has nothing further to send, but if vSendMsg has more message(s) left, that still will result in more wire bytes after the next SetMessageToSend(). For the BIP324 v2 transport, there will arguably be a third state: * definitely not: the transport has nothing further to send, but even if vSendMsg has more messages left, they can't be sent (right now). This happens before the handshake is complete. To implement this, we move the entire decision logic to the Transport, by adding a boolean to GetBytesToSend(), called have_next_message, which informs the transport whether more messages are available. The return values are still true and false, but they mean "definitely yes" and "definitely no", rather than "yes" and "maybe". net: remove unused Transport::SetReceiveVersion crypto: Spanify EllSwiftPubKey constructor net: add V2Transport class with subset of BIP324 functionality This introduces a V2Transport with a basic subset of BIP324 functionality: * no ability to send garbage (but receiving is supported) * no ability to send decoy packets (but receiving them is supported) * no support for short message id encoding (neither encoding or decoding) * no waiting until 12 non-V1 bytes have been received * (and thus) no detection of V1 connections on the responder side (on the sender side, detecting V1 is not supported either, but that needs to be dealt with at a higher layer, by reconnecting) net: make V2Transport auto-detect incoming V1 and fall back to it net: add short message encoding/decoding support to V2Transport net: make V2Transport send uniformly random number garbage bytes net: make V2Transport preallocate receive buffer space test: add unit tests for V2Transport net: detect wrong-network V1 talking to V2Transport Remove version/hashing options from CBlockLocator/CDiskBlockIndex refactor: Use DataStream now that version/type are unused refactor: remove clientversion include from dbwrapper.h consensus/validation.h: remove needless GetTransactionOutputWeight helper Introduced in 9b7ec393b82ca9d7ada77d06e0835df0386a8b85. This copied the format of the other Get.*Weight helpers but it's useless for a CTxOut. test: refactor: remove unnecessary blocks_checked counter Since we already store all the blocks in `events`, keeping an additional counter is redundant. test: refactor: rename inbound to is_inbound Makes it easier to recognize this variable represents a flag. test: refactor: deduplicate handle_utxocache_* logic Carve out the comparison logic into a helper function to avoid code duplication. test: store utxocache events By storing the events instead of doing the comparison inside the handle_utxocache_* functions, we simplify the overall logic and potentially making debugging easier, by allowing pdb to access the events. Mostly a refactor, but changes logging behaviour slightly by not raising and not calling self.log.exception("Assertion failed") test: log sanity check assertion failures test: refactor: remove unnecessary nonlocal Since we're only mutating, and not reassigning, we don't need to declare `events` as `nonlocal`. test: refactor: usdt_mempool: store all events Even though we expect these functions to only produce one event, we still keep a counter to check if that's true. By simply storing all the events, we can remove the counters and make debugging easier, by allowing pdb to access the events. net: merge V2Transport constructors, move key gen This removes the ability for BIP324Cipher to generate its own key, moving that responsibility to the caller (mostly, V2Transport). This allows us to write the random-key V2Transport constructor by delegating to the explicit-key one. net: do not use send buffer to store/cache garbage Before this commit the V2Transport::m_send_buffer is used to store the garbage: * During MAYBE_V1 state, it's there despite not being sent. * During AWAITING_KEY state, while it is being sent. * At the end of the AWAITING_KEY state it cannot be wiped as it's still needed to compute the garbage authentication packet. Change this by introducing a separate m_send_garbage field, taking over the first and last role listed above. This means the garbage is only in the send buffer when it's actually being sent, removing a few special cases related to this. doc: fix typos and mistakes in BIP324 code comments index: coinstats reorg, fail when block cannot be reversed During a reorg, continuing execution when a block cannot be reversed leaves the coinstats index in an inconsistent state, which was surely overlooked when 'CustomRewind' was implemented. index: add [nodiscard] attribute to functions writing to the db rpc: Deprecate rpcserialversion=0 doc: Clarify that -fstack-reuse=all bugs exist on all versions of GCC wallet rpc: return final tx hex from walletprocesspsbt if complete test: remove unnecessary finalizepsbt rpc calls doc: add release note for PR #28414 doc, refactor: Changing -torcontrol help to specify that a default port is used Right now when we get the help for -torcontrol it says that there is a default ip and port we dont specify if there is a specified ip that we would also use port 9051 as default [policy] check for duplicate txids in package Duplicates of normal transactions would be found by looking for conflicting inputs, but this doesn't catch identical empty transactions. These wouldn't be valid but exiting early is good and AcceptPackage's result sanity checks assume non-duplicate transactions. [CCoinsViewMemPool] track non-base coins and allow Reset Temporary coins should not be available in separate subpackage submissions. Any mempool coins that are cached in m_view should be removed whenever mempool contents change, as they may be spent or no longer exist. [validation] add AcceptSubPackage to delegate Accept* calls and clean up m_view (1) Call AcceptSingleTransaction when there is only 1 transaction in the subpackage. This avoids calling PackageMempoolChecks() which enforces rules that don't need to be applied for a single transaction, i.e. disabling CPFP carve out. There is a slight change in the error type returned, as shown in the txpackage_tests change. When a transaction is the last one left in the package and its fee is too low, this returns a PCKG_TX instead of PCKG_POLICY. This interface is clearer; "package-fee-too-low" for 1 transaction would be a bit misleading. (2) Clean up m_view and m_viewmempool so that coins created in this sub-package evaluation are not available for other sub-package evaluations. The contents of the mempool may change, so coins that are available now might not be later. [validation] make PackageMempoolAcceptResult members mutable After the PackageMempoolAcceptResult is returned from AcceptMultipleTransactions, leave room for results to change due to LimitMempool() eviction. [refactor] back-fill results in AcceptPackage Instead of populating the last PackageMempoolAcceptResult with stuff from results_final and individual_results_nonfinal, fill results_final and create a PackageMempoolAcceptResult using that one. A future commit will add LimitMempoolSize() which may change the status of each of these transactions from "already in mempool" or "submitted to mempool" to "no longer in mempool". We will change those transactions' results here. A future commit also gets rid of the last AcceptSubPackage outside of the loop. It makes more sense to use results_final as the place where all results end up. [validation] return correct result when already-in-mempool tx gets evicted Bug fix: a transaction may be in the mempool when package evaluation begins (so it is added to results_final with MEMPOOL_ENTRY or DIFFERENT_WITNESS), but get evicted due to another transaction submission. [validation] don't LimitMempoolSize in any subpackage submissions Don't do any mempool evictions until package validation is done, preventing the mempool minimum feerate from changing. Whether we submit transactions separately or as a package depends on whether they meet the mempool minimum feerate threshold, so it's best that the value not change while we are evaluating a package. This avoids a situation where we have a CPFP package in which the parents meet the mempool minimum feerate and are submitted by themselves, but they are evicted before we have submitted the child. [test framework] add ability to spend only confirmed utxos Useful to ensure that the topologies of packages/transactions are as expected, preventing bugs caused by having unexpected mempool ancestors. [refactor] split setup in mempool_limit test We want to be able to re-use fill_mempool so that none of the tests affect each other. Change the logs from info to debug because they are otherwise repeated many times in the test output. [test] mempool coins disappearing mid-package evaluation Test for scenario(s) outlined in PR 28251. Test what happens when a package transaction spends a mempool coin which is fetched and then disappears mid-package evaluation due to eviction or replacement. dbwrapper: Use DataStream for batch operations Remove unused GetType() from CBufferedFile and CAutoFile GetType() is only called in tests, so it is unused and can be removed. scripted-diff: Rename CBufferedFile to BufferedFile While touching all constructors in the previous commit, the class name can be adjusted to comply with the style guide. -BEGIN VERIFY SCRIPT- sed -i 's/CBufferedFile/BufferedFile/g' $( git grep -l CBufferedFile ) -END VERIFY SCRIPT- ci: Add test-each-commit task ci: Limit test-each-commit to --max-count=6 [refactor] Allow std::array<std::byte, N> in serialize.h This is already possible for C-style arrays, so allow it for C++11 std::array as well. [refactor] Define MessageStartChars as std::array kernel: Move MessageStartChars to its own file The protocol.h file contains many non-consensus related definitions and should thus not be part of the libbitcoinkernel. This commit makes protocol.h no longer a required include for users of the libbitcoinkernel. This commit is part of the libbitcoinkernel project, namely its stage 1 step 3: Decouple most non-consensus headers from libbitcoinkernel. Co-Authored-By: Cory Fields <cory-nospam-@coryfields.com> [refactor] Add missing includes for next commit [refactor] Add CChainParams member to CConnman This is done in preparation to the next commit, but has the nice effect of removing one further data structure relying on the global `Params()`. [refactor] Remove netaddress.h from kernel headers Move functions requiring the netaddress.h include out of libbitcoinkernel source files. The netaddress.h file contains many non-consensus related definitions and should thus not be part of the libbitcoinkernel. This commit makes netaddress.h no longer a required include for users of the libbitcoinkernel. This commit is part of the libbitcoinkernel project, namely its stage 1 step 3: Decouple most non-consensus headers from libbitcoinkernel. [refactor] Remove compat.h from kernel headers This commit makes compat.h no longer a required include for users of the libbitcoinkernel. Including compat.h imports a bunch of platform-specific definitions. This commit is part of the libbitcoinkernel project, namely its stage 1 step 3: Decouple most non-consensus headers from libbitcoinkernel. ci: clang-17 for fuzz and tsan [fuzz] Use afl++ shared-memory fuzzing Using shared-memory is faster than reading from stdin, see https://github.com/AFLplusplus/AFLplusplus/blob/7d2122e0596132f9344a5d0896020ebc79cd33db/instrumentation/README.persistent_mode.md Revert "Merge bitcoin/bitcoin#28279: ci: Add test-each-commit task" This reverts commit…
… flat list of chainstates Also add m_validated and m_target_block members to Chainstate class it is possible to determine chainstate properties directly from Chainstate objects and it is not neccessary for validation code make calls to ChainstateManager and decide what to do by looking at assumeutxo download state. Goal is to remove hardcoded logic handling assumeutxo snapshots from most validation code. Also to make it easy to fix locking issues like the fact that cs_main is currently held unnecessarily validating snapshots, and the fact that background chainstate is not immediately deleted when it is no longer used, wasting disk space and adding a long startup delay next time the node is restarted. This follows up on some previous discussions: bitcoin#24232 (comment) bitcoin#27746 (comment) bitcoin#28562 (comment)
… flat list of chainstates Also add m_validity and m_target_block members to Chainstate class it is possible to determine chainstate properties directly from Chainstate objects and it is not neccessary for validation code make calls to ChainstateManager and decide what to do by looking at assumeutxo download state. Goal is to remove hardcoded logic handling assumeutxo snapshots from most validation code. Also to make it easy to fix locking issues like the fact that cs_main is currently held unnecessarily validating snapshots, and the fact that background chainstate is not immediately deleted when it is no longer used, wasting disk space and adding a long startup delay next time the node is restarted. This follows up on some previous discussions: bitcoin#24232 (comment) bitcoin#27746 (comment) bitcoin#28562 (comment)
… flat list of chainstates Also add m_validity and m_target_block members to Chainstate class it is possible to determine chainstate properties directly from Chainstate objects and it is not neccessary for validation code make calls to ChainstateManager and decide what to do by looking at assumeutxo download state. Goal is to remove hardcoded logic handling assumeutxo snapshots from most validation code. Also to make it easy to fix locking issues like the fact that cs_main is currently held unnecessarily validating snapshots, and the fact that background chainstate is not immediately deleted when it is no longer used, wasting disk space and adding a long startup delay next time the node is restarted. This follows up on some previous discussions: bitcoin#24232 (comment) bitcoin#27746 (comment) bitcoin#28562 (comment)
… flat list of chainstates Also add m_validity and m_target_block members to Chainstate class it is possible to determine chainstate properties directly from Chainstate objects and it is not neccessary for validation code make calls to ChainstateManager and decide what to do by looking at assumeutxo download state. Goal is to remove hardcoded logic handling assumeutxo snapshots from most validation code. Also to make it easy to fix locking issues like the fact that cs_main is currently held unnecessarily validating snapshots, and the fact that background chainstate is not immediately deleted when it is no longer used, wasting disk space and adding a long startup delay next time the node is restarted. This follows up on some previous discussions: bitcoin#24232 (comment) bitcoin#27746 (comment) bitcoin#28562 (comment)
… flat list of chainstates Also add m_validity and m_target_block members to Chainstate class it is possible to determine chainstate properties directly from Chainstate objects and it is not neccessary for validation code make calls to ChainstateManager and decide what to do by looking at assumeutxo download state. Goal is to remove hardcoded logic handling assumeutxo snapshots from most validation code. Also to make it easy to fix locking issues like the fact that cs_main is currently held unnecessarily validating snapshots, and the fact that background chainstate is not immediately deleted when it is no longer used, wasting disk space and adding a long startup delay next time the node is restarted. This follows up on some previous discussions: bitcoin#24232 (comment) bitcoin#27746 (comment) bitcoin#28562 (comment)
… flat list of chainstates Also add m_validity and m_target_block members to Chainstate class it is possible to determine chainstate properties directly from Chainstate objects and it is not neccessary for validation code make calls to ChainstateManager and decide what to do by looking at assumeutxo download state. Goal is to remove hardcoded logic handling assumeutxo snapshots from most validation code. Also to make it easy to fix locking issues like the fact that cs_main is currently held unnecessarily validating snapshots, and the fact that background chainstate is not immediately deleted when it is no longer used, wasting disk space and adding a long startup delay next time the node is restarted. This follows up on some previous discussions: bitcoin#24232 (comment) bitcoin#27746 (comment) bitcoin#28562 (comment)
… flat list of chainstates Also add m_validity and m_target_block members to Chainstate class it is possible to determine chainstate properties directly from Chainstate objects and it is not neccessary for validation code make calls to ChainstateManager and decide what to do by looking at assumeutxo download state. Goal is to remove hardcoded logic handling assumeutxo snapshots from most validation code. Also to make it easy to fix locking issues like the fact that cs_main is currently held unnecessarily validating snapshots, and the fact that background chainstate is not immediately deleted when it is no longer used, wasting disk space and adding a long startup delay next time the node is restarted. This follows up on some previous discussions: bitcoin#24232 (comment) bitcoin#27746 (comment) bitcoin#28562 (comment)
… flat list of chainstates Also add m_validity and m_target_block members to Chainstate class it is possible to determine chainstate properties directly from Chainstate objects and it is not neccessary for validation code make calls to ChainstateManager and decide what to do by looking at assumeutxo download state. Goal is to remove hardcoded logic handling assumeutxo snapshots from most validation code. Also to make it easy to fix locking issues like the fact that cs_main is currently held unnecessarily validating snapshots, and the fact that background chainstate is not immediately deleted when it is no longer used, wasting disk space and adding a long startup delay next time the node is restarted. This follows up on some previous discussions: bitcoin#24232 (comment) bitcoin#27746 (comment) bitcoin#28562 (comment)
… flat list of chainstates Also add m_validity and m_target_block members to Chainstate class it is possible to determine chainstate properties directly from Chainstate objects and it is not neccessary for validation code make calls to ChainstateManager and decide what to do by looking at assumeutxo download state. Goal is to remove hardcoded logic handling assumeutxo snapshots from most validation code. Also to make it easy to fix locking issues like the fact that cs_main is currently held unnecessarily validating snapshots, and the fact that background chainstate is not immediately deleted when it is no longer used, wasting disk space and adding a long startup delay next time the node is restarted. This follows up on some previous discussions: bitcoin#24232 (comment) bitcoin#27746 (comment) bitcoin#28562 (comment)
This PR proposes a clean up of the relationship between block storage and the chainstate objects, by moving the decision of whether to store a block on disk to something that is not chainstate-specific. Philosophically, the decision of whether to store a block on disk is related to validation rules that do not require any UTXO state; for anti-DoS reasons we were using some chainstate-specific heuristics, and those have been reworked here to achieve the proposed separation.
This PR also fixes a bug in how a chainstate's
setBlockIndexCandidates
was being initialized; it should always have all the HAVE_DATA block index entries that have more work than the chain tip. During startup, we were not fully populatingsetBlockIndexCandidates
in some scenarios involving multiple chainstates.Further, this PR establishes a concept that whenever we have 2 chainstates, that we always know the snapshotted chain's base block and the base block's hash must be an element of our block index. Given that, we can establish a new invariant that the background validation chainstate only needs to consider blocks leading to that snapshotted block entry as potential candidates for its tip. As a followup I would imagine that when writing net_processing logic to download blocks for the background chainstate, that we would use this concept to only download blocks towards the snapshotted entry as well.