[Bundle 3/n] Prune remaining g_chainman usage in validation functions #21055

pull dongcarl wants to merge 16 commits into bitcoin:master from dongcarl:2020-09-reduce-validation-ccsactiveglobal-usage changing 9 files +101 −125
  1. dongcarl commented at 5:09 pm on February 1, 2021: member

    Overall PR: #20158 (tree-wide: De-globalize ChainstateManager)

    Based on:

    • #20750 | [Bundle 2/n] Prune g_chainman usage in mempool-related validation functions

    Note to reviewers:

    1. This bundle may apparently introduce usage of g_chainman or ::Chain(state|)Active() globals, but these are resolved later on in the overall PR. Commits of overall PR
    2. There may be seemingly obvious local references to ChainstateManager or other validation objects which are not being used in callers of the current function in question, this is done intentionally to keep each commit centered around one function/method to ease review and to make the overall change systematic. We don’t assume anything about our callers. Rest assured that once we are considering that particular caller in later commits, we will use the obvious local references. Commits of overall PR
    3. When changing a function/method that has many callers (e.g. LookupBlockIndex with 55 callers), it is sometimes easier (and less error-prone) to use a scripted-diff. When doing so, there will be 3 commits in sequence so that every commit compiles like so:
      1. Add new_function, make old_function a wrapper of new_function, divert all calls to old_function to new_function in the local module only
      2. Scripted-diff to divert all calls to old_function to new_function in the rest of the codebase
      3. Remove old_function

    Note to self:

  2. DrahtBot added the label Consensus on Feb 1, 2021
  3. DrahtBot added the label Mempool on Feb 1, 2021
  4. DrahtBot added the label P2P on Feb 1, 2021
  5. DrahtBot added the label RPC/REST/ZMQ on Feb 1, 2021
  6. DrahtBot added the label Validation on Feb 1, 2021
  7. DrahtBot commented at 11:42 pm on February 1, 2021: member

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

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #21270 ([Bundle 4/n] Prune g_chainman usage in validation-adjacent modules by dongcarl)
    • #21090 (Default to NODE_WITNESS in nLocalServices by dhruv)
    • #21009 (Remove RewindBlockIndex logic by dhruv)
    • #20833 (rpc/validation: enable packages through testmempoolaccept by glozow)
    • #20331 (allow -loadblock blocks to be unsorted by LarryRuane)
    • #19573 (Replace unused BIP 9 logic with draft BIP 8 by luke-jr)
    • #19438 (Introduce deploymentstatus by ajtowns)

    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.

  8. dongcarl force-pushed on Feb 2, 2021
  9. in src/validation.cpp:4146 in fa730f7a87 outdated
    4111@@ -4112,11 +4112,12 @@ void BlockManager::Unload() {
    4112     m_block_index.clear();
    4113 }
    4114 
    4115-bool static LoadBlockIndexDB(ChainstateManager& chainman, const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
    4116+bool CChainState::LoadBlockIndexDB(const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
    


    ryanofsky commented at 9:19 pm on February 2, 2021:

    In commit “validation: Move LoadBlockIndexDB to CChainState” (fa730f7a871c49072e2e899cefbc8275e5f67057)

    It seems chainman variable wasn’t really needed here, just the chainman.m_blockman member, so this might make more sense as a BlockManager method instead of CChainState method


    dongcarl commented at 8:19 pm on February 18, 2021:
    Unfortunately we need setBlockIndexCandidates which is a member off CChainState… If you think LoadBlockIndexDB makes more sense logically as a method of BlockManager rather than CChainState we can pass in the setBlockIndexCandidates. Let me know!

    ryanofsky commented at 6:26 pm on March 5, 2021:

    re: #21055 (review)

    Unfortunately we need setBlockIndexCandidates which is a member off CChainState… If you think LoadBlockIndexDB makes more sense logically as a method of BlockManager rather than CChainState we can pass in the setBlockIndexCandidates. Let me know!

    Thanks, I didn’t recognize the setBlockIndexCandidates access. Proposed change sounds reasonable, but I don’t actually know too much about it and it would seem good to tackle as a followup not changing here.

  10. in src/net_processing.cpp:3271 in a765747415 outdated
    3202@@ -3201,7 +3203,10 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
    3203         std::list<CTransactionRef> lRemovedTxn;
    3204 
    3205         if (AcceptToMemoryPool(::ChainstateActive(), m_mempool, state, ptx, &lRemovedTxn, false /* bypass_limits */)) {
    3206-            m_mempool.check(&::ChainstateActive().CoinsTip());
    3207+            CChainState& active_chainstate = m_chainman.ActiveChainstate();
    3208+            CCoinsViewCache& active_coins_tip = active_chainstate.CoinsTip();
    3209+            m_mempool.check(&active_coins_tip, active_chainstate.m_blockman.GetSpendHeight(active_coins_tip));
    


    ryanofsky commented at 9:50 pm on February 2, 2021:

    In commit “validation: Pass in spendheight to CTxMemPool::check” (a765747415aebd432d5feffb6cb609be62e2592b)

    I think it would be nice to delete the BlockManager::GetSpendHeight method entirely instead of adding new calls to it. It’s basically a one-line function returning height of active_coins_tip + 1, and it would seem more straightforward to pass active_coins_tip and active_coins_tip height together as arguments to the mempool check method (assuming the check method can’t access the height directly) instead of the tip and an offset height.


    dongcarl commented at 8:33 pm on February 18, 2021:
    Not entirely sure what you mean here by an “offset height”… Looking at all the uses of spendheight in CTxMemPool::check it seems that this “offset height” is exactly what CheckInputsAndUpdateCoins wants?

    jnewbery commented at 3:37 pm on February 28, 2021:

    I agree with @ryanofsky that the use of BlockManager::GetSpendHeight() is quite ugly. We can get the height directly from ::ChainstateActive().m_chain.Height() + 1.

    I also think it’d be preferable to not have net_processing reach inside validation for the various active chainstate fields, just to call a check() function (which defaults to a no-op with default -mempoolcheck). Could we perhaps move this call to CTxMemPool.check() into AcceptToMemoryPool(), so that it’s done consistently for all callers, and net_processing doesn’t need to concern itself with validation internals?


    dongcarl commented at 11:03 pm on March 1, 2021:

    I’m not sure I can easily convince myself that moving this check into ATMP is completely safe. However, I do see how this is ugly.

    Do you think the following patch would be an acceptable solution?

     0diff --git a/src/net_processing.cpp b/src/net_processing.cpp
     1index 614a3e0791..022f2e0574 100644
     2--- a/src/net_processing.cpp
     3+++ b/src/net_processing.cpp
     4@@ -2301,10 +2301,7 @@ void PeerManagerImpl::ProcessOrphanTx(std::set<uint256>& orphan_work_set)
     5             break;
     6         }
     7     }
     8-    CChainState& active_chainstate = m_chainman.ActiveChainstate();
     9-    CCoinsViewCache& active_coins_tip = active_chainstate.CoinsTip();
    10-    assert(std::addressof(::ChainstateActive().CoinsTip()) == std::addressof(active_coins_tip));
    11-    m_mempool.check(&active_coins_tip, active_chainstate.m_blockman.GetSpendHeight(active_coins_tip));
    12+    m_mempool.check(m_chainman.ActiveChainstate());
    13 }
    14 
    15 /**
    16@@ -3265,10 +3262,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
    17         const TxValidationState& state = result.m_state;
    18 
    19         if (result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
    20-            CChainState& active_chainstate = m_chainman.ActiveChainstate();
    21-            CCoinsViewCache& active_coins_tip = active_chainstate.CoinsTip();
    22-            assert(std::addressof(::ChainstateActive().CoinsTip()) == std::addressof(active_coins_tip));
    23-            m_mempool.check(&active_coins_tip, active_chainstate.m_blockman.GetSpendHeight(active_coins_tip));
    24+            m_mempool.check(m_chainman.ActiveChainstate());
    25 
    26             // As this version of the transaction was acceptable, we can forget about any
    27             // requests for it.
    28diff --git a/src/txmempool.cpp b/src/txmempool.cpp
    29index 4df7017c47..05902a55c3 100644
    30--- a/src/txmempool.cpp
    31+++ b/src/txmempool.cpp
    32@@ -619,7 +619,7 @@ static void CheckInputsAndUpdateCoins(const CTransaction& tx, CCoinsViewCache& m
    33     UpdateCoins(tx, mempoolDuplicate, std::numeric_limits<int>::max());
    34 }
    35 
    36-void CTxMemPool::check(const CCoinsViewCache *pcoins, const int64_t spendheight) const
    37+void CTxMemPool::check(CChainState& active_chainstate) const
    38 {
    39     if (m_check_ratio == 0) return;
    40 
    41@@ -633,7 +633,10 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins, const int64_t spendheight)
    42     CAmount check_total_fee{0};
    43     uint64_t innerUsage = 0;
    44 
    45-    CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(pcoins));
    46+    CCoinsViewCache& active_coins_tip = active_chainstate.CoinsTip();
    47+    assert(std::addressof(::ChainstateActive().CoinsTip()) == std::addressof(active_coins_tip)); // TODO: REVIEW-ONLY, REMOVE IN FUTURE COMMIT
    48+    CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(&active_coins_tip));
    49+    const int64_t spendheight = active_chainstate.m_chain.Height() + 1;
    50     assert(g_chainman.m_blockman.GetSpendHeight(mempoolDuplicate) == spendheight); // TODO: REVIEW-ONLY, REMOVE IN FUTURE COMMIT
    51 
    52     std::list<const CTxMemPoolEntry*> waitingOnDependants;
    53@@ -655,7 +658,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins, const int64_t spendheight)
    54                 fDependsWait = true;
    55                 setParentCheck.insert(*it2);
    56             } else {
    57-                assert(pcoins->HaveCoin(txin.prevout));
    58+                assert(active_coins_tip.HaveCoin(txin.prevout));
    59             }
    60             // Check whether its inputs are marked in mapNextTx.
    61             auto it3 = mapNextTx.find(txin.prevout);
    62diff --git a/src/txmempool.h b/src/txmempool.h
    63index dd82d61fc6..001d856e43 100644
    64--- a/src/txmempool.h
    65+++ b/src/txmempool.h
    66@@ -604,7 +604,7 @@ public:
    67      * all inputs are in the mapNextTx array). If sanity-checking is turned off,
    68      * check does nothing.
    69      */
    70-    void check(const CCoinsViewCache *pcoins, const int64_t spendheight) const EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
    71+    void check(CChainState& active_chainstate) const EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
    72 
    73     // addUnchecked must updated state for all ancestors of a given transaction,
    74     // to track size/count of descendant transactions.  First version of
    75diff --git a/src/validation.cpp b/src/validation.cpp
    76index 325edc5b6a..ac79dce52e 100644
    77--- a/src/validation.cpp
    78+++ b/src/validation.cpp
    79@@ -2801,8 +2801,7 @@ bool CChainState::ActivateBestChainStep(BlockValidationState& state, const CChai
    80         UpdateMempoolForReorg(*this, m_mempool, disconnectpool, true);
    81     }
    82 
    83-    CCoinsViewCache& active_coins_tip = CoinsTip();
    84-    m_mempool.check(&active_coins_tip, m_blockman.GetSpendHeight(active_coins_tip));
    85+    m_mempool.check(*this);
    86 
    87     CheckForkWarningConditions();
    88 
    

    jnewbery commented at 12:59 pm on March 2, 2021:

    I’m not sure I can easily convince myself that moving this check into ATMP is completely safe.

    I think you’re right to be wary. The call to ATMP from UpdateMempoolForReorg probably can’t call check().

    I like your proposed change.


    dongcarl commented at 7:59 pm on March 3, 2021:
    Fixed in 4744efc9ba
  11. ryanofsky approved
  12. ryanofsky commented at 9:52 pm on February 2, 2021: member
    Code review ACK f5ee2f37742da70d1731508e647dccd9b6035a7c
  13. in src/validation.cpp:5014 in a756ecb7bc outdated
    4972@@ -4973,24 +4973,6 @@ CBlockFileInfo* GetBlockFileInfo(size_t n)
    4973     return &vinfoBlockFile.at(n);
    4974 }
    4975 
    4976-ThresholdState VersionBitsTipState(const Consensus::Params& params, Consensus::DeploymentPos pos)
    4977-{
    4978-    LOCK(cs_main);
    


    ariard commented at 1:06 pm on February 8, 2021:

    This global was introduced by d23f6c6. At that commit, the globalVersionBitsTipState’s unique callerBIP9SoftForkDesc didn’t require cs_main locking.

    Those methods were refactored by 3862e47, where the new BIP9SoftForkDescPushBack did require the lock. I think since then this lock has been useless and could have been substituted by an annotation.

    So not a concern to get rid of them.

  14. in src/net_processing.cpp:2307 in a765747415 outdated
    2242@@ -2243,7 +2243,9 @@ void PeerManagerImpl::ProcessOrphanTx(std::set<uint256>& orphan_work_set)
    2243             break;
    2244         }
    2245     }
    2246-    m_mempool.check(&::ChainstateActive().CoinsTip());
    2247+    CChainState& active_chainstate = m_chainman.ActiveChainstate();
    2248+    CCoinsViewCache& active_coins_tip = active_chainstate.CoinsTip();
    2249+    m_mempool.check(&active_coins_tip, active_chainstate.m_blockman.GetSpendHeight(active_coins_tip));
    


    ariard commented at 1:29 pm on February 8, 2021:
    Shouldn’t an assert be added here and before the following invocations ? The CCoinsViewCache pointer is used throughout `CTxMemPool::check.

    dongcarl commented at 8:49 pm on February 18, 2021:
    Fixed in: 52c29d9aedcf8d141b75a6d923a5d5bea53f4079
  15. ariard commented at 1:30 pm on February 8, 2021: member
    See about the maybe missing assert otherwise code review ACK f5ee2f3
  16. DrahtBot added the label Needs rebase on Feb 11, 2021
  17. dongcarl force-pushed on Feb 18, 2021
  18. dongcarl commented at 8:09 pm on February 18, 2021: member

    Pushed f5ee2f37742da70d1731508e647dccd9b6035a7c -> eb8f8e42dcca3448ceddb2d774342a524475dd6e

    • Rebased on master

    Note: Have not yet addressed review.

  19. DrahtBot removed the label Needs rebase on Feb 18, 2021
  20. dongcarl force-pushed on Feb 18, 2021
  21. dongcarl commented at 8:48 pm on February 18, 2021: member

    Pushed eb8f8e42dcca3448ceddb2d774342a524475dd6e -> 914e9d321608b909f7f8f0442fa64cb425fcd955

  22. jnewbery commented at 10:47 am on February 20, 2021: member
    Concept ACK. This may need rebase now that #20750 is merged.
  23. MarcoFalke removed the label Consensus on Feb 20, 2021
  24. MarcoFalke removed the label Mempool on Feb 20, 2021
  25. MarcoFalke removed the label P2P on Feb 20, 2021
  26. MarcoFalke removed the label RPC/REST/ZMQ on Feb 20, 2021
  27. MarcoFalke added the label Refactoring on Feb 20, 2021
  28. dongcarl commented at 4:16 pm on February 22, 2021: member

    @MarcoFalke w/re #20750 (review), it seems like making the change would require changing all callers as well (sorta out of scope for this PR), how about we just do the following for now to ensure that the theoretical UB won’t happen?

     0diff --git a/src/validation.cpp b/src/validation.cpp
     1index a66c3d09e3..2bd7046e0f 100644
     2--- a/src/validation.cpp
     3+++ b/src/validation.cpp
     4@@ -211,6 +211,7 @@ static FlatFileSeq UndoFileSeq();
     5 bool CheckFinalTx(const CBlockIndex* active_chain_tip, const CTransaction &tx, int flags)
     6 {
     7     AssertLockHeld(cs_main);
     8+    assert(active_chain_tip); // TODO: Make active_chain_tip a reference
     9     assert(std::addressof(*::ChainActive().Tip()) == std::addressof(*active_chain_tip));
    10 
    11     // By convention a negative value for flags indicates that the
    
  29. dongcarl force-pushed on Feb 22, 2021
  30. dongcarl commented at 4:17 pm on February 22, 2021: member

    Pushed 914e9d321608b909f7f8f0442fa64cb425fcd9551e0d2d83f6ba8761eee4d2b97828e18204804dc3

    • Rebased on master
  31. validation: Check chain tip is non-null in CheckFinalTx
    ...also update comments to remove mention of ::ChainActive()
    
    From: https://github.com/bitcoin/bitcoin/pull/20750#discussion_r579400663
    
    > Also, what about passing a const reference instead of a pointer? I
    > know this is only theoretical, but previously if the tip was nullptr,
    > then Height() evaluated to -1, now it evaluates to UB
    9da106be4d
  32. validation: Remove global ::LoadGenesisBlock 4927c9e699
  33. validation: Remove global ::{{Precious,Invalidate}Block,ResetBlockFailureFlags} a3ba08ba7d
  34. dongcarl force-pushed on Feb 22, 2021
  35. dongcarl commented at 5:20 pm on February 22, 2021: member

    Pushed 1e0d2d83f6ba8761eee4d2b97828e18204804dc30bd83b71afd7cd60bca6870ce9428b9fe5bc120e

    • Prepended commit 9da106be4db692fa5db7b4de79f9cf7bfef37075 to address #20750 (review)
  36. in src/validation.cpp:2454 in 0bd83b71af outdated
    2448@@ -2445,7 +2449,9 @@ static void UpdateTip(CTxMemPool& mempool, const CBlockIndex* pindexNew, const C
    2449     }
    2450 
    2451     bilingual_str warning_messages;
    2452-    if (!::ChainstateActive().IsInitialBlockDownload()) {
    2453+    assert(std::addressof(::ChainstateActive()) == std::addressof(active_chainstate));
    2454+    if (!active_chainstate.IsInitialBlockDownload())
    2455+    {
    


    jnewbery commented at 2:18 pm on February 28, 2021:
    Don’t split { into a new line.

    dongcarl commented at 11:00 pm on March 1, 2021:
    Fixed in 4bada76237
  37. in src/validation.cpp:4246 in 0bd83b71af outdated
    4245@@ -4242,15 +4246,16 @@ CVerifyDB::~CVerifyDB()
    4246     uiInterface.ShowProgress("", 100, false);
    4247 }
    4248 
    4249-bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, int nCheckLevel, int nCheckDepth)
    4250+bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CChainState& active_chainstate, CCoinsView *coinsview, int nCheckLevel, int nCheckDepth)
    


    jnewbery commented at 2:33 pm on February 28, 2021:

    Perhaps change this function to be annotated with EXCLUSIVE_LOCKS_REQUIRED(cs_main) and assert that cs_main is held, rather than locking cs_main in the first line of the function.

    This function is always called with cs_main held. Without that guarantee, there’s the possibility that one thread calls it with ::ChainstateActive(), another thread updates the active chainstate, and then this thread asserts on the std::addressof check.


    dongcarl commented at 11:01 pm on March 1, 2021:
    Fixed in ef83bb8550

    jnewbery commented at 12:47 pm on March 2, 2021:
    Perhaps also add AssertLockHeld(cs_main) to the top of the function body?

    dongcarl commented at 7:58 pm on March 3, 2021:
    Fixed in e11b649650
  38. in src/validation.h:777 in 0bd83b71af outdated
    781- * May not be called in a
    782- * validationinterface callback.
    783- */
    784-bool PreciousBlock(BlockValidationState& state, const CChainParams& params, CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main);
    785+    void CheckForkWarningConditions() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
    786+    void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
    


    jnewbery commented at 2:36 pm on February 28, 2021:
    This function no longer exists. Remove the declaration.

    dongcarl commented at 11:01 pm on March 1, 2021:
    Fixed in: 8b99efbcc0
  39. in src/validation.cpp:4146 in 0bd83b71af outdated
    4142@@ -4140,11 +4143,12 @@ void BlockManager::Unload() {
    4143     m_block_index.clear();
    4144 }
    4145 
    4146-bool static LoadBlockIndexDB(ChainstateManager& chainman, const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
    4147+bool CChainState::LoadBlockIndexDB(const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
    


    jnewbery commented at 2:42 pm on February 28, 2021:
    Remove EXCLUSIVE_LOCKS_REQUIRED(cs_main) (which is now on the declaration in validation.h)

    dongcarl commented at 11:01 pm on March 1, 2021:
    Fixed in 8cdb2f7e58
  40. validation: Pass in chainstate to UpdateTip 4bada76237
  41. validation: Pass in chainstate to ::PruneBlockFilesManual 63e4c7316a
  42. validation: Remove global ::VersionBitsTip{State,SinceHeight,Statistics}
    Tip: versionbitscache is currently a global so we didn't need to pass it
         in to any of ::VersionBitsTip*'s callers
    31eac50c72
  43. validation: Pass in chainstate to CVerifyDB::VerifyDB 2bdf37fe18
  44. validation: Move invalid block handling to CChainState
    - InvalidChainFound
    - CheckForkWarningConditions
    8b99efbcc0
  45. validation: Move LoadBlockIndexDB to CChainState
    CChainState needed cuz setBlockIndexCandidates
    8cdb2f7e58
  46. validation: Use *this in CChainState::InvalidateBlock 1fb7b2c595
  47. dongcarl force-pushed on Mar 1, 2021
  48. dongcarl commented at 10:59 pm on March 1, 2021: member

    Pushed 0bd83b71afd7cd60bca6870ce9428b9fe5bc120e -> ef83bb85507ad9e4e6801aa2197f195e9e42a948

    • Addressed some of jnewbery’s review comments
  49. jnewbery commented at 12:59 pm on March 2, 2021: member
    Changes look good, @dongcarl! I’ve left a couple more comments.
  50. validation: Pass in chainstate to CTxMemPool::check
    This is the only instance where validation reaches for something outside
    of it.
    4744efc9ba
  51. validation: Use *this in CChainState::ActivateBestChainStep a9d28bcd8d
  52. validation: Pass in chain to FindBlockPos+SaveBlockToDisk fee73347c0
  53. validation: Use existing chain member in CChainState::AcceptBlock 5e4af77380
  54. validation: Use existing chain member in CChainState::LoadGenesisBlock 03f75c42e1
  55. validation: CVerifyDB::VerifyDB: Use locking annotation
    ...instead of recursively locking unconditionally
    e11b649650
  56. dongcarl force-pushed on Mar 3, 2021
  57. dongcarl commented at 7:58 pm on March 3, 2021: member

    Pushed ef83bb85507ad9e4e6801aa2197f195e9e42a948 -> e11b6496506246882df450586acf735dabedf731

    Thanks jnewbery for your diligent review!

  58. laanwj commented at 1:50 pm on March 4, 2021: member
    Code review ACK e11b6496506246882df450586acf735dabedf731
  59. laanwj merged this on Mar 4, 2021
  60. laanwj closed this on Mar 4, 2021

  61. sidhujag referenced this in commit 5a7dfaa148 on Mar 4, 2021
  62. ryanofsky commented at 3:06 pm on March 6, 2021: member
    Code review ACK e11b6496506246882df450586acf735dabedf731. Changes since last review: rebase, two new commits adding null assert and lock assert, replacing mempool check coins and spendheight arguments
  63. laanwj referenced this in commit 767bb7d5c5 on Mar 11, 2021
  64. Fabcien referenced this in commit 184be66e5c on Mar 17, 2022
  65. Fabcien referenced this in commit 2e4442d716 on Mar 17, 2022
  66. Fabcien referenced this in commit e671f04660 on Mar 17, 2022
  67. deadalnix referenced this in commit 1102c286aa on Mar 17, 2022
  68. deadalnix referenced this in commit d86cfa5288 on Mar 17, 2022
  69. deadalnix referenced this in commit 7176fb75a4 on Mar 17, 2022
  70. Fabcien referenced this in commit 6a8d50e7f9 on Mar 18, 2022
  71. Fabcien referenced this in commit 6a1163b5f2 on Mar 18, 2022
  72. Fabcien referenced this in commit 4a60f3fed4 on Mar 18, 2022
  73. Fabcien referenced this in commit b2b8bc2789 on Mar 18, 2022
  74. Fabcien referenced this in commit 24fb6667ed on Mar 18, 2022
  75. Fabcien referenced this in commit 915290d4f1 on Mar 18, 2022
  76. Fabcien referenced this in commit 68365eea34 on Mar 18, 2022
  77. Fabcien referenced this in commit 00f28a0a45 on Mar 21, 2022
  78. MarcoFalke referenced this in commit 27724c23f7 on Aug 12, 2022
  79. sidhujag referenced this in commit d01f1834e0 on Aug 12, 2022
  80. DrahtBot locked this on Aug 16, 2022

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-12-18 21:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me