mirror of
https://github.com/dashpay/dash.git
synced 2024-12-24 19:42:46 +01:00
1db9e6ac76
Merge #19979: Replace LockAssertion with AssertLockHeld, remove LockAssertion (MarcoFalke)d0a4198166
Merge #21598: refactor: Remove negative lock annotations from globals (MarcoFalke)55114a682e
Merge #19668: Do not hide compile-time thread safety warnings (MarcoFalke)898282d620
Merge bitcoin/bitcoin#28774: wallet: avoid returning a reference to vMasterKey after releasing the mutex that guards it (Ava Chow)6d452845dc
fix: add missing lock annotation for ContextualCheckBlock and related TODO (Konstantin Akimov)846ebab6e0
fix: fixes for orphange's locks and cs_main (Konstantin Akimov)002580c42d
fix: add ignoring safety-annotation for llmq/signing_shares due to template lambdas (Konstantin Akimov)502d6ae8ef
fix: add multiple missing annotation about locks for dash specific code (Konstantin Akimov)a219a8be15
partial Merge #29040: refactor: Remove pre-C++20 code, fs::path cleanup (Konstantin Akimov)042e8a4101
fix: drop unneded lock assert in net.cpp for m_nodes_mutex (Konstantin Akimov) Pull request description: ## What was done? These 4 backports improve noticeable implementation of thread-safety analysis by moving many possible warnings to compilation level. There's a lot of fixes for annotations after that! ## How Has This Been Tested? Build with clang: ``` CC=clang CXX=clang++ ./configure --prefix=$(pwd)/depends/x86_64-pc-linux-gnu --enable-suppress-external-warnings --enable-debug --enable-stacktraces --enable-werror --enable-crash-hooks --enable-maintainer-mode ``` ## Breaking Changes n/a ## Checklist: - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] I have added or updated relevant unit/integration/functional/e2e tests - [x] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone ACKs for top commit: UdjinM6: utACK1db9e6ac76
PastaPastaPasta: utACK1db9e6ac76
Tree-SHA512: 42a73e423f311689babc366b58a92f024556cf63af93357cfa0715c471efc1491d02ed9e7ba19b23efcdf423ab5bd051a24da2ad64c32e4b6db132a05f6669c1
This commit is contained in:
commit
7701b8dcea
@ -899,6 +899,53 @@ the upper cycle, etc.
|
|||||||
Threads and synchronization
|
Threads and synchronization
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
|
- Prefer `Mutex` type to `RecursiveMutex` one
|
||||||
|
|
||||||
|
- Consistently use [Clang Thread Safety Analysis](https://clang.llvm.org/docs/ThreadSafetyAnalysis.html) annotations to
|
||||||
|
get compile-time warnings about potential race conditions in code. Combine annotations in function declarations with
|
||||||
|
run-time asserts in function definitions:
|
||||||
|
|
||||||
|
```C++
|
||||||
|
// txmempool.h
|
||||||
|
class CTxMemPool
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
...
|
||||||
|
mutable RecursiveMutex cs;
|
||||||
|
...
|
||||||
|
void UpdateTransactionsFromBlock(...) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, cs);
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
// txmempool.cpp
|
||||||
|
void CTxMemPool::UpdateTransactionsFromBlock(...)
|
||||||
|
{
|
||||||
|
AssertLockHeld(::cs_main);
|
||||||
|
AssertLockHeld(cs);
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```C++
|
||||||
|
// validation.h
|
||||||
|
class ChainstateManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
...
|
||||||
|
bool ProcessNewBlock(...) LOCKS_EXCLUDED(::cs_main);
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
// validation.cpp
|
||||||
|
bool ChainstateManager::ProcessNewBlock(...)
|
||||||
|
{
|
||||||
|
AssertLockNotHeld(::cs_main);
|
||||||
|
...
|
||||||
|
LOCK(::cs_main);
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
- Build and run tests with `-DDEBUG_LOCKORDER` to verify that no potential
|
- Build and run tests with `-DDEBUG_LOCKORDER` to verify that no potential
|
||||||
deadlocks are introduced.
|
deadlocks are introduced.
|
||||||
|
|
||||||
|
@ -1448,11 +1448,16 @@ bool CCoinJoinClientSession::MakeCollateralAmounts()
|
|||||||
});
|
});
|
||||||
|
|
||||||
// First try to use only non-denominated funds
|
// First try to use only non-denominated funds
|
||||||
if (std::any_of(vecTally.begin(), vecTally.end(), [&](const auto& item) { return MakeCollateralAmounts(item, false); })) {
|
if (ranges::any_of(vecTally, [&](const auto& item) EXCLUSIVE_LOCKS_REQUIRED(m_wallet.cs_wallet) {
|
||||||
|
return MakeCollateralAmounts(item, false);
|
||||||
|
})) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// There should be at least some denominated funds we should be able to break in pieces to continue mixing
|
// There should be at least some denominated funds we should be able to break in pieces to continue mixing
|
||||||
if (std::any_of(vecTally.begin(), vecTally.end(), [&](const auto& item) { return MakeCollateralAmounts(item, true); })) {
|
if (ranges::any_of(vecTally, [&](const auto& item) EXCLUSIVE_LOCKS_REQUIRED(m_wallet.cs_wallet) {
|
||||||
|
return MakeCollateralAmounts(item, true);
|
||||||
|
})) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,13 +161,16 @@ private:
|
|||||||
|
|
||||||
/// Create denominations
|
/// Create denominations
|
||||||
bool CreateDenominated(CAmount nBalanceToDenominate);
|
bool CreateDenominated(CAmount nBalanceToDenominate);
|
||||||
bool CreateDenominated(CAmount nBalanceToDenominate, const CompactTallyItem& tallyItem, bool fCreateMixingCollaterals);
|
bool CreateDenominated(CAmount nBalanceToDenominate, const CompactTallyItem& tallyItem, bool fCreateMixingCollaterals)
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(m_wallet.cs_wallet);
|
||||||
|
|
||||||
/// Split up large inputs or make fee sized inputs
|
/// Split up large inputs or make fee sized inputs
|
||||||
bool MakeCollateralAmounts();
|
bool MakeCollateralAmounts();
|
||||||
bool MakeCollateralAmounts(const CompactTallyItem& tallyItem, bool fTryDenominated);
|
bool MakeCollateralAmounts(const CompactTallyItem& tallyItem, bool fTryDenominated)
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(m_wallet.cs_wallet);
|
||||||
|
|
||||||
bool CreateCollateralTransaction(CMutableTransaction& txCollateral, std::string& strReason);
|
bool CreateCollateralTransaction(CMutableTransaction& txCollateral, std::string& strReason)
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(m_wallet.cs_wallet);
|
||||||
|
|
||||||
bool JoinExistingQueue(CAmount nBalanceNeedsAnonymized, CConnman& connman);
|
bool JoinExistingQueue(CAmount nBalanceNeedsAnonymized, CConnman& connman);
|
||||||
bool StartNewQueue(CAmount nBalanceNeedsAnonymized, CConnman& connman);
|
bool StartNewQueue(CAmount nBalanceNeedsAnonymized, CConnman& connman);
|
||||||
@ -175,7 +178,9 @@ private:
|
|||||||
/// step 0: select denominated inputs and txouts
|
/// step 0: select denominated inputs and txouts
|
||||||
bool SelectDenominate(std::string& strErrorRet, std::vector<CTxDSIn>& vecTxDSInRet);
|
bool SelectDenominate(std::string& strErrorRet, std::vector<CTxDSIn>& vecTxDSInRet);
|
||||||
/// step 1: prepare denominated inputs and outputs
|
/// step 1: prepare denominated inputs and outputs
|
||||||
bool PrepareDenominate(int nMinRounds, int nMaxRounds, std::string& strErrorRet, const std::vector<CTxDSIn>& vecTxDSIn, std::vector<std::pair<CTxDSIn, CTxOut> >& vecPSInOutPairsRet, bool fDryRun = false);
|
bool PrepareDenominate(int nMinRounds, int nMaxRounds, std::string& strErrorRet, const std::vector<CTxDSIn>& vecTxDSIn,
|
||||||
|
std::vector<std::pair<CTxDSIn, CTxOut>>& vecPSInOutPairsRet, bool fDryRun = false)
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(m_wallet.cs_wallet);
|
||||||
/// step 2: send denominated inputs and outputs prepared in step 1
|
/// step 2: send denominated inputs and outputs prepared in step 1
|
||||||
bool SendDenominate(const std::vector<std::pair<CTxDSIn, CTxOut> >& vecPSInOutPairsIn, CConnman& connman) EXCLUSIVE_LOCKS_REQUIRED(!cs_coinjoin);
|
bool SendDenominate(const std::vector<std::pair<CTxDSIn, CTxOut> >& vecPSInOutPairsIn, CConnman& connman) EXCLUSIVE_LOCKS_REQUIRED(!cs_coinjoin);
|
||||||
|
|
||||||
|
@ -398,8 +398,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
void CheckDSTXes(const CBlockIndex* pindex, const llmq::CChainLocksHandler& clhandler)
|
void CheckDSTXes(const CBlockIndex* pindex, const llmq::CChainLocksHandler& clhandler)
|
||||||
EXCLUSIVE_LOCKS_REQUIRED(!cs_mapdstx);
|
EXCLUSIVE_LOCKS_REQUIRED(!cs_mapdstx);
|
||||||
void UpdateDSTXConfirmedHeight(const CTransactionRef& tx, std::optional<int> nHeight);
|
void UpdateDSTXConfirmedHeight(const CTransactionRef& tx, std::optional<int> nHeight)
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(cs_mapdstx);
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ATMPIfSaneFee(ChainstateManager& chainman, const CTransactionRef& tx, bool test_accept = false)
|
bool ATMPIfSaneFee(ChainstateManager& chainman, const CTransactionRef& tx, bool test_accept = false)
|
||||||
|
@ -1067,11 +1067,13 @@ CDeterministicMNList CDeterministicMNManager::GetListForBlockInternal(gsl::not_n
|
|||||||
mnListsCache.emplace(snapshot.GetBlockHash(), snapshot);
|
mnListsCache.emplace(snapshot.GetBlockHash(), snapshot);
|
||||||
} else {
|
} else {
|
||||||
// keep snapshots for yet alive quorums
|
// keep snapshots for yet alive quorums
|
||||||
if (ranges::any_of(Params().GetConsensus().llmqs, [&snapshot, this](const auto& params){
|
if (ranges::any_of(Params().GetConsensus().llmqs,
|
||||||
AssertLockHeld(cs);
|
[&snapshot, this](const auto& params) EXCLUSIVE_LOCKS_REQUIRED(cs) {
|
||||||
return (snapshot.GetHeight() % params.dkgInterval == 0) &&
|
AssertLockHeld(cs);
|
||||||
(snapshot.GetHeight() + params.dkgInterval * (params.keepOldConnections + 1) >= tipIndex->nHeight);
|
return (snapshot.GetHeight() % params.dkgInterval == 0) &&
|
||||||
})) {
|
(snapshot.GetHeight() + params.dkgInterval * (params.keepOldConnections + 1) >=
|
||||||
|
tipIndex->nHeight);
|
||||||
|
})) {
|
||||||
mnListsCache.emplace(snapshot.GetBlockHash(), snapshot);
|
mnListsCache.emplace(snapshot.GetBlockHash(), snapshot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,8 +171,9 @@ public:
|
|||||||
[[nodiscard]] UniValue ToJson(bool extended = false) const;
|
[[nodiscard]] UniValue ToJson(bool extended = false) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool BuildSimplifiedMNListDiff(CDeterministicMNManager& dmnman, const ChainstateManager& chainman, const llmq::CQuorumBlockProcessor& qblockman,
|
bool BuildSimplifiedMNListDiff(CDeterministicMNManager& dmnman, const ChainstateManager& chainman,
|
||||||
const llmq::CQuorumManager& qman, const uint256& baseBlockHash, const uint256& blockHash,
|
const llmq::CQuorumBlockProcessor& qblockman, const llmq::CQuorumManager& qman,
|
||||||
CSimplifiedMNListDiff& mnListDiffRet, std::string& errorRet, bool extended = false);
|
const uint256& baseBlockHash, const uint256& blockHash, CSimplifiedMNListDiff& mnListDiffRet,
|
||||||
|
std::string& errorRet, bool extended = false) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
||||||
|
|
||||||
#endif // BITCOIN_EVO_SIMPLIFIEDMNS_H
|
#endif // BITCOIN_EVO_SIMPLIFIEDMNS_H
|
||||||
|
@ -19,9 +19,10 @@
|
|||||||
#include <primitives/block.h>
|
#include <primitives/block.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
|
|
||||||
static bool CheckSpecialTxInner(CDeterministicMNManager& dmnman, const ChainstateManager& chainman, const llmq::CQuorumManager& qman, const CTransaction& tx,
|
static bool CheckSpecialTxInner(CDeterministicMNManager& dmnman, const ChainstateManager& chainman,
|
||||||
const CBlockIndex* pindexPrev, const CCoinsViewCache& view, const std::optional<CRangesSet>& indexes, bool check_sigs,
|
const llmq::CQuorumManager& qman, const CTransaction& tx, const CBlockIndex* pindexPrev,
|
||||||
TxValidationState& state)
|
const CCoinsViewCache& view, const std::optional<CRangesSet>& indexes, bool check_sigs,
|
||||||
|
TxValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_main);
|
AssertLockHeld(cs_main);
|
||||||
|
|
||||||
|
@ -347,9 +347,9 @@ public:
|
|||||||
* - Track governance objects which are triggers
|
* - Track governance objects which are triggers
|
||||||
* - After triggers are activated and executed, they can be removed
|
* - After triggers are activated and executed, they can be removed
|
||||||
*/
|
*/
|
||||||
std::vector<std::shared_ptr<CSuperblock>> GetActiveTriggers() const;
|
std::vector<std::shared_ptr<CSuperblock>> GetActiveTriggers() const EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||||
bool AddNewTrigger(uint256 nHash);
|
bool AddNewTrigger(uint256 nHash) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||||
void CleanAndRemoveTriggers();
|
void CleanAndRemoveTriggers() EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||||
|
|
||||||
// Superblocks related:
|
// Superblocks related:
|
||||||
|
|
||||||
@ -373,7 +373,8 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void ExecuteBestSuperblock(const CDeterministicMNList& tip_mn_list, int nBlockHeight);
|
void ExecuteBestSuperblock(const CDeterministicMNList& tip_mn_list, int nBlockHeight);
|
||||||
bool GetBestSuperblock(const CDeterministicMNList& tip_mn_list, CSuperblock_sptr& pSuperblockRet, int nBlockHeight);
|
bool GetBestSuperblock(const CDeterministicMNList& tip_mn_list, CSuperblock_sptr& pSuperblockRet, int nBlockHeight)
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||||
|
|
||||||
std::optional<const CSuperblock> CreateSuperblockCandidate(int nHeight) const;
|
std::optional<const CSuperblock> CreateSuperblockCandidate(int nHeight) const;
|
||||||
std::optional<const CGovernanceObject> CreateGovernanceTrigger(const std::optional<const CSuperblock>& sb_opt, PeerManager& peerman,
|
std::optional<const CGovernanceObject> CreateGovernanceTrigger(const std::optional<const CSuperblock>& sb_opt, PeerManager& peerman,
|
||||||
|
@ -235,7 +235,8 @@ public:
|
|||||||
/// Check the collateral transaction for the budget proposal/finalized budget
|
/// Check the collateral transaction for the budget proposal/finalized budget
|
||||||
bool IsCollateralValid(const ChainstateManager& chainman, std::string& strError, bool& fMissingConfirmations) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
bool IsCollateralValid(const ChainstateManager& chainman, std::string& strError, bool& fMissingConfirmations) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||||
|
|
||||||
void UpdateLocalValidity(const CDeterministicMNList& tip_mn_list, const ChainstateManager& chainman);
|
void UpdateLocalValidity(const CDeterministicMNList& tip_mn_list, const ChainstateManager& chainman)
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||||
|
|
||||||
void UpdateSentinelVariables(const CDeterministicMNList& tip_mn_list);
|
void UpdateSentinelVariables(const CDeterministicMNList& tip_mn_list);
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ public:
|
|||||||
/// sync once and only needs to process blocks in the ValidationInterface
|
/// sync once and only needs to process blocks in the ValidationInterface
|
||||||
/// queue. If the index is catching up from far behind, this method does
|
/// queue. If the index is catching up from far behind, this method does
|
||||||
/// not block and immediately returns false.
|
/// not block and immediately returns false.
|
||||||
bool BlockUntilSyncedToCurrentChain() const;
|
bool BlockUntilSyncedToCurrentChain() const LOCKS_EXCLUDED(::cs_main);
|
||||||
|
|
||||||
void Interrupt();
|
void Interrupt();
|
||||||
|
|
||||||
|
@ -565,24 +565,29 @@ void CSigSharesManager::CollectPendingSigSharesToVerify(
|
|||||||
// other nodes would be able to poison us with a large batch with N-1 valid shares and the last one being
|
// other nodes would be able to poison us with a large batch with N-1 valid shares and the last one being
|
||||||
// invalid, making batch verification fail and revert to per-share verification, which in turn would slow down
|
// invalid, making batch verification fail and revert to per-share verification, which in turn would slow down
|
||||||
// the whole verification process
|
// the whole verification process
|
||||||
|
|
||||||
std::unordered_set<std::pair<NodeId, uint256>, StaticSaltedHasher> uniqueSignHashes;
|
std::unordered_set<std::pair<NodeId, uint256>, StaticSaltedHasher> uniqueSignHashes;
|
||||||
IterateNodesRandom(nodeStates, [&]() {
|
IterateNodesRandom(
|
||||||
return uniqueSignHashes.size() < maxUniqueSessions;
|
nodeStates,
|
||||||
}, [&](NodeId nodeId, CSigSharesNodeState& ns) {
|
[&]() {
|
||||||
if (ns.pendingIncomingSigShares.Empty()) {
|
return uniqueSignHashes.size() < maxUniqueSessions;
|
||||||
return false;
|
// TODO: remove NO_THREAD_SAFETY_ANALYSIS
|
||||||
}
|
// using here template IterateNodesRandom makes impossible to use lock annotation
|
||||||
const auto& sigShare = *ns.pendingIncomingSigShares.GetFirst();
|
},
|
||||||
|
[&](NodeId nodeId, CSigSharesNodeState& ns) NO_THREAD_SAFETY_ANALYSIS {
|
||||||
|
if (ns.pendingIncomingSigShares.Empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto& sigShare = *ns.pendingIncomingSigShares.GetFirst();
|
||||||
|
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
if (const bool alreadyHave = this->sigShares.Has(sigShare.GetKey()); !alreadyHave) {
|
if (const bool alreadyHave = this->sigShares.Has(sigShare.GetKey()); !alreadyHave) {
|
||||||
uniqueSignHashes.emplace(nodeId, sigShare.GetSignHash());
|
uniqueSignHashes.emplace(nodeId, sigShare.GetSignHash());
|
||||||
retSigShares[nodeId].emplace_back(sigShare);
|
retSigShares[nodeId].emplace_back(sigShare);
|
||||||
}
|
}
|
||||||
ns.pendingIncomingSigShares.Erase(sigShare.GetKey());
|
ns.pendingIncomingSigShares.Erase(sigShare.GetKey());
|
||||||
return !ns.pendingIncomingSigShares.Empty();
|
return !ns.pendingIncomingSigShares.Empty();
|
||||||
}, rnd);
|
},
|
||||||
|
rnd);
|
||||||
|
|
||||||
if (retSigShares.empty()) {
|
if (retSigShares.empty()) {
|
||||||
return;
|
return;
|
||||||
@ -1020,7 +1025,10 @@ void CSigSharesManager::CollectSigSharesToAnnounce(std::unordered_map<NodeId, st
|
|||||||
|
|
||||||
std::unordered_map<std::pair<Consensus::LLMQType, uint256>, std::unordered_set<NodeId>, StaticSaltedHasher> quorumNodesMap;
|
std::unordered_map<std::pair<Consensus::LLMQType, uint256>, std::unordered_set<NodeId>, StaticSaltedHasher> quorumNodesMap;
|
||||||
|
|
||||||
sigSharesQueuedToAnnounce.ForEach([this, &quorumNodesMap, &sigSharesToAnnounce](const SigShareKey& sigShareKey, bool) {
|
// TODO: remove NO_THREAD_SAFETY_ANALYSIS
|
||||||
|
// using here template ForEach makes impossible to use lock annotation
|
||||||
|
sigSharesQueuedToAnnounce.ForEach([this, &quorumNodesMap, &sigSharesToAnnounce](const SigShareKey& sigShareKey,
|
||||||
|
bool) NO_THREAD_SAFETY_ANALYSIS {
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
const auto& signHash = sigShareKey.first;
|
const auto& signHash = sigShareKey.first;
|
||||||
auto quorumMember = sigShareKey.second;
|
auto quorumMember = sigShareKey.second;
|
||||||
@ -1076,7 +1084,7 @@ bool CSigSharesManager::SendMessages()
|
|||||||
std::unordered_map<NodeId, std::unordered_map<uint256, CSigSharesInv, StaticSaltedHasher>> sigSharesToAnnounce;
|
std::unordered_map<NodeId, std::unordered_map<uint256, CSigSharesInv, StaticSaltedHasher>> sigSharesToAnnounce;
|
||||||
std::unordered_map<NodeId, std::vector<CSigSesAnn>> sigSessionAnnouncements;
|
std::unordered_map<NodeId, std::vector<CSigSesAnn>> sigSessionAnnouncements;
|
||||||
|
|
||||||
auto addSigSesAnnIfNeeded = [&](NodeId nodeId, const uint256& signHash) {
|
auto addSigSesAnnIfNeeded = [&](NodeId nodeId, const uint256& signHash) EXCLUSIVE_LOCKS_REQUIRED(cs) {
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
auto& nodeState = nodeStates[nodeId];
|
auto& nodeState = nodeStates[nodeId];
|
||||||
auto* session = nodeState.GetSessionBySignHash(signHash);
|
auto* session = nodeState.GetSessionBySignHash(signHash);
|
||||||
@ -1357,7 +1365,9 @@ void CSigSharesManager::Cleanup()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// remove global requested state to force a re-request from another node
|
// remove global requested state to force a re-request from another node
|
||||||
it->second.requestedSigShares.ForEach([this](const SigShareKey& k, bool) {
|
// TODO: remove NO_THREAD_SAFETY_ANALYSIS
|
||||||
|
// using here template ForEach makes impossible to use lock annotation
|
||||||
|
it->second.requestedSigShares.ForEach([this](const SigShareKey& k, bool) NO_THREAD_SAFETY_ANALYSIS {
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
sigSharesRequested.Erase(k);
|
sigSharesRequested.Erase(k);
|
||||||
});
|
});
|
||||||
@ -1390,7 +1400,9 @@ void CSigSharesManager::RemoveBannedNodeStates()
|
|||||||
for (auto it = nodeStates.begin(); it != nodeStates.end();) {
|
for (auto it = nodeStates.begin(); it != nodeStates.end();) {
|
||||||
if (Assert(m_peerman)->IsBanned(it->first)) {
|
if (Assert(m_peerman)->IsBanned(it->first)) {
|
||||||
// re-request sigshares from other nodes
|
// re-request sigshares from other nodes
|
||||||
it->second.requestedSigShares.ForEach([this](const SigShareKey& k, int64_t) {
|
// TODO: remove NO_THREAD_SAFETY_ANALYSIS
|
||||||
|
// using here template ForEach makes impossible to use lock annotation
|
||||||
|
it->second.requestedSigShares.ForEach([this](const SigShareKey& k, int64_t) NO_THREAD_SAFETY_ANALYSIS {
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
sigSharesRequested.Erase(k);
|
sigSharesRequested.Erase(k);
|
||||||
});
|
});
|
||||||
@ -1419,7 +1431,9 @@ void CSigSharesManager::BanNode(NodeId nodeId)
|
|||||||
auto& nodeState = it->second;
|
auto& nodeState = it->second;
|
||||||
|
|
||||||
// Whatever we requested from him, let's request it from someone else now
|
// Whatever we requested from him, let's request it from someone else now
|
||||||
nodeState.requestedSigShares.ForEach([this](const SigShareKey& k, int64_t) {
|
// TODO: remove NO_THREAD_SAFETY_ANALYSIS
|
||||||
|
// using here template ForEach makes impossible to use lock annotation
|
||||||
|
nodeState.requestedSigShares.ForEach([this](const SigShareKey& k, int64_t) NO_THREAD_SAFETY_ANALYSIS {
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
sigSharesRequested.Erase(k);
|
sigSharesRequested.Erase(k);
|
||||||
});
|
});
|
||||||
|
@ -209,7 +209,7 @@ public:
|
|||||||
|
|
||||||
bool BuildQuorumRotationInfo(CDeterministicMNManager& dmnman, const ChainstateManager& chainman, const CQuorumManager& qman,
|
bool BuildQuorumRotationInfo(CDeterministicMNManager& dmnman, const ChainstateManager& chainman, const CQuorumManager& qman,
|
||||||
const CQuorumBlockProcessor& qblockman, const CGetQuorumRotationInfo& request,
|
const CQuorumBlockProcessor& qblockman, const CGetQuorumRotationInfo& request,
|
||||||
CQuorumRotationInfo& response, std::string& errorRet);
|
CQuorumRotationInfo& response, std::string& errorRet) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
||||||
uint256 GetLastBaseBlockHash(Span<const CBlockIndex*> baseBlockIndexes, const CBlockIndex* blockIndex);
|
uint256 GetLastBaseBlockHash(Span<const CBlockIndex*> baseBlockIndexes, const CBlockIndex* blockIndex);
|
||||||
|
|
||||||
class CQuorumSnapshotManager
|
class CQuorumSnapshotManager
|
||||||
|
@ -73,7 +73,11 @@ public:
|
|||||||
UniValue ToJson() const;
|
UniValue ToJson() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const uint256& GetProTxHash() const { LOCK(cs); return proTxHash; }
|
const uint256 GetProTxHash() const
|
||||||
|
{
|
||||||
|
LOCK(cs);
|
||||||
|
return proTxHash;
|
||||||
|
}
|
||||||
int64_t GetLastDsq() const { return nLastDsq; }
|
int64_t GetLastDsq() const { return nLastDsq; }
|
||||||
int GetMixingTxCount() const { return nMixingTxCount; }
|
int GetMixingTxCount() const { return nMixingTxCount; }
|
||||||
|
|
||||||
|
10
src/net.cpp
10
src/net.cpp
@ -647,8 +647,6 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
|
|||||||
|
|
||||||
void CNode::CloseSocketDisconnect(CConnman* connman)
|
void CNode::CloseSocketDisconnect(CConnman* connman)
|
||||||
{
|
{
|
||||||
AssertLockHeld(connman->m_nodes_mutex);
|
|
||||||
|
|
||||||
fDisconnect = true;
|
fDisconnect = true;
|
||||||
LOCK2(connman->cs_mapSocketToNode, m_sock_mutex);
|
LOCK2(connman->cs_mapSocketToNode, m_sock_mutex);
|
||||||
if (!m_sock) {
|
if (!m_sock) {
|
||||||
@ -3587,8 +3585,8 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman,
|
|||||||
|
|
||||||
MasternodeProbeConn isProbe = MasternodeProbeConn::IsNotConnection;
|
MasternodeProbeConn isProbe = MasternodeProbeConn::IsNotConnection;
|
||||||
|
|
||||||
const auto getPendingQuorumNodes = [&]() {
|
const auto getPendingQuorumNodes = [&]() EXCLUSIVE_LOCKS_REQUIRED(cs_vPendingMasternodes) {
|
||||||
LockAssertion lock(cs_vPendingMasternodes);
|
AssertLockHeld(cs_vPendingMasternodes);
|
||||||
std::vector<CDeterministicMNCPtr> ret;
|
std::vector<CDeterministicMNCPtr> ret;
|
||||||
for (const auto& group : masternodeQuorumNodes) {
|
for (const auto& group : masternodeQuorumNodes) {
|
||||||
for (const auto& proRegTxHash : group.second) {
|
for (const auto& proRegTxHash : group.second) {
|
||||||
@ -3626,8 +3624,8 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman,
|
|||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto getPendingProbes = [&]() {
|
const auto getPendingProbes = [&]() EXCLUSIVE_LOCKS_REQUIRED(cs_vPendingMasternodes) {
|
||||||
LockAssertion lock(cs_vPendingMasternodes);
|
AssertLockHeld(cs_vPendingMasternodes);
|
||||||
std::vector<CDeterministicMNCPtr> ret;
|
std::vector<CDeterministicMNCPtr> ret;
|
||||||
for (auto it = masternodePendingProbes.begin(); it != masternodePendingProbes.end(); ) {
|
for (auto it = masternodePendingProbes.begin(); it != masternodePendingProbes.end(); ) {
|
||||||
auto dmn = mnList.GetMN(*it);
|
auto dmn = mnList.GetMN(*it);
|
||||||
|
12
src/net.h
12
src/net.h
@ -1316,6 +1316,8 @@ public:
|
|||||||
return ForNode(id, FullyConnectedOnly, func);
|
return ForNode(id, FullyConnectedOnly, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using NodeFn = std::function<void(CNode*)>;
|
||||||
|
|
||||||
bool IsConnected(const CService& addr, std::function<bool(const CNode* pnode)> cond)
|
bool IsConnected(const CService& addr, std::function<bool(const CNode* pnode)> cond)
|
||||||
{
|
{
|
||||||
return ForNode(addr, cond, [](CNode* pnode){
|
return ForNode(addr, cond, [](CNode* pnode){
|
||||||
@ -1372,10 +1374,9 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Callable>
|
void ForEachNode(const NodeFn& fn)
|
||||||
void ForEachNode(Callable&& func)
|
|
||||||
{
|
{
|
||||||
ForEachNode(FullyConnectedOnly, func);
|
ForEachNode(FullyConnectedOnly, fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Condition, typename Callable>
|
template<typename Condition, typename Callable>
|
||||||
@ -1388,10 +1389,9 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Callable>
|
void ForEachNode(const NodeFn& fn) const
|
||||||
void ForEachNode(Callable&& func) const
|
|
||||||
{
|
{
|
||||||
ForEachNode(FullyConnectedOnly, func);
|
ForEachNode(FullyConnectedOnly, fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Condition, typename Callable, typename CallableAfter>
|
template<typename Condition, typename Callable, typename CallableAfter>
|
||||||
|
@ -944,7 +944,7 @@ private:
|
|||||||
/** Determine whether or not a peer can request a transaction, and return it (or nullptr if not found or not allowed). */
|
/** Determine whether or not a peer can request a transaction, and return it (or nullptr if not found or not allowed). */
|
||||||
CTransactionRef FindTxForGetData(const CNode* peer, const uint256& txid, const std::chrono::seconds mempool_req, const std::chrono::seconds now) LOCKS_EXCLUDED(cs_main);
|
CTransactionRef FindTxForGetData(const CNode* peer, const uint256& txid, const std::chrono::seconds mempool_req, const std::chrono::seconds now) LOCKS_EXCLUDED(cs_main);
|
||||||
|
|
||||||
void ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic<bool>& interruptMsgProc) LOCKS_EXCLUDED(cs_main) EXCLUSIVE_LOCKS_REQUIRED(peer.m_getdata_requests_mutex);
|
void ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic<bool>& interruptMsgProc) EXCLUSIVE_LOCKS_REQUIRED(peer.m_getdata_requests_mutex) LOCKS_EXCLUDED(::cs_main);
|
||||||
|
|
||||||
/** Process a new block. Perform any post-processing housekeeping */
|
/** Process a new block. Perform any post-processing housekeeping */
|
||||||
void ProcessBlock(CNode& from, const std::shared_ptr<const CBlock>& pblock, bool force_processing);
|
void ProcessBlock(CNode& from, const std::shared_ptr<const CBlock>& pblock, bool force_processing);
|
||||||
@ -1930,12 +1930,14 @@ void PeerManagerImpl::StartScheduledTasks(CScheduler& scheduler)
|
|||||||
*/
|
*/
|
||||||
void PeerManagerImpl::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindex)
|
void PeerManagerImpl::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindex)
|
||||||
{
|
{
|
||||||
LOCK2(::cs_main, g_cs_orphans);
|
{
|
||||||
|
LOCK2(::cs_main, g_cs_orphans);
|
||||||
|
|
||||||
auto orphanWorkSet = m_orphanage.GetCandidatesForBlock(*pblock);
|
auto orphanWorkSet = m_orphanage.GetCandidatesForBlock(*pblock);
|
||||||
while (!orphanWorkSet.empty()) {
|
while (!orphanWorkSet.empty()) {
|
||||||
LogPrint(BCLog::MEMPOOL, "Trying to process %d orphans\n", orphanWorkSet.size());
|
LogPrint(BCLog::MEMPOOL, "Trying to process %d orphans\n", orphanWorkSet.size());
|
||||||
ProcessOrphanTx(orphanWorkSet);
|
ProcessOrphanTx(orphanWorkSet);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_orphanage.EraseForBlock(*pblock);
|
m_orphanage.EraseForBlock(*pblock);
|
||||||
@ -1998,8 +2000,8 @@ void PeerManagerImpl::NewPoWValidBlock(const CBlockIndex *pindex, const std::sha
|
|||||||
m_most_recent_compact_block = pcmpctblock;
|
m_most_recent_compact_block = pcmpctblock;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_connman.ForEachNode([this, pindex, &lazy_ser, &hashBlock](CNode* pnode) {
|
m_connman.ForEachNode([this, pindex, &lazy_ser, &hashBlock](CNode* pnode) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
|
||||||
LockAssertion lock(::cs_main);
|
AssertLockHeld(::cs_main);
|
||||||
// TODO: Avoid the repeated-serialization here
|
// TODO: Avoid the repeated-serialization here
|
||||||
if (pnode->fDisconnect)
|
if (pnode->fDisconnect)
|
||||||
return;
|
return;
|
||||||
@ -5276,8 +5278,8 @@ void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now)
|
|||||||
// We want to prevent recently connected to Onion peers from being disconnected here, protect them as long as
|
// We want to prevent recently connected to Onion peers from being disconnected here, protect them as long as
|
||||||
// there are more non_onion nodes than onion nodes so far
|
// there are more non_onion nodes than onion nodes so far
|
||||||
size_t onion_count = 0;
|
size_t onion_count = 0;
|
||||||
m_connman.ForEachNode([&](CNode* pnode) {
|
m_connman.ForEachNode([&](CNode* pnode) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
|
||||||
LockAssertion lock(::cs_main);
|
AssertLockHeld(::cs_main);
|
||||||
if (pnode->addr.IsTor() && ++onion_count <= m_connman.GetMaxOutboundOnionNodeCount()) return;
|
if (pnode->addr.IsTor() && ++onion_count <= m_connman.GetMaxOutboundOnionNodeCount()) return;
|
||||||
// Don't disconnect masternodes just because they were slow in block announcement
|
// Don't disconnect masternodes just because they were slow in block announcement
|
||||||
if (pnode->m_masternode_connection) return;
|
if (pnode->m_masternode_connection) return;
|
||||||
@ -5294,8 +5296,8 @@ void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now)
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (worst_peer != -1) {
|
if (worst_peer != -1) {
|
||||||
bool disconnected = m_connman.ForNode(worst_peer, [&](CNode *pnode) {
|
bool disconnected = m_connman.ForNode(worst_peer, [&](CNode* pnode) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
|
||||||
LockAssertion lock(::cs_main);
|
AssertLockHeld(::cs_main);
|
||||||
|
|
||||||
// Only disconnect a peer that has been connected to us for
|
// Only disconnect a peer that has been connected to us for
|
||||||
// some reasonable fraction of our check-frequency, to give
|
// some reasonable fraction of our check-frequency, to give
|
||||||
@ -5774,7 +5776,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
|
|||||||
peer->m_blocks_for_inv_relay.clear();
|
peer->m_blocks_for_inv_relay.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto queueAndMaybePushInv = [this, pto, peer, &vInv, &msgMaker](const CInv& invIn) {
|
auto queueAndMaybePushInv = [this, pto, peer, &vInv, &msgMaker](const CInv& invIn) EXCLUSIVE_LOCKS_REQUIRED(peer->m_tx_relay->m_tx_inventory_mutex) {
|
||||||
AssertLockHeld(peer->m_tx_relay->m_tx_inventory_mutex);
|
AssertLockHeld(peer->m_tx_relay->m_tx_inventory_mutex);
|
||||||
peer->m_tx_relay->m_tx_inventory_known_filter.insert(invIn.hash);
|
peer->m_tx_relay->m_tx_inventory_known_filter.insert(invIn.hash);
|
||||||
LogPrint(BCLog::NET, "SendMessages -- queued inv: %s index=%d peer=%d\n", invIn.ToString(), vInv.size(), pto->GetId());
|
LogPrint(BCLog::NET, "SendMessages -- queued inv: %s index=%d peer=%d\n", invIn.ToString(), vInv.size(), pto->GetId());
|
||||||
|
@ -213,8 +213,9 @@ static bool ValidatePlatformPort(const int32_t port)
|
|||||||
|
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
|
|
||||||
template<typename SpecialTxPayload>
|
template <typename SpecialTxPayload>
|
||||||
static void FundSpecialTx(CWallet& wallet, CMutableTransaction& tx, const SpecialTxPayload& payload, const CTxDestination& fundDest)
|
static void FundSpecialTx(CWallet& wallet, CMutableTransaction& tx, const SpecialTxPayload& payload,
|
||||||
|
const CTxDestination& fundDest) EXCLUSIVE_LOCKS_REQUIRED(!wallet.cs_wallet)
|
||||||
{
|
{
|
||||||
// Make sure the results are valid at least up to the most recent block
|
// Make sure the results are valid at least up to the most recent block
|
||||||
// the user could have gotten from another RPC command prior to now
|
// the user could have gotten from another RPC command prior to now
|
||||||
|
@ -285,12 +285,16 @@ template void AssertLockHeldInternal(const char*, const char*, int, Mutex*);
|
|||||||
template void AssertLockHeldInternal(const char*, const char*, int, RecursiveMutex*);
|
template void AssertLockHeldInternal(const char*, const char*, int, RecursiveMutex*);
|
||||||
template void AssertLockHeldInternal(const char*, const char*, int, SharedMutex*);
|
template void AssertLockHeldInternal(const char*, const char*, int, SharedMutex*);
|
||||||
|
|
||||||
void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs)
|
template <typename MutexType>
|
||||||
|
void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs)
|
||||||
{
|
{
|
||||||
if (!LockHeld(cs)) return;
|
if (!LockHeld(cs)) return;
|
||||||
tfm::format(std::cerr, "Assertion failed: lock %s held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld());
|
tfm::format(std::cerr, "Assertion failed: lock %s held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld());
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
template void AssertLockNotHeldInternal(const char*, const char*, int, Mutex*);
|
||||||
|
template void AssertLockNotHeldInternal(const char*, const char*, int, RecursiveMutex*);
|
||||||
|
template void AssertLockNotHeldInternal(const char*, const char*, int, SharedMutex*);
|
||||||
|
|
||||||
void DeleteLock(void* cs)
|
void DeleteLock(void* cs)
|
||||||
{
|
{
|
||||||
|
24
src/sync.h
24
src/sync.h
@ -57,8 +57,9 @@ void LeaveCritical();
|
|||||||
void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line);
|
void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line);
|
||||||
std::string LocksHeld();
|
std::string LocksHeld();
|
||||||
template <typename MutexType>
|
template <typename MutexType>
|
||||||
void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) ASSERT_EXCLUSIVE_LOCK(cs);
|
void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||||
void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs);
|
template <typename MutexType>
|
||||||
|
void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) LOCKS_EXCLUDED(cs);
|
||||||
void DeleteLock(void* cs);
|
void DeleteLock(void* cs);
|
||||||
bool LockStackEmpty();
|
bool LockStackEmpty();
|
||||||
|
|
||||||
@ -74,8 +75,9 @@ inline void EnterCritical(const char* pszName, const char* pszFile, int nLine, M
|
|||||||
inline void LeaveCritical() {}
|
inline void LeaveCritical() {}
|
||||||
inline void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line) {}
|
inline void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line) {}
|
||||||
template <typename MutexType>
|
template <typename MutexType>
|
||||||
inline void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) ASSERT_EXCLUSIVE_LOCK(cs) {}
|
inline void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(cs) {}
|
||||||
inline void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) {}
|
template <typename MutexType>
|
||||||
|
void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) LOCKS_EXCLUDED(cs) {}
|
||||||
inline void DeleteLock(void* cs) {}
|
inline void DeleteLock(void* cs) {}
|
||||||
inline bool LockStackEmpty() { return true; }
|
inline bool LockStackEmpty() { return true; }
|
||||||
#endif
|
#endif
|
||||||
@ -481,18 +483,4 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Utility class for indicating to compiler thread analysis that a mutex is
|
|
||||||
// locked (when it couldn't be determined otherwise).
|
|
||||||
struct SCOPED_LOCKABLE LockAssertion
|
|
||||||
{
|
|
||||||
template <typename Mutex>
|
|
||||||
explicit LockAssertion(Mutex& mutex) EXCLUSIVE_LOCK_FUNCTION(mutex)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG_LOCKORDER
|
|
||||||
AssertLockHeld(mutex);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
~LockAssertion() UNLOCK_FUNCTION() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // BITCOIN_SYNC_H
|
#endif // BITCOIN_SYNC_H
|
||||||
|
@ -955,7 +955,7 @@ void CTxMemPool::removeProTxSpentCollateralConflicts(const CTransaction &tx)
|
|||||||
assert(m_dmnman);
|
assert(m_dmnman);
|
||||||
|
|
||||||
// Remove TXs that refer to a MN for which the collateral was spent
|
// Remove TXs that refer to a MN for which the collateral was spent
|
||||||
auto removeSpentCollateralConflict = [&](const uint256& proTxHash) {
|
auto removeSpentCollateralConflict = [&](const uint256& proTxHash) EXCLUSIVE_LOCKS_REQUIRED(cs) {
|
||||||
// Can't use equal_range here as every call to removeRecursive might invalidate iterators
|
// Can't use equal_range here as every call to removeRecursive might invalidate iterators
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -1353,7 +1353,7 @@ bool CTxMemPool::existsProviderTxConflict(const CTransaction &tx) const {
|
|||||||
|
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
|
|
||||||
auto hasKeyChangeInMempool = [&](const uint256& proTxHash) {
|
auto hasKeyChangeInMempool = [&](const uint256& proTxHash) EXCLUSIVE_LOCKS_REQUIRED(cs) {
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
for (auto its = mapProTxRefs.equal_range(proTxHash); its.first != its.second; ++its.first) {
|
for (auto its = mapProTxRefs.equal_range(proTxHash); its.first != its.second; ++its.first) {
|
||||||
auto txit = mapTx.find(its.first->second);
|
auto txit = mapTx.find(its.first->second);
|
||||||
|
@ -197,7 +197,7 @@ std::set<uint256> TxOrphanage::GetCandidatesForBlock(const CBlock& block)
|
|||||||
|
|
||||||
void TxOrphanage::EraseForBlock(const CBlock& block)
|
void TxOrphanage::EraseForBlock(const CBlock& block)
|
||||||
{
|
{
|
||||||
AssertLockHeld(g_cs_orphans);
|
LOCK(g_cs_orphans);
|
||||||
|
|
||||||
std::vector<uint256> vOrphanErase;
|
std::vector<uint256> vOrphanErase;
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ public:
|
|||||||
void EraseForPeer(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans);
|
void EraseForPeer(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans);
|
||||||
|
|
||||||
/** Erase all orphans included in or invalidated by a new block */
|
/** Erase all orphans included in or invalidated by a new block */
|
||||||
void EraseForBlock(const CBlock& block) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans);
|
void EraseForBlock(const CBlock& block) LOCKS_EXCLUDED(::g_cs_orphans);
|
||||||
|
|
||||||
/** Limit the orphanage to the given maximum */
|
/** Limit the orphanage to the given maximum */
|
||||||
unsigned int LimitOrphans(unsigned int max_orphans_size) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans);
|
unsigned int LimitOrphans(unsigned int max_orphans_size) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans);
|
||||||
|
@ -420,7 +420,7 @@ std::optional<unsigned int> ArgsManager::GetArgFlags(const std::string& name) co
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fs::path& ArgsManager::GetBlocksDirPath() const
|
const fs::path ArgsManager::GetBlocksDirPath() const
|
||||||
{
|
{
|
||||||
LOCK(cs_args);
|
LOCK(cs_args);
|
||||||
fs::path& path = m_cached_blocks_path;
|
fs::path& path = m_cached_blocks_path;
|
||||||
@ -445,7 +445,7 @@ const fs::path& ArgsManager::GetBlocksDirPath() const
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fs::path& ArgsManager::GetDataDir(bool net_specific) const
|
const fs::path ArgsManager::GetDataDir(bool net_specific) const
|
||||||
{
|
{
|
||||||
LOCK(cs_args);
|
LOCK(cs_args);
|
||||||
fs::path& path = net_specific ? m_cached_network_datadir_path : m_cached_datadir_path;
|
fs::path& path = net_specific ? m_cached_network_datadir_path : m_cached_datadir_path;
|
||||||
|
@ -288,7 +288,7 @@ protected:
|
|||||||
*
|
*
|
||||||
* @return Blocks path which is network specific
|
* @return Blocks path which is network specific
|
||||||
*/
|
*/
|
||||||
const fs::path& GetBlocksDirPath() const;
|
const fs::path GetBlocksDirPath() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get data directory path
|
* Get data directory path
|
||||||
@ -296,7 +296,7 @@ protected:
|
|||||||
* @return Absolute path on success, otherwise an empty path when a non-directory path would be returned
|
* @return Absolute path on success, otherwise an empty path when a non-directory path would be returned
|
||||||
* @post Returned directory path is created unless it is empty
|
* @post Returned directory path is created unless it is empty
|
||||||
*/
|
*/
|
||||||
const fs::path& GetDataDirBase() const { return GetDataDir(false); }
|
const fs::path GetDataDirBase() const { return GetDataDir(false); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get data directory path with appended network identifier
|
* Get data directory path with appended network identifier
|
||||||
@ -304,7 +304,7 @@ protected:
|
|||||||
* @return Absolute path on success, otherwise an empty path when a non-directory path would be returned
|
* @return Absolute path on success, otherwise an empty path when a non-directory path would be returned
|
||||||
* @post Returned directory path is created unless it is empty
|
* @post Returned directory path is created unless it is empty
|
||||||
*/
|
*/
|
||||||
const fs::path& GetDataDirNet() const { return GetDataDir(true); }
|
const fs::path GetDataDirNet() const { return GetDataDir(true); }
|
||||||
|
|
||||||
fs::path GetBackupsDirPath();
|
fs::path GetBackupsDirPath();
|
||||||
|
|
||||||
@ -483,7 +483,7 @@ private:
|
|||||||
* @return Absolute path on success, otherwise an empty path when a non-directory path would be returned
|
* @return Absolute path on success, otherwise an empty path when a non-directory path would be returned
|
||||||
* @post Returned directory path is created unless it is empty
|
* @post Returned directory path is created unless it is empty
|
||||||
*/
|
*/
|
||||||
const fs::path& GetDataDir(bool net_specific) const;
|
const fs::path GetDataDir(bool net_specific) const;
|
||||||
|
|
||||||
// Helper function for LogArgs().
|
// Helper function for LogArgs().
|
||||||
void logArgsPrefix(
|
void logArgsPrefix(
|
||||||
|
@ -3638,9 +3638,10 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidatio
|
|||||||
* in ConnectBlock().
|
* in ConnectBlock().
|
||||||
* Note that -reindex-chainstate skips the validation that happens here!
|
* Note that -reindex-chainstate skips the validation that happens here!
|
||||||
*/
|
*/
|
||||||
static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
|
static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_main);
|
// TODO: validate - why do we need this cs_main ?
|
||||||
|
AssertLockHeld(::cs_main);
|
||||||
const int nHeight = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1;
|
const int nHeight = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1;
|
||||||
|
|
||||||
// Enforce BIP113 (Median Time Past).
|
// Enforce BIP113 (Median Time Past).
|
||||||
|
@ -342,8 +342,11 @@ void LegacyScriptPubKeyMan::UpgradeKeyMetadata()
|
|||||||
CHDChain hdChainCurrent;
|
CHDChain hdChainCurrent;
|
||||||
if (!GetHDChain(hdChainCurrent))
|
if (!GetHDChain(hdChainCurrent))
|
||||||
throw std::runtime_error(std::string(__func__) + ": GetHDChain failed");
|
throw std::runtime_error(std::string(__func__) + ": GetHDChain failed");
|
||||||
if (!DecryptHDChain(m_storage.GetEncryptionKey(), hdChainCurrent))
|
if (!m_storage.WithEncryptionKey([&](const CKeyingMaterial& encryption_key) {
|
||||||
|
return DecryptHDChain(encryption_key, hdChainCurrent);
|
||||||
|
})) {
|
||||||
throw std::runtime_error(std::string(__func__) + ": DecryptHDChain failed");
|
throw std::runtime_error(std::string(__func__) + ": DecryptHDChain failed");
|
||||||
|
}
|
||||||
|
|
||||||
CExtKey masterKey;
|
CExtKey masterKey;
|
||||||
SecureVector vchSeed = hdChainCurrent.GetSeed();
|
SecureVector vchSeed = hdChainCurrent.GetSeed();
|
||||||
@ -474,8 +477,11 @@ bool LegacyScriptPubKeyMan::GetDecryptedHDChain(CHDChain& hdChainRet)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!DecryptHDChain(m_storage.GetEncryptionKey(), hdChainTmp))
|
if (!m_storage.WithEncryptionKey([&](const CKeyingMaterial& encryption_key) {
|
||||||
|
return DecryptHDChain(encryption_key, hdChainTmp);
|
||||||
|
})) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// make sure seed matches this chain
|
// make sure seed matches this chain
|
||||||
if (hdChainTmp.GetID() != hdChainTmp.GetSeedHash())
|
if (hdChainTmp.GetID() != hdChainTmp.GetSeedHash())
|
||||||
@ -911,7 +917,9 @@ bool LegacyScriptPubKeyMan::AddKeyPubKeyInner(const CKey& key, const CPubKey &pu
|
|||||||
|
|
||||||
std::vector<unsigned char> vchCryptedSecret;
|
std::vector<unsigned char> vchCryptedSecret;
|
||||||
CKeyingMaterial vchSecret(key.begin(), key.end());
|
CKeyingMaterial vchSecret(key.begin(), key.end());
|
||||||
if (!EncryptSecret(m_storage.GetEncryptionKey(), vchSecret, pubkey.GetHash(), vchCryptedSecret)) {
|
if (!m_storage.WithEncryptionKey([&](const CKeyingMaterial& encryption_key) {
|
||||||
|
return EncryptSecret(encryption_key, vchSecret, pubkey.GetHash(), vchCryptedSecret);
|
||||||
|
})) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -933,7 +941,9 @@ bool LegacyScriptPubKeyMan::GetKeyInner(const CKeyID &address, CKey& keyOut) con
|
|||||||
{
|
{
|
||||||
const CPubKey &vchPubKey = (*mi).second.first;
|
const CPubKey &vchPubKey = (*mi).second.first;
|
||||||
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
|
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
|
||||||
return DecryptKey(m_storage.GetEncryptionKey(), vchCryptedSecret, vchPubKey, keyOut);
|
return m_storage.WithEncryptionKey([&](const CKeyingMaterial& encryption_key) {
|
||||||
|
return DecryptKey(encryption_key, vchCryptedSecret, vchPubKey, keyOut);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1164,8 +1174,11 @@ bool LegacyScriptPubKeyMan::GetKey(const CKeyID &address, CKey& keyOut) const
|
|||||||
CHDChain hdChainCurrent;
|
CHDChain hdChainCurrent;
|
||||||
if (!GetHDChain(hdChainCurrent))
|
if (!GetHDChain(hdChainCurrent))
|
||||||
throw std::runtime_error(std::string(__func__) + ": GetHDChain failed");
|
throw std::runtime_error(std::string(__func__) + ": GetHDChain failed");
|
||||||
if (!DecryptHDChain(m_storage.GetEncryptionKey(), hdChainCurrent))
|
if (!m_storage.WithEncryptionKey([&](const CKeyingMaterial& encryption_key) {
|
||||||
|
return DecryptHDChain(encryption_key, hdChainCurrent);
|
||||||
|
})) {
|
||||||
throw std::runtime_error(std::string(__func__) + ": DecryptHDChain failed");
|
throw std::runtime_error(std::string(__func__) + ": DecryptHDChain failed");
|
||||||
|
}
|
||||||
// make sure seed matches this chain
|
// make sure seed matches this chain
|
||||||
if (hdChainCurrent.GetID() != hdChainCurrent.GetSeedHash())
|
if (hdChainCurrent.GetID() != hdChainCurrent.GetSeedHash())
|
||||||
throw std::runtime_error(std::string(__func__) + ": Wrong HD chain!");
|
throw std::runtime_error(std::string(__func__) + ": Wrong HD chain!");
|
||||||
@ -1276,8 +1289,11 @@ void LegacyScriptPubKeyMan::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata&
|
|||||||
throw std::runtime_error(std::string(__func__) + ": GetHDChain failed");
|
throw std::runtime_error(std::string(__func__) + ": GetHDChain failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!DecryptHDChain(m_storage.GetEncryptionKey(), hdChainTmp))
|
if (!m_storage.WithEncryptionKey([&](const CKeyingMaterial& encryption_key) {
|
||||||
|
return DecryptHDChain(encryption_key, hdChainTmp);
|
||||||
|
})) {
|
||||||
throw std::runtime_error(std::string(__func__) + ": DecryptHDChain failed");
|
throw std::runtime_error(std::string(__func__) + ": DecryptHDChain failed");
|
||||||
|
}
|
||||||
// make sure seed matches this chain
|
// make sure seed matches this chain
|
||||||
if (hdChainTmp.GetID() != hdChainTmp.GetSeedHash())
|
if (hdChainTmp.GetID() != hdChainTmp.GetSeedHash())
|
||||||
throw std::runtime_error(std::string(__func__) + ": Wrong HD chain!");
|
throw std::runtime_error(std::string(__func__) + ": Wrong HD chain!");
|
||||||
@ -1897,7 +1913,9 @@ std::map<CKeyID, CKey> DescriptorScriptPubKeyMan::GetKeys() const
|
|||||||
const CPubKey& pubkey = key_pair.second.first;
|
const CPubKey& pubkey = key_pair.second.first;
|
||||||
const std::vector<unsigned char>& crypted_secret = key_pair.second.second;
|
const std::vector<unsigned char>& crypted_secret = key_pair.second.second;
|
||||||
CKey key;
|
CKey key;
|
||||||
DecryptKey(m_storage.GetEncryptionKey(), crypted_secret, pubkey, key);
|
m_storage.WithEncryptionKey([&](const CKeyingMaterial& encryption_key) {
|
||||||
|
return DecryptKey(encryption_key, crypted_secret, pubkey, key);
|
||||||
|
});
|
||||||
keys[pubkey.GetID()] = key;
|
keys[pubkey.GetID()] = key;
|
||||||
}
|
}
|
||||||
return keys;
|
return keys;
|
||||||
@ -2010,7 +2028,9 @@ bool DescriptorScriptPubKeyMan::AddDescriptorKeyWithDB(WalletBatch& batch, const
|
|||||||
|
|
||||||
std::vector<unsigned char> crypted_secret;
|
std::vector<unsigned char> crypted_secret;
|
||||||
CKeyingMaterial secret(key.begin(), key.end());
|
CKeyingMaterial secret(key.begin(), key.end());
|
||||||
if (!EncryptSecret(m_storage.GetEncryptionKey(), secret, pubkey.GetHash(), crypted_secret)) {
|
if (!m_storage.WithEncryptionKey([&](const CKeyingMaterial& encryption_key) {
|
||||||
|
return EncryptSecret(encryption_key, secret, pubkey.GetHash(), crypted_secret);
|
||||||
|
})) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <boost/signals2/signal.hpp>
|
#include <boost/signals2/signal.hpp>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
// Wallet storage things that ScriptPubKeyMans need in order to be able to store things to the wallet database.
|
// Wallet storage things that ScriptPubKeyMans need in order to be able to store things to the wallet database.
|
||||||
@ -38,7 +39,8 @@ public:
|
|||||||
virtual void UnsetBlankWalletFlag(WalletBatch&) = 0;
|
virtual void UnsetBlankWalletFlag(WalletBatch&) = 0;
|
||||||
virtual bool CanSupportFeature(enum WalletFeature) const = 0;
|
virtual bool CanSupportFeature(enum WalletFeature) const = 0;
|
||||||
virtual void SetMinVersion(enum WalletFeature, WalletBatch* = nullptr) = 0;
|
virtual void SetMinVersion(enum WalletFeature, WalletBatch* = nullptr) = 0;
|
||||||
virtual const CKeyingMaterial& GetEncryptionKey() const = 0;
|
//! Pass the encryption key to cb().
|
||||||
|
virtual bool WithEncryptionKey(std::function<bool (const CKeyingMaterial&)> cb) const = 0;
|
||||||
virtual bool HasEncryptionKeys() const = 0;
|
virtual bool HasEncryptionKeys() const = 0;
|
||||||
virtual bool IsLocked(bool fForMixing) const = 0;
|
virtual bool IsLocked(bool fForMixing) const = 0;
|
||||||
|
|
||||||
@ -526,7 +528,7 @@ private:
|
|||||||
//! keeps track of whether Unlock has run a thorough check before
|
//! keeps track of whether Unlock has run a thorough check before
|
||||||
bool m_decryption_thoroughly_checked = false;
|
bool m_decryption_thoroughly_checked = false;
|
||||||
|
|
||||||
bool AddDescriptorKeyWithDB(WalletBatch& batch, const CKey& key, const CPubKey &pubkey);
|
bool AddDescriptorKeyWithDB(WalletBatch& batch, const CKey& key, const CPubKey &pubkey) EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
|
||||||
|
|
||||||
KeyMap GetKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
|
KeyMap GetKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
|
||||||
|
|
||||||
|
@ -3681,7 +3681,7 @@ bool CWallet::CreateTransactionInternal(
|
|||||||
txNew.vin.emplace_back(coin.outpoint, CScript(), CTxIn::SEQUENCE_FINAL - 1);
|
txNew.vin.emplace_back(coin.outpoint, CScript(), CTxIn::SEQUENCE_FINAL - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto calculateFee = [&](CAmount& nFee) -> bool {
|
auto calculateFee = [&](CAmount& nFee) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) -> bool {
|
||||||
AssertLockHeld(cs_wallet);
|
AssertLockHeld(cs_wallet);
|
||||||
nBytes = CalculateMaximumSignedTxSize(CTransaction(txNew), this, coin_control.fAllowWatchOnly);
|
nBytes = CalculateMaximumSignedTxSize(CTransaction(txNew), this, coin_control.fAllowWatchOnly);
|
||||||
if (nBytes < 0) {
|
if (nBytes < 0) {
|
||||||
@ -5743,9 +5743,10 @@ void CWallet::SetupLegacyScriptPubKeyMan()
|
|||||||
m_spk_managers[spk_manager->GetID()] = std::move(spk_manager);
|
m_spk_managers[spk_manager->GetID()] = std::move(spk_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
const CKeyingMaterial& CWallet::GetEncryptionKey() const
|
bool CWallet::WithEncryptionKey(std::function<bool (const CKeyingMaterial&)> cb) const
|
||||||
{
|
{
|
||||||
return vMasterKey;
|
LOCK(cs_wallet);
|
||||||
|
return cb(vMasterKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWallet::HasEncryptionKeys() const
|
bool CWallet::HasEncryptionKeys() const
|
||||||
|
@ -516,8 +516,12 @@ public:
|
|||||||
CAmount GetImmatureWatchOnlyCredit(const bool fUseCache = true) const;
|
CAmount GetImmatureWatchOnlyCredit(const bool fUseCache = true) const;
|
||||||
CAmount GetChange() const;
|
CAmount GetChange() const;
|
||||||
|
|
||||||
CAmount GetAnonymizedCredit(const CCoinControl* coinControl = nullptr) const;
|
// TODO: Remove "NO_THREAD_SAFETY_ANALYSIS" and replace it with the correct
|
||||||
CAmount GetDenominatedCredit(bool unconfirmed, bool fUseCache=true) const;
|
// annotation "EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)". The
|
||||||
|
// annotation "NO_THREAD_SAFETY_ANALYSIS" was temporarily added to avoid
|
||||||
|
// having to resolve the issue of member access into incomplete type CWallet.
|
||||||
|
CAmount GetAnonymizedCredit(const CCoinControl* coinControl = nullptr) const NO_THREAD_SAFETY_ANALYSIS;
|
||||||
|
CAmount GetDenominatedCredit(bool unconfirmed, bool fUseCache=true) const NO_THREAD_SAFETY_ANALYSIS;
|
||||||
|
|
||||||
/** Get the marginal bytes if spending the specified output from this transaction */
|
/** Get the marginal bytes if spending the specified output from this transaction */
|
||||||
int GetSpendSize(unsigned int out, bool use_max_sig = false) const
|
int GetSpendSize(unsigned int out, bool use_max_sig = false) const
|
||||||
@ -569,7 +573,7 @@ public:
|
|||||||
int GetDepthInMainChain() const NO_THREAD_SAFETY_ANALYSIS;
|
int GetDepthInMainChain() const NO_THREAD_SAFETY_ANALYSIS;
|
||||||
bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
|
bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
|
||||||
bool IsLockedByInstantSend() const;
|
bool IsLockedByInstantSend() const;
|
||||||
bool IsChainLocked() const;
|
bool IsChainLocked() const NO_THREAD_SAFETY_ANALYSIS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return number of blocks to maturity for this transaction:
|
* @return number of blocks to maturity for this transaction:
|
||||||
@ -1289,7 +1293,7 @@ public:
|
|||||||
std::set<uint256> GetConflicts(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
std::set<uint256> GetConflicts(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||||
|
|
||||||
//! Check if a given transaction has any of its outputs spent by another transaction in the wallet
|
//! Check if a given transaction has any of its outputs spent by another transaction in the wallet
|
||||||
bool HasWalletSpend(const uint256& txid) const;
|
bool HasWalletSpend(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||||
|
|
||||||
//! Flush wallet (bitdb flush)
|
//! Flush wallet (bitdb flush)
|
||||||
void Flush();
|
void Flush();
|
||||||
@ -1386,11 +1390,11 @@ public:
|
|||||||
void notifyChainLock(const CBlockIndex* pindexChainLock, const std::shared_ptr<const llmq::CChainLockSig>& clsig) override;
|
void notifyChainLock(const CBlockIndex* pindexChainLock, const std::shared_ptr<const llmq::CChainLockSig>& clsig) override;
|
||||||
|
|
||||||
/** Load a CGovernanceObject into m_gobjects. */
|
/** Load a CGovernanceObject into m_gobjects. */
|
||||||
bool LoadGovernanceObject(const Governance::Object& obj);
|
bool LoadGovernanceObject(const Governance::Object& obj) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||||
/** Store a CGovernanceObject in the wallet database. This should only be used by governance objects that are created by this wallet via `gobject prepare`. */
|
/** Store a CGovernanceObject in the wallet database. This should only be used by governance objects that are created by this wallet via `gobject prepare`. */
|
||||||
bool WriteGovernanceObject(const Governance::Object& obj);
|
bool WriteGovernanceObject(const Governance::Object& obj) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||||
/** Returns a vector containing pointers to the governance objects in m_gobjects */
|
/** Returns a vector containing pointers to the governance objects in m_gobjects */
|
||||||
std::vector<const Governance::Object*> GetGovernanceObjects();
|
std::vector<const Governance::Object*> GetGovernanceObjects() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Blocks until the wallet state is up-to-date to /at least/ the current
|
* Blocks until the wallet state is up-to-date to /at least/ the current
|
||||||
@ -1398,7 +1402,7 @@ public:
|
|||||||
* Obviously holding cs_main/cs_wallet when going into this call may cause
|
* Obviously holding cs_main/cs_wallet when going into this call may cause
|
||||||
* deadlock
|
* deadlock
|
||||||
*/
|
*/
|
||||||
void BlockUntilSyncedToCurrentChain() const LOCKS_EXCLUDED(cs_main, cs_wallet);
|
void BlockUntilSyncedToCurrentChain() const LOCKS_EXCLUDED(::cs_main) EXCLUSIVE_LOCKS_REQUIRED(!cs_wallet);
|
||||||
|
|
||||||
/** set a single wallet flag */
|
/** set a single wallet flag */
|
||||||
void SetWalletFlag(uint64_t flags);
|
void SetWalletFlag(uint64_t flags);
|
||||||
@ -1464,7 +1468,8 @@ public:
|
|||||||
//! Make a LegacyScriptPubKeyMan and set it for all types, internal, and external.
|
//! Make a LegacyScriptPubKeyMan and set it for all types, internal, and external.
|
||||||
void SetupLegacyScriptPubKeyMan();
|
void SetupLegacyScriptPubKeyMan();
|
||||||
|
|
||||||
const CKeyingMaterial& GetEncryptionKey() const override;
|
bool WithEncryptionKey(std::function<bool (const CKeyingMaterial&)> cb) const override;
|
||||||
|
|
||||||
bool HasEncryptionKeys() const override;
|
bool HasEncryptionKeys() const override;
|
||||||
|
|
||||||
/** Get last block processed height */
|
/** Get last block processed height */
|
||||||
@ -1510,7 +1515,7 @@ public:
|
|||||||
void DeactivateScriptPubKeyMan(uint256 id, bool internal);
|
void DeactivateScriptPubKeyMan(uint256 id, bool internal);
|
||||||
|
|
||||||
//! Create new DescriptorScriptPubKeyMans and add them to the wallet
|
//! Create new DescriptorScriptPubKeyMans and add them to the wallet
|
||||||
void SetupDescriptorScriptPubKeyMans();
|
void SetupDescriptorScriptPubKeyMans() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||||
|
|
||||||
//! Return the DescriptorScriptPubKeyMan for a WalletDescriptor if it is already in the wallet
|
//! Return the DescriptorScriptPubKeyMan for a WalletDescriptor if it is already in the wallet
|
||||||
DescriptorScriptPubKeyMan* GetDescriptorScriptPubKeyMan(const WalletDescriptor& desc) const;
|
DescriptorScriptPubKeyMan* GetDescriptorScriptPubKeyMan(const WalletDescriptor& desc) const;
|
||||||
|
Loading…
Reference in New Issue
Block a user