Skip to content
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

Merged

Conversation

sdaftuar
Copy link
Member

@sdaftuar sdaftuar commented May 24, 2023

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 populating setBlockIndexCandidates 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.

@jamesob
Copy link
Member

jamesob commented May 24, 2023

Great! Thanks for this. I'm active in these neighborhoods today as well, since adding some -stopatheight/restart logic to the functional tests in #27596 has turned up some issues with CheckBlockIndex(), which are maybe related to some of the changes here. So I'll be looking at this shortly.

@sdaftuar sdaftuar force-pushed the 2023-05-assumeutxo-validation-improvements branch from beb5334 to 379467a Compare May 24, 2023 21:55
@DrahtBot
Copy link
Contributor

DrahtBot commented May 25, 2023

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Reviews

See the guideline for information on the review process.

Type Reviewers
ACK achow101, jamesob, Sjors, ryanofsky
Concept ACK dergoegge
Stale ACK fjahr, mzumsande

If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #28052 (blockstorage: XOR blocksdir *.dat files by MarcoFalke)
  • #27866 (blockstorage: Return on fatal flush errors by TheCharlatan)
  • #27460 (rpc: Add importmempool RPC by MarcoFalke)

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.

@Sjors
Copy link
Member

Sjors commented May 31, 2023

The first two commits up to f50fa24 look good to me.

How do you see the division of labor between ChainstateManager and BlockManager? The ChainState doc currently says:

Anything that is contingent on the current tip of the chain is stored here, whereas block information and metadata independent of the current tip is kept in BlockManager.

In any case moving AcceptBlock from Chainstate to ChainstateManager seems an improvement.

Copy link
Member

@Sjors Sjors left a 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.h Show resolved Hide resolved
src/validation.cpp Outdated Show resolved Hide resolved
// 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
Copy link
Member

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?

Copy link
Member Author

@sdaftuar sdaftuar Jun 13, 2023

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.

Copy link
Contributor

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.

Copy link
Member Author

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.

src/validation.cpp Outdated Show resolved Hide resolved
src/validation.cpp Show resolved Hide resolved
@sdaftuar
Copy link
Member Author

sdaftuar commented Jun 5, 2023

How do you see the division of labor between ChainstateManager and BlockManager? The ChainState doc currently says:

Anything that is contingent on the current tip of the chain is stored here, whereas block information and metadata independent of the current tip is kept in BlockManager.

I think of BlockManager as being a generic backend database of block (and undo) data, while any validation-related logic should live in Chainstate (if it relies on chainstate-specific information) or somewhere else (either a static function in validation or in ChainstateManager as I propose here) if not.

I think AcceptBlock could also be a static function in validation.cpp; I mostly just wanted to get it out of Chainstate because I think that having block storage be coupled to a particular chainstate is a confusing idea, but I can go either way on whether it belongs in ChainstateManager or not.

@sdaftuar
Copy link
Member Author

@Sjors @achow101 Thanks for the review! I split up the big commit as @Sjors suggested, and with the test fixes I think this is ready to be moved out of Draft status.

@sdaftuar sdaftuar marked this pull request as ready for review June 13, 2023 17:54
@sdaftuar sdaftuar force-pushed the 2023-05-assumeutxo-validation-improvements branch from bccd618 to 48de8dc Compare June 13, 2023 17:59
@sdaftuar sdaftuar changed the title Draft: rework validation logic for assumeutxo Rework validation logic for assumeutxo Jun 13, 2023
@sdaftuar sdaftuar force-pushed the 2023-05-assumeutxo-validation-improvements branch from 48de8dc to 89e8826 Compare June 14, 2023 15:15
Copy link
Contributor

@mzumsande mzumsande left a 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.h Outdated Show resolved Hide resolved
// 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;
Copy link
Contributor

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?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, good idea.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

55e27ee

If you retouch, I think you can simply say bool is_bg_chainstate = this != &ActiveChainstate();

Copy link
Member Author

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!

src/validation.cpp Outdated Show resolved Hide resolved
@sdaftuar sdaftuar force-pushed the 2023-05-assumeutxo-validation-improvements branch from 89e8826 to f02125f Compare June 15, 2023 18:22
Copy link
Member

@achow101 achow101 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK f02125f

src/validation.cpp Outdated Show resolved Hide resolved
Copy link
Contributor

@ryanofsky ryanofsky left a 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.

src/node/blockstorage.h Outdated Show resolved Hide resolved
src/validation.cpp Outdated Show resolved Hide resolved
@@ -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()));
Copy link
Contributor

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.cpp Show resolved Hide resolved
src/validation.cpp Show resolved Hide resolved
src/validation.cpp Outdated Show resolved Hide resolved
src/validation.cpp Outdated Show resolved Hide resolved
src/validation.cpp Show resolved Hide resolved
src/validation.h Outdated
void UpdateSnapshotBaseEntry(const CBlockIndex *entry) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
{ m_snapshot_entry = entry; }

//! Track the snapshot entry
Copy link
Contributor

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.

Copy link
Member

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.

Copy link
Member Author

@sdaftuar sdaftuar Jun 17, 2023

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 in net_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!

Copy link
Contributor

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;
 }
 

// 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
Copy link
Contributor

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.

Copy link
Member

@Sjors Sjors left a 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
Copy link
Member

@Sjors Sjors Jul 29, 2023

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.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re: #27746 (comment)

GetSnapshotBaseBlock() is nullptr 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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

768690b

//!
//! - 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);
Copy link
Member

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.

Copy link
Contributor

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.

Copy link
Member

@Sjors Sjors left a 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.

My comments above can all wait for a followup, if any.

I'd like to take this for a spin in a rebased #27596 with -checkblockindex to see if we didn't miss anything (without pruning, since that has a clear TODO).

@@ -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);
Copy link
Member

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)
Copy link
Member

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.

@ryanofsky
Copy link
Contributor

re: #27746 (review)

(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?)

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 m_blocks_unlinked (which used to be mapBlocksUnlinked) is:

Multimap containing "all pairs A->B, where A (or one if its ancestors) misses transactions, but B has transactions." (comment at main.cpp:125).

The purpose of mapBlocksUnlinked is to quickly attach blocks we've already received to the blockchain when we receive a missing, intermediate block.

The alternative would be to search the entire mapBlockIndex; however, it is more efficient to keep track of unlinked blocks in a separate data structure.

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.

Copy link
Contributor

@ryanofsky ryanofsky left a 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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re: #27746 (comment)

GetSnapshotBaseBlock() is nullptr 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);
Copy link
Contributor

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);
Copy link
Contributor

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.
Copy link
Contributor

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,
Copy link
Contributor

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 alternatively ASSUMED_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.

@ryanofsky ryanofsky merged commit f4f1d6d into bitcoin:master Jul 31, 2023
15 checks passed
@TheCharlatan
Copy link
Contributor

Post-merge ACK a733dd7

Very happy with the separation of concerns between blockstorage and validation.

@fjahr
Copy link
Contributor

fjahr commented Aug 1, 2023

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.

ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Aug 4, 2023
…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.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Aug 4, 2023
…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.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Aug 8, 2023
…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.
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Aug 9, 2023
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Aug 18, 2023
…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.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Aug 18, 2023
…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.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Aug 18, 2023
…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.
fanquake added a commit to bitcoin-core/gui that referenced this pull request Aug 21, 2023
…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
janus pushed a commit to BitgesellOfficial/bitgesell that referenced this pull request Sep 11, 2023
…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() ||
Copy link
Contributor

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:

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:

m_chain.SetTip(*pindex);

so the m_chain.Contains(pindexTest) check before the assert will be false and the assert will not run:

bitcoin/src/validation.cpp

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.

Copy link
Member

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 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.

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.

Copy link
Contributor

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:

bitcoin/src/validation.cpp

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?

Copy link
Member

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.

Copy link
Member

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.

Copy link
Contributor

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?

Copy link
Member

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().

Copy link
Member

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.

Retropex pushed a commit to Retropex/bitcoin that referenced this pull request Oct 4, 2023
…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.
Retropex added a commit to Retropex/bitcoin that referenced this pull request Oct 4, 2023
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…
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Oct 6, 2023
… 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)
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Oct 10, 2023
… 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)
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Oct 11, 2023
… 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)
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Oct 12, 2023
… 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)
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Oct 12, 2023
… 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)
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Oct 12, 2023
… 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)
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Oct 12, 2023
… 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)
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Feb 23, 2024
… 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)
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Feb 23, 2024
… 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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet