diff --git a/src/avalanche/processor.h b/src/avalanche/processor.h --- a/src/avalanche/processor.h +++ b/src/avalanche/processor.h @@ -294,26 +294,33 @@ CTxMemPool *mempoolIn, CScheduler &scheduler, bilingual_str &error); - bool addToReconcile(const AnyVoteItem &item); + bool addToReconcile(const AnyVoteItem &item) + EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager, !cs_finalizedItems); /** * Wrapper around the addToReconcile for proofs that adds back the * finalization flag to the peer if it is not polled due to being recently * finalized. */ - bool reconcileOrFinalize(const ProofRef &proof); + bool reconcileOrFinalize(const ProofRef &proof) + EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager, !cs_finalizedItems); bool isAccepted(const AnyVoteItem &item) const; int getConfidence(const AnyVoteItem &item) const; - bool isRecentlyFinalized(const uint256 &itemId) const; - void clearFinalizedItems(); + bool isRecentlyFinalized(const uint256 &itemId) const + EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager, !cs_finalizedItems); + void clearFinalizedItems() EXCLUSIVE_LOCKS_REQUIRED(!cs_finalizedItems); // TODO: Refactor the API to remove the dependency on avalanche/protocol.h void sendResponse(CNode *pfrom, Response response) const; bool registerVotes(NodeId nodeid, const Response &response, std::vector &updates, int &banscore, - std::string &error); + std::string &error) + EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager, !cs_finalizedItems, + !cs_invalidatedBlocks, !cs_finalizationTip); - template auto withPeerManager(Callable &&func) const { + template + auto withPeerManager(Callable &&func) const + EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager) { LOCK(cs_peerManager); return func(*peerManager); } @@ -325,8 +332,10 @@ * @param pfrom The node to send the message to * @return True if a non-null delegation has been announced */ - bool sendHello(CNode *pfrom); - void sendDelayedAvahello(); + bool sendHello(CNode *pfrom) + EXCLUSIVE_LOCKS_REQUIRED(!cs_delayedAvahelloNodeIds); + void sendDelayedAvahello() + EXCLUSIVE_LOCKS_REQUIRED(!cs_delayedAvahelloNodeIds); ProofRef getLocalProof() const; ProofRegistrationState getLocalProofRegistrationState() const; @@ -339,20 +348,26 @@ bool startEventLoop(CScheduler &scheduler); bool stopEventLoop(); - void avaproofsSent(NodeId nodeid) LOCKS_EXCLUDED(cs_main); + void avaproofsSent(NodeId nodeid) LOCKS_EXCLUDED(cs_main) + EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager); int64_t getAvaproofsNodeCounter() const { return avaproofsNodeCounter.load(); } - bool isQuorumEstablished() LOCKS_EXCLUDED(cs_main); + bool isQuorumEstablished() LOCKS_EXCLUDED(cs_main) + EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager, !cs_stakingRewards); bool canShareLocalProof(); - bool computeStakingReward(const CBlockIndex *pindex); - bool eraseStakingRewardWinner(const BlockHash &prevBlockHash); - void cleanupStakingRewards(const int minHeight); + bool computeStakingReward(const CBlockIndex *pindex) + EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager, !cs_stakingRewards); + bool eraseStakingRewardWinner(const BlockHash &prevBlockHash) + EXCLUSIVE_LOCKS_REQUIRED(!cs_stakingRewards); + void cleanupStakingRewards(const int minHeight) + EXCLUSIVE_LOCKS_REQUIRED(!cs_stakingRewards); bool getStakingRewardWinner(const BlockHash &prevBlockHash, - CScript &winner) const; - bool setStakingRewardWinner(const CBlockIndex *pprev, - const CScript &winner); + CScript &winner) const + EXCLUSIVE_LOCKS_REQUIRED(!cs_stakingRewards); + bool setStakingRewardWinner(const CBlockIndex *pprev, const CScript &winner) + EXCLUSIVE_LOCKS_REQUIRED(!cs_stakingRewards); // Implement NetEventInterface. Only FinalizeNode is of interest. void InitializeNode(const ::Config &config, CNode &pnode, @@ -366,17 +381,23 @@ } /** Handle removal of a node */ - void FinalizeNode(const ::Config &config, const CNode &node) override - LOCKS_EXCLUDED(cs_main); + void FinalizeNode(const ::Config &config, + const CNode &node) override LOCKS_EXCLUDED(cs_main) + EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager, !cs_delayedAvahelloNodeIds); private: - void updatedBlockTip(); - void runEventLoop(); - void clearTimedoutRequests(); - std::vector getInvsForNextPoll(bool forPoll = true); + void updatedBlockTip() + EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager, !cs_finalizedItems); + void runEventLoop() + EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager, !cs_stakingRewards, + !cs_finalizedItems); + void clearTimedoutRequests() EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager); + std::vector getInvsForNextPoll(bool forPoll = true) + EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager, !cs_finalizedItems); bool sendHelloInternal(CNode *pfrom) EXCLUSIVE_LOCKS_REQUIRED(cs_delayedAvahelloNodeIds); - AnyVoteItem getVoteItemFromInv(const CInv &inv) const; + AnyVoteItem getVoteItemFromInv(const CInv &inv) const + EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager); /** * We don't need many blocks but a low false positive rate. @@ -412,7 +433,8 @@ LOCKS_EXCLUDED(cs_peerManager); bool operator()(const CTransactionRef &tx) const; }; - bool isWorthPolling(const AnyVoteItem &item) const; + bool isWorthPolling(const AnyVoteItem &item) const + EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager, !cs_finalizedItems); struct GetLocalAcceptance { const Processor &processor; diff --git a/src/eventloop.h b/src/eventloop.h --- a/src/eventloop.h +++ b/src/eventloop.h @@ -6,6 +6,7 @@ #define BITCOIN_EVENTLOOP_H #include +#include #include #include @@ -21,8 +22,9 @@ bool startEventLoop(CScheduler &scheduler, std::function runEventLoop, - std::chrono::milliseconds delta); - bool stopEventLoop(); + std::chrono::milliseconds delta) + EXCLUSIVE_LOCKS_REQUIRED(!cs_running); + bool stopEventLoop() EXCLUSIVE_LOCKS_REQUIRED(!cs_running); private: /** diff --git a/src/net_processing.cpp b/src/net_processing.cpp --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -732,17 +732,18 @@ ServiceFlags our_services) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex); void FinalizeNode(const Config &config, const CNode &node) override - EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex); + EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !cs_proofrequest); bool ProcessMessages(const Config &config, CNode *pfrom, std::atomic &interrupt) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, - !m_most_recent_block_mutex); + !m_most_recent_block_mutex, !cs_proofrequest); bool SendMessages(const Config &config, CNode *pto) override EXCLUSIVE_LOCKS_REQUIRED(pto->cs_sendProcessing) EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, - !m_most_recent_block_mutex); + !m_most_recent_block_mutex, + !cs_proofrequest); /** Implement PeerManager */ void StartScheduledTasks(CScheduler &scheduler) override; @@ -768,7 +769,7 @@ const std::atomic &interruptMsgProc) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, - !m_most_recent_block_mutex); + !m_most_recent_block_mutex, !cs_proofrequest); void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds) override; @@ -1267,7 +1268,8 @@ * @return Our current vote for the transaction */ uint32_t GetAvalancheVoteForTx(const TxId &id) const - EXCLUSIVE_LOCKS_REQUIRED(cs_main); + EXCLUSIVE_LOCKS_REQUIRED(cs_main, + !m_recent_confirmed_transactions_mutex); /** * Checks if address relay is permitted with peer. If needed, initializes @@ -1285,7 +1287,7 @@ */ bool ReceivedAvalancheProof(CNode &node, Peer &peer, const avalanche::ProofRef &proof) - EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex); + EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !cs_proofrequest); avalanche::ProofRef FindProofForGetData(const CNode &peer, const avalanche::ProofId &proofid, diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -114,7 +115,8 @@ } void openNetworkConnection(const CAddress &addrConnect, - ConnectionType connType) { + ConnectionType connType) + EXCLUSIVE_LOCKS_REQUIRED(!cs) { bool newConnection = !AlreadyConnectedToAddress(addrConnect); addrman.Attempt(addrConnect, true); @@ -147,7 +149,7 @@ bool checkContiguousAddressesConnection( const std::vector &testAddresses, size_t expectedOutboundFullRelayCount, - size_t expectedAvalancheOutboundsCount) { + size_t expectedAvalancheOutboundsCount) EXCLUSIVE_LOCKS_REQUIRED(!cs) { { LOCK(cs); diff --git a/src/validation.h b/src/validation.h --- a/src/validation.h +++ b/src/validation.h @@ -830,7 +830,8 @@ /** Import blocks from an external file */ void LoadExternalBlockFile(const Config &config, FILE *fileIn, FlatFilePos *dbp = nullptr) - EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex); + EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex, + !cs_avalancheFinalizedBlockIndex); /** * Update the on-disk chain state. @@ -876,7 +877,9 @@ */ bool ActivateBestChain(const Config &config, BlockValidationState &state, std::shared_ptr pblock = nullptr) - EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex) LOCKS_EXCLUDED(cs_main); + EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex, + !cs_avalancheFinalizedBlockIndex) + LOCKS_EXCLUDED(cs_main); bool AcceptBlock(const Config &config, const std::shared_ptr &pblock, @@ -908,30 +911,37 @@ */ bool PreciousBlock(const Config &config, BlockValidationState &state, CBlockIndex *pindex) - EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex) LOCKS_EXCLUDED(cs_main); + EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex, + !cs_avalancheFinalizedBlockIndex) + LOCKS_EXCLUDED(cs_main); /** Mark a block as invalid. */ bool InvalidateBlock(const Config &config, BlockValidationState &state, CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main) - EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex); + EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex, + !cs_avalancheFinalizedBlockIndex); /** Park a block. */ bool ParkBlock(const Config &config, BlockValidationState &state, CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main) - EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex); + EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex, + !cs_avalancheFinalizedBlockIndex); /** * Mark a block as finalized by avalanche. */ - bool AvalancheFinalizeBlock(CBlockIndex *pindex); + bool AvalancheFinalizeBlock(CBlockIndex *pindex) + EXCLUSIVE_LOCKS_REQUIRED(!cs_avalancheFinalizedBlockIndex); /** * Clear avalanche finalization. */ - void ClearAvalancheFinalizedBlock(); + void ClearAvalancheFinalizedBlock() + EXCLUSIVE_LOCKS_REQUIRED(!cs_avalancheFinalizedBlockIndex); /** * Checks if a block is finalized by avalanche voting. */ - bool IsBlockAvalancheFinalized(const CBlockIndex *pindex) const; + bool IsBlockAvalancheFinalized(const CBlockIndex *pindex) const + EXCLUSIVE_LOCKS_REQUIRED(!cs_avalancheFinalizedBlockIndex); /** Remove invalidity status from a block and its descendants. */ void ResetBlockFailureFlags(CBlockIndex *pindex) @@ -1014,20 +1024,22 @@ CBlockIndex *pindexMostWork, const std::shared_ptr &pblock, bool &fInvalidFound, ConnectTrace &connectTrace) - EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_mempool->cs); + EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_mempool->cs, + !cs_avalancheFinalizedBlockIndex); bool ConnectTip(const Config &config, BlockValidationState &state, BlockPolicyValidationState &blockPolicyState, CBlockIndex *pindexNew, const std::shared_ptr &pblock, ConnectTrace &connectTrace, DisconnectedBlockTransactions &disconnectpool) - EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_mempool->cs); + EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_mempool->cs, + !cs_avalancheFinalizedBlockIndex); void InvalidBlockFound(CBlockIndex *pindex, const BlockValidationState &state) - EXCLUSIVE_LOCKS_REQUIRED(cs_main); + EXCLUSIVE_LOCKS_REQUIRED(cs_main, !cs_avalancheFinalizedBlockIndex); CBlockIndex * FindMostWorkChain(std::vector &blocksToReconcile) - EXCLUSIVE_LOCKS_REQUIRED(cs_main); + EXCLUSIVE_LOCKS_REQUIRED(cs_main, !cs_avalancheFinalizedBlockIndex); void ReceivedBlockTransactions(const CBlock &block, CBlockIndex *pindexNew, const FlatFilePos &pos) EXCLUSIVE_LOCKS_REQUIRED(cs_main); @@ -1040,13 +1052,14 @@ bool UnwindBlock(const Config &config, BlockValidationState &state, CBlockIndex *pindex, bool invalidate) - EXCLUSIVE_LOCKS_REQUIRED(m_chainstate_mutex); + EXCLUSIVE_LOCKS_REQUIRED(m_chainstate_mutex, + !cs_avalancheFinalizedBlockIndex); void CheckForkWarningConditions() EXCLUSIVE_LOCKS_REQUIRED(cs_main); void CheckForkWarningConditionsOnNewFork(CBlockIndex *pindexNewForkTip) EXCLUSIVE_LOCKS_REQUIRED(cs_main); void InvalidChainFound(CBlockIndex *pindexNew) - EXCLUSIVE_LOCKS_REQUIRED(cs_main); + EXCLUSIVE_LOCKS_REQUIRED(cs_main, !cs_avalancheFinalizedBlockIndex); const CBlockIndex *FindBlockToFinalize(CBlockIndex *pindexNew) EXCLUSIVE_LOCKS_REQUIRED(cs_main);