mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 03:52:49 +01:00
Merge #5940: refactor: consolidate activeMasternodeInfo{Cs} into CActiveMasternodeManager, create NodeContext alias, reduce globals usage
815e4f8026
masternode: protect m_{error,state} with cs (pasta)136e445abc
refactor: pass CActiveMasternodeManager as pointer arg to LLMQContext (Kittywhiskers Van Gogh)5e0f77747a
refactor: pass CActiveMasternodeManager as pointer arg to CJContext (Kittywhiskers Van Gogh)f171c24a29
refactor: add CActiveMasternodeManager NodeContext alias, use in RPC (Kittywhiskers Van Gogh)44beb941cb
refactor: prefix member variable names with m_ (Kittywhiskers Van Gogh)73cef4f5f9
refactor: make bls{Pub}KeyOperator member variables instead of pointers (Kittywhiskers Van Gogh)fbc783635a
refactor: make m_info private, get const refs (or copies) from Get*() functions (Kittywhiskers Van Gogh)1b516ce4ed
refactor: use signing helper function instead of passing blsKeyOperator (Kittywhiskers Van Gogh)33702aca39
refactor: add helper function to decrypt messages with blsKeyOperator (Kittywhiskers Van Gogh)3eb931b596
refactor: add helper function to sign messages with blsKeyOperator (Kittywhiskers Van Gogh)3827355cce
refactor: move key initialization to InitKeys, define destructor (Kittywhiskers Van Gogh)e5295dec1f
refactor: move activeMasternodeInfo{Cs} into CActiveMasternodeManager (Kittywhiskers Van Gogh)b8c1f010e7
refactor: avoid accessing active masternode info if not in masternode mode (Kittywhiskers Van Gogh)9a3c5a3c48
trivial: access activeMasternodeInfo when lock is in scope (Kittywhiskers Van Gogh) Pull request description: ## Additional Information * `CActiveMasternodeManager`, unlike other managers, is _conditionally_ initialized (specifically, when the node is hosting a masternode). This means that checks need to be made to ensure that the conditions needed to initialize the manager are true or that the pointer leads to a valid manager instance. As the codebase currently checks (and fast-fails) based on the node being in "masternode mode" (`fMasternodeMode`) or not, we will continue with this approach, but with additional assertions _after_ the masternode mode check if the manager exists. * Though, since `activeMasternodeInfo`(`Cs`) are global variables, they can be accessed _regardless_ of whether the corresponding manager exists. This means some parts of the codebase attempt to fetch information about the (nonexistent) active masternode _before_ determining if it should use the masternode mode path or not (looking at you, `CMNAuth::ProcessMessage`) Moving them into `CActiveMasternodeManager` meant adding checks _before_ attempting to access information about the masternode, as they would no longer be accessible with dummy values ([here](2110c0c309/src/init.cpp (L1633-L1635)
)) on account of being part of the conditionally initialized manager. * In an attempt to opportunistically dereference the manager, `CDKGSessionManager` (accepting a pointer) was dereferencing the manager before passing it to `CDKGSessionHandler`. This was done under the assumption that `CDKGSessionManager` would only ever be initialized in masternode mode. This is not true. I can confirm that because I spent a few days trying to debug test failures. `CDKGSessionHandler` is initialized in two scenarios: * In masternode mode * If the `-watchquorums` flag is enabled The latter scenario doesn't initialize `CActiveMasternodeManager`. Furthermore, the DKG round thread is started unconditionally ([here](2110c0c309/src/llmq/context.cpp (L79)
)) and the `CDKGSessionHandler::StartThreads` > `CDKGSessionHandler::StartThread` > `CDKGSessionHandler::PhaseHandlerThread` > `CDKGSessionHandler::HandleDKGRound` > `CDKGSessionHandler::InitNewQuorum` > `CActiveMasternodeManager::GetProTxHash` call chain reveals an attempt to fetch active masternode information without any masternode mode checks. This behaviour has now been changed and the thread will only be spun up if in masternode mode. * Dereferencing so far has been limited to objects that primarily hold data (like `CCoinJoinBroadcastTx` or `CGovernanceObject`) as they should not have knowledge of node's state (that responsibility lies with whatever manager manipulates those objects), perform one-off operations and static functions. * `activeMasternodeInfo` allowed its members to be read-write accessible to anybody who asked. Additionally, signing and decrypting involved borrowing the operator secret key from the active masternode state to perform those operations. This behaviour has now been changed. The internal state is now private and accessible read-only as a const ref (or copy) and `Decrypt`/`Sign` functions have been implemented to allow those operations to happen without having another manager access the operator private key in order to do so. * You cannot combine a `WITH_LOCK` and an `Assert` (in either mutex or accessed value), doing so will cause errors if `-Werror=thread-safety` is enabled. This is why `assert`s are added even when it would intuitively seem that `Assert` would've been more appropriate to use. ## Future Considerations Currently there are no unit tests that test the functionality of `CActiveMasternodeManager` as it's never initialized in test contexts, breakage had to be found using functional tests. Perhaps some (rudimentary) tests for `CActiveMasternodeManager` may prove to be valuable. ## Breaking Changes Not _really_. Some behaviour has been modified but nothing that should necessitate updates or upgrades. ## Checklist: - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas **(note: N/A)** - [x] I have added or updated relevant unit/integration/functional/e2e tests - [x] I have made corresponding changes to the documentation **(note: N/A)** - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ ACKs for top commit: PastaPastaPasta: utACK815e4f8026
Tree-SHA512: cbe49ea9e1c35df514e1b40869ee271baef1c348c9d09e4b356e5fc8fe5449cbbe66569258f2d664029faa9a46f711df9bf9e41eb8734c3aefc6cd8e94378948
This commit is contained in:
commit
f217e0ae7b
@ -47,12 +47,10 @@ uint256 CCoinJoinQueue::GetSignatureHash() const
|
||||
return SerializeHash(*this, SER_GETHASH, PROTOCOL_VERSION);
|
||||
}
|
||||
|
||||
bool CCoinJoinQueue::Sign()
|
||||
bool CCoinJoinQueue::Sign(const CActiveMasternodeManager& mn_activeman)
|
||||
{
|
||||
if (!fMasternodeMode) return false;
|
||||
|
||||
uint256 hash = GetSignatureHash();
|
||||
CBLSSignature sig = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.blsKeyOperator->Sign(hash, false));
|
||||
CBLSSignature sig = mn_activeman.Sign(hash, /*is_legacy=*/ false);
|
||||
if (!sig.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
@ -99,12 +97,10 @@ uint256 CCoinJoinBroadcastTx::GetSignatureHash() const
|
||||
return SerializeHash(*this, SER_GETHASH, PROTOCOL_VERSION);
|
||||
}
|
||||
|
||||
bool CCoinJoinBroadcastTx::Sign()
|
||||
bool CCoinJoinBroadcastTx::Sign(const CActiveMasternodeManager& mn_activeman)
|
||||
{
|
||||
if (!fMasternodeMode) return false;
|
||||
|
||||
uint256 hash = GetSignatureHash();
|
||||
CBLSSignature sig = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.blsKeyOperator->Sign(hash, false));
|
||||
CBLSSignature sig = mn_activeman.Sign(hash, /*is_legacy=*/ false);
|
||||
if (!sig.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
class CActiveMasternodeManager;
|
||||
class CChainState;
|
||||
class CConnman;
|
||||
class CBLSPublicKey;
|
||||
@ -213,7 +214,7 @@ public:
|
||||
* 3) we signed the message successfully, and
|
||||
* 4) we verified the message successfully
|
||||
*/
|
||||
bool Sign();
|
||||
bool Sign(const CActiveMasternodeManager& mn_activeman);
|
||||
/// Check if we have a valid Masternode address
|
||||
[[nodiscard]] bool CheckSignature(const CBLSPublicKey& blsPubKey) const;
|
||||
|
||||
@ -284,7 +285,7 @@ public:
|
||||
|
||||
[[nodiscard]] uint256 GetSignatureHash() const;
|
||||
|
||||
bool Sign();
|
||||
bool Sign(const CActiveMasternodeManager& mn_activeman);
|
||||
[[nodiscard]] bool CheckSignature(const CBLSPublicKey& blsPubKey) const;
|
||||
|
||||
void SetConfirmedHeight(std::optional<int> nConfirmedHeightIn) { assert(nConfirmedHeightIn == std::nullopt || *nConfirmedHeightIn > 0); nConfirmedHeight = nConfirmedHeightIn; }
|
||||
|
@ -14,13 +14,13 @@
|
||||
#include <coinjoin/server.h>
|
||||
|
||||
CJContext::CJContext(CChainState& chainstate, CConnman& connman, CDeterministicMNManager& dmnman, CTxMemPool& mempool,
|
||||
const CMasternodeSync& mn_sync, bool relay_txes) :
|
||||
const CActiveMasternodeManager* mn_activeman, const CMasternodeSync& mn_sync, bool relay_txes) :
|
||||
dstxman{std::make_unique<CDSTXManager>()},
|
||||
#ifdef ENABLE_WALLET
|
||||
walletman{std::make_unique<CoinJoinWalletManager>(connman, dmnman, mempool, mn_sync, queueman)},
|
||||
queueman {relay_txes ? std::make_unique<CCoinJoinClientQueueManager>(connman, *walletman, dmnman, mn_sync) : nullptr},
|
||||
#endif // ENABLE_WALLET
|
||||
server{std::make_unique<CCoinJoinServer>(chainstate, connman, dmnman, *dstxman, mempool, mn_sync)}
|
||||
server{std::make_unique<CCoinJoinServer>(chainstate, connman, dmnman, *dstxman, mempool, mn_activeman, mn_sync)}
|
||||
{}
|
||||
|
||||
CJContext::~CJContext() {}
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
class CActiveMasternodeManager;
|
||||
class CBlockPolicyEstimator;
|
||||
class CChainState;
|
||||
class CCoinJoinServer;
|
||||
@ -29,7 +30,7 @@ struct CJContext {
|
||||
CJContext() = delete;
|
||||
CJContext(const CJContext&) = delete;
|
||||
CJContext(CChainState& chainstate, CConnman& connman, CDeterministicMNManager& dmnman, CTxMemPool& mempool,
|
||||
const CMasternodeSync& mn_sync, bool relay_txes);
|
||||
const CActiveMasternodeManager* mn_activeman, const CMasternodeSync& mn_sync, bool relay_txes);
|
||||
~CJContext();
|
||||
|
||||
const std::unique_ptr<CDSTXManager> dstxman;
|
||||
|
@ -43,6 +43,8 @@ PeerMsgRet CCoinJoinServer::ProcessMessage(CNode& peer, std::string_view msg_typ
|
||||
|
||||
void CCoinJoinServer::ProcessDSACCEPT(CNode& peer, CDataStream& vRecv)
|
||||
{
|
||||
assert(m_mn_activeman);
|
||||
|
||||
if (IsSessionReady()) {
|
||||
// too many users in this session already, reject new ones
|
||||
LogPrint(BCLog::COINJOIN, "DSACCEPT -- queue is already full!\n");
|
||||
@ -56,7 +58,7 @@ void CCoinJoinServer::ProcessDSACCEPT(CNode& peer, CDataStream& vRecv)
|
||||
LogPrint(BCLog::COINJOIN, "DSACCEPT -- nDenom %d (%s) txCollateral %s", dsa.nDenom, CoinJoin::DenominationToString(dsa.nDenom), dsa.txCollateral.ToString()); /* Continued */
|
||||
|
||||
auto mnList = m_dmnman.GetListAtChainTip();
|
||||
auto dmn = WITH_LOCK(activeMasternodeInfoCs, return mnList.GetValidMNByCollateral(activeMasternodeInfo.outpoint));
|
||||
auto dmn = WITH_LOCK(m_mn_activeman->cs, return mnList.GetValidMNByCollateral(m_mn_activeman->GetOutPoint()));
|
||||
if (!dmn) {
|
||||
PushStatus(peer, STATUS_REJECTED, ERR_MN_LIST);
|
||||
return;
|
||||
@ -67,7 +69,7 @@ void CCoinJoinServer::ProcessDSACCEPT(CNode& peer, CDataStream& vRecv)
|
||||
TRY_LOCK(cs_vecqueue, lockRecv);
|
||||
if (!lockRecv) return;
|
||||
|
||||
auto mnOutpoint = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.outpoint);
|
||||
auto mnOutpoint = WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetOutPoint());
|
||||
|
||||
if (ranges::any_of(vecCoinJoinQueue,
|
||||
[&mnOutpoint](const auto& q){return q.masternodeOutpoint == mnOutpoint;})) {
|
||||
@ -308,6 +310,8 @@ void CCoinJoinServer::CommitFinalTransaction()
|
||||
AssertLockNotHeld(cs_coinjoin);
|
||||
if (!fMasternodeMode) return; // check and relay final tx only on masternode
|
||||
|
||||
assert(m_mn_activeman);
|
||||
|
||||
CTransactionRef finalTransaction = WITH_LOCK(cs_coinjoin, return MakeTransactionRef(finalMutableTransaction));
|
||||
uint256 hashTx = finalTransaction->GetHash();
|
||||
|
||||
@ -331,10 +335,10 @@ void CCoinJoinServer::CommitFinalTransaction()
|
||||
// create and sign masternode dstx transaction
|
||||
if (!m_dstxman.GetDSTX(hashTx)) {
|
||||
CCoinJoinBroadcastTx dstxNew(finalTransaction,
|
||||
WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.outpoint),
|
||||
WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash),
|
||||
WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetOutPoint()),
|
||||
WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash()),
|
||||
GetAdjustedTime());
|
||||
dstxNew.Sign();
|
||||
dstxNew.Sign(*m_mn_activeman);
|
||||
m_dstxman.AddDSTX(dstxNew);
|
||||
}
|
||||
|
||||
@ -495,16 +499,18 @@ void CCoinJoinServer::CheckForCompleteQueue()
|
||||
{
|
||||
if (!fMasternodeMode) return;
|
||||
|
||||
assert(m_mn_activeman);
|
||||
|
||||
if (nState == POOL_STATE_QUEUE && IsSessionReady()) {
|
||||
SetState(POOL_STATE_ACCEPTING_ENTRIES);
|
||||
|
||||
CCoinJoinQueue dsq(nSessionDenom,
|
||||
WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.outpoint),
|
||||
WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash),
|
||||
WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetOutPoint()),
|
||||
WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash()),
|
||||
GetAdjustedTime(), true);
|
||||
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::CheckForCompleteQueue -- queue is ready, signing and relaying (%s) " /* Continued */
|
||||
"with %d participants\n", dsq.ToString(), vecSessionCollaterals.size());
|
||||
dsq.Sign();
|
||||
dsq.Sign(*m_mn_activeman);
|
||||
dsq.Relay(connman);
|
||||
}
|
||||
}
|
||||
@ -692,6 +698,8 @@ bool CCoinJoinServer::CreateNewSession(const CCoinJoinAccept& dsa, PoolMessage&
|
||||
{
|
||||
if (!fMasternodeMode || nSessionID != 0) return false;
|
||||
|
||||
assert(m_mn_activeman);
|
||||
|
||||
// new session can only be started in idle mode
|
||||
if (nState != POOL_STATE_IDLE) {
|
||||
nMessageIDRet = ERR_MODE;
|
||||
@ -713,11 +721,11 @@ bool CCoinJoinServer::CreateNewSession(const CCoinJoinAccept& dsa, PoolMessage&
|
||||
if (!fUnitTest) {
|
||||
//broadcast that I'm accepting entries, only if it's the first entry through
|
||||
CCoinJoinQueue dsq(nSessionDenom,
|
||||
WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.outpoint),
|
||||
WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash),
|
||||
WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetOutPoint()),
|
||||
WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash()),
|
||||
GetAdjustedTime(), false);
|
||||
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::CreateNewSession -- signing and relaying new queue: %s\n", dsq.ToString());
|
||||
dsq.Sign();
|
||||
dsq.Sign(*m_mn_activeman);
|
||||
dsq.Relay(connman);
|
||||
LOCK(cs_vecqueue);
|
||||
vecCoinJoinQueue.push_back(dsq);
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include <net_types.h>
|
||||
|
||||
class CActiveMasternodeManager;
|
||||
class CChainState;
|
||||
class CCoinJoinServer;
|
||||
class CDataStream;
|
||||
@ -29,6 +30,7 @@ private:
|
||||
CDeterministicMNManager& m_dmnman;
|
||||
CDSTXManager& m_dstxman;
|
||||
CTxMemPool& mempool;
|
||||
const CActiveMasternodeManager* m_mn_activeman;
|
||||
const CMasternodeSync& m_mn_sync;
|
||||
|
||||
// Mixing uses collateral transactions to trust parties entering the pool
|
||||
@ -85,12 +87,13 @@ private:
|
||||
|
||||
public:
|
||||
explicit CCoinJoinServer(CChainState& chainstate, CConnman& _connman, CDeterministicMNManager& dmnman, CDSTXManager& dstxman,
|
||||
CTxMemPool& mempool, const CMasternodeSync& mn_sync) :
|
||||
CTxMemPool& mempool, const CActiveMasternodeManager* mn_activeman, const CMasternodeSync& mn_sync) :
|
||||
m_chainstate(chainstate),
|
||||
connman(_connman),
|
||||
m_dmnman(dmnman),
|
||||
m_dstxman(dstxman),
|
||||
mempool(mempool),
|
||||
m_mn_activeman(mn_activeman),
|
||||
m_mn_sync(mn_sync),
|
||||
vecSessionCollaterals(),
|
||||
fUnitTest(false)
|
||||
|
@ -21,12 +21,16 @@
|
||||
|
||||
void CMNAuth::PushMNAUTH(CNode& peer, CConnman& connman, const CBlockIndex* tip)
|
||||
{
|
||||
LOCK(activeMasternodeInfoCs);
|
||||
if (!fMasternodeMode || activeMasternodeInfo.proTxHash.IsNull()) {
|
||||
if (!fMasternodeMode) return;
|
||||
|
||||
CMNAuth mnauth;
|
||||
uint256 signHash;
|
||||
{
|
||||
LOCK(::activeMasternodeManager->cs);
|
||||
if (::activeMasternodeManager->GetProTxHash().IsNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint256 signHash;
|
||||
const auto receivedMNAuthChallenge = peer.GetReceivedMNAuthChallenge();
|
||||
if (receivedMNAuthChallenge.IsNull()) {
|
||||
return;
|
||||
@ -42,19 +46,20 @@ void CMNAuth::PushMNAUTH(CNode& peer, CConnman& connman, const CBlockIndex* tip)
|
||||
nOurNodeVersion = gArgs.GetArg("-pushversion", PROTOCOL_VERSION);
|
||||
}
|
||||
const bool is_basic_scheme_active{DeploymentActiveAfter(tip, Params().GetConsensus(), Consensus::DEPLOYMENT_V19)};
|
||||
const CBLSPublicKeyVersionWrapper pubKey(*activeMasternodeInfo.blsPubKeyOperator, !is_basic_scheme_active);
|
||||
auto pk = ::activeMasternodeManager->GetPubKey();
|
||||
const CBLSPublicKeyVersionWrapper pubKey(pk, !is_basic_scheme_active);
|
||||
if (peer.nVersion < MNAUTH_NODE_VER_VERSION || nOurNodeVersion < MNAUTH_NODE_VER_VERSION) {
|
||||
signHash = ::SerializeHash(std::make_tuple(pubKey, receivedMNAuthChallenge, peer.IsInboundConn()));
|
||||
} else {
|
||||
signHash = ::SerializeHash(std::make_tuple(pubKey, receivedMNAuthChallenge, peer.IsInboundConn(), nOurNodeVersion));
|
||||
}
|
||||
|
||||
CMNAuth mnauth;
|
||||
mnauth.proRegTxHash = activeMasternodeInfo.proTxHash;
|
||||
mnauth.sig = activeMasternodeInfo.blsKeyOperator->Sign(signHash);
|
||||
mnauth.proRegTxHash = ::activeMasternodeManager->GetProTxHash();
|
||||
} // ::activeMasternodeManager->cs
|
||||
|
||||
mnauth.sig = ::activeMasternodeManager->Sign(signHash);
|
||||
|
||||
LogPrint(BCLog::NET_NETCONN, "CMNAuth::%s -- Sending MNAUTH, peer=%d\n", __func__, peer.GetId());
|
||||
|
||||
connman.PushMessage(&peer, CNetMsgMaker(peer.GetCommonVersion()).Make(NetMsgType::MNAUTH, mnauth));
|
||||
}
|
||||
|
||||
@ -127,7 +132,9 @@ PeerMsgRet CMNAuth::ProcessMessage(CNode& peer, CConnman& connman, const CDeterm
|
||||
}
|
||||
}
|
||||
|
||||
const uint256 myProTxHash = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash);
|
||||
const uint256 myProTxHash = fMasternodeMode ?
|
||||
WITH_LOCK(::activeMasternodeManager->cs, return ::activeMasternodeManager->GetProTxHash()) :
|
||||
uint256();
|
||||
|
||||
connman.ForEachNode([&](CNode* pnode2) {
|
||||
if (peer.fDisconnect) {
|
||||
|
@ -692,14 +692,14 @@ std::optional<const CGovernanceObject> CGovernanceManager::CreateGovernanceTrigg
|
||||
}
|
||||
|
||||
{
|
||||
LOCK(activeMasternodeInfoCs);
|
||||
if (mn_payees.front()->proTxHash != activeMasternodeInfo.proTxHash) {
|
||||
LOCK(::activeMasternodeManager->cs);
|
||||
if (mn_payees.front()->proTxHash != ::activeMasternodeManager->GetProTxHash()) {
|
||||
LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s we are not the payee, skipping\n", __func__);
|
||||
return std::nullopt;
|
||||
}
|
||||
gov_sb.SetMasternodeOutpoint(activeMasternodeInfo.outpoint);
|
||||
gov_sb.Sign( *activeMasternodeInfo.blsKeyOperator);
|
||||
} // activeMasternodeInfoCs
|
||||
gov_sb.SetMasternodeOutpoint(::activeMasternodeManager->GetOutPoint());
|
||||
} // ::activeMasternodeManager->cs
|
||||
gov_sb.Sign(*::activeMasternodeManager);
|
||||
|
||||
if (std::string strError; !gov_sb.IsValidLocally(m_dmnman->GetListAtChainTip(), strError, true)) {
|
||||
LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s Created trigger is invalid:%s\n", __func__, strError);
|
||||
@ -719,7 +719,8 @@ std::optional<const CGovernanceObject> CGovernanceManager::CreateGovernanceTrigg
|
||||
void CGovernanceManager::VoteGovernanceTriggers(const std::optional<const CGovernanceObject>& trigger_opt, CConnman& connman)
|
||||
{
|
||||
// only active masternodes can vote on triggers
|
||||
if (!fMasternodeMode || WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash.IsNull())) return;
|
||||
if (!fMasternodeMode) return;
|
||||
if (WITH_LOCK(::activeMasternodeManager->cs, return ::activeMasternodeManager->GetProTxHash().IsNull())) return;
|
||||
|
||||
LOCK2(cs_main, cs);
|
||||
|
||||
@ -762,9 +763,9 @@ void CGovernanceManager::VoteGovernanceTriggers(const std::optional<const CGover
|
||||
|
||||
bool CGovernanceManager::VoteFundingTrigger(const uint256& nHash, const vote_outcome_enum_t outcome, CConnman& connman)
|
||||
{
|
||||
CGovernanceVote vote(WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.outpoint), nHash, VOTE_SIGNAL_FUNDING, outcome);
|
||||
CGovernanceVote vote(WITH_LOCK(::activeMasternodeManager->cs, return ::activeMasternodeManager->GetOutPoint()), nHash, VOTE_SIGNAL_FUNDING, outcome);
|
||||
vote.SetTime(GetAdjustedTime());
|
||||
vote.Sign(WITH_LOCK(activeMasternodeInfoCs, return *activeMasternodeInfo.blsKeyOperator));
|
||||
vote.Sign(*::activeMasternodeManager);
|
||||
|
||||
CGovernanceException exception;
|
||||
if (!ProcessVoteAndRelay(vote, exception, connman)) {
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <governance/governance.h>
|
||||
#include <governance/validators.h>
|
||||
#include <masternode/meta.h>
|
||||
#include <masternode/node.h>
|
||||
#include <masternode/sync.h>
|
||||
#include <messagesigner.h>
|
||||
#include <net.h>
|
||||
@ -273,9 +274,9 @@ void CGovernanceObject::SetMasternodeOutpoint(const COutPoint& outpoint)
|
||||
m_obj.masternodeOutpoint = outpoint;
|
||||
}
|
||||
|
||||
bool CGovernanceObject::Sign(const CBLSSecretKey& key)
|
||||
bool CGovernanceObject::Sign(const CActiveMasternodeManager& mn_activeman)
|
||||
{
|
||||
CBLSSignature sig = key.Sign(GetSignatureHash(), false);
|
||||
CBLSSignature sig = mn_activeman.Sign(GetSignatureHash(), false);
|
||||
if (!sig.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#include <univalue.h>
|
||||
|
||||
class CBLSSecretKey;
|
||||
class CActiveMasternodeManager;
|
||||
class CBLSPublicKey;
|
||||
class CDeterministicMNList;
|
||||
class CGovernanceManager;
|
||||
@ -217,7 +217,7 @@ public:
|
||||
// Signature related functions
|
||||
|
||||
void SetMasternodeOutpoint(const COutPoint& outpoint);
|
||||
bool Sign(const CBLSSecretKey& key);
|
||||
bool Sign(const CActiveMasternodeManager& mn_activeman);
|
||||
bool CheckSignature(const CBLSPublicKey& pubKey) const;
|
||||
|
||||
uint256 GetSignatureHash() const;
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <bls/bls.h>
|
||||
#include <chainparams.h>
|
||||
#include <key.h>
|
||||
#include <masternode/node.h>
|
||||
#include <masternode/sync.h>
|
||||
#include <messagesigner.h>
|
||||
#include <net.h>
|
||||
@ -221,9 +222,9 @@ bool CGovernanceVote::CheckSignature(const CKeyID& keyID) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGovernanceVote::Sign(const CBLSSecretKey& key)
|
||||
bool CGovernanceVote::Sign(const CActiveMasternodeManager& mn_activeman)
|
||||
{
|
||||
CBLSSignature sig = key.Sign(GetSignatureHash(), false);
|
||||
CBLSSignature sig = mn_activeman.Sign(GetSignatureHash(), false);
|
||||
if (!sig.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -8,11 +8,11 @@
|
||||
#include <primitives/transaction.h>
|
||||
#include <uint256.h>
|
||||
|
||||
class CGovernanceVote;
|
||||
class CActiveMasternodeManager;
|
||||
class CBLSPublicKey;
|
||||
class CBLSSecretKey;
|
||||
class CConnman;
|
||||
class CDeterministicMNList;
|
||||
class CGovernanceVote;
|
||||
class CKey;
|
||||
class CKeyID;
|
||||
|
||||
@ -101,7 +101,7 @@ public:
|
||||
|
||||
bool Sign(const CKey& key, const CKeyID& keyID);
|
||||
bool CheckSignature(const CKeyID& keyID) const;
|
||||
bool Sign(const CBLSSecretKey& key);
|
||||
bool Sign(const CActiveMasternodeManager& mn_activeman);
|
||||
bool CheckSignature(const CBLSPublicKey& pubKey) const;
|
||||
bool IsValid(const CDeterministicMNList& tip_mn_list, bool useVotingKey) const;
|
||||
void Relay(CConnman& connman, const CDeterministicMNList& tip_mn_list) const;
|
||||
|
58
src/init.cpp
58
src/init.cpp
@ -369,15 +369,9 @@ void PrepareShutdown(NodeContext& node)
|
||||
pdsNotificationInterface = nullptr;
|
||||
}
|
||||
if (fMasternodeMode) {
|
||||
UnregisterValidationInterface(activeMasternodeManager.get());
|
||||
activeMasternodeManager.reset();
|
||||
}
|
||||
|
||||
{
|
||||
LOCK(activeMasternodeInfoCs);
|
||||
// make sure to clean up BLS keys before global destructors are called (they have allocated from the secure memory pool)
|
||||
activeMasternodeInfo.blsKeyOperator.reset();
|
||||
activeMasternodeInfo.blsPubKeyOperator.reset();
|
||||
UnregisterValidationInterface(node.mn_activeman);
|
||||
node.mn_activeman = nullptr;
|
||||
::activeMasternodeManager.reset();
|
||||
}
|
||||
|
||||
node.chain_clients.clear();
|
||||
@ -1606,31 +1600,6 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
|
||||
StartScriptCheckWorkerThreads(script_threads);
|
||||
}
|
||||
|
||||
assert(activeMasternodeInfo.blsKeyOperator == nullptr);
|
||||
assert(activeMasternodeInfo.blsPubKeyOperator == nullptr);
|
||||
fMasternodeMode = false;
|
||||
std::string strMasterNodeBLSPrivKey = args.GetArg("-masternodeblsprivkey", "");
|
||||
if (!strMasterNodeBLSPrivKey.empty()) {
|
||||
CBLSSecretKey keyOperator(ParseHex(strMasterNodeBLSPrivKey));
|
||||
if (!keyOperator.IsValid()) {
|
||||
return InitError(_("Invalid masternodeblsprivkey. Please see documentation."));
|
||||
}
|
||||
fMasternodeMode = true;
|
||||
{
|
||||
LOCK(activeMasternodeInfoCs);
|
||||
activeMasternodeInfo.blsKeyOperator = std::make_unique<CBLSSecretKey>(keyOperator);
|
||||
activeMasternodeInfo.blsPubKeyOperator = std::make_unique<CBLSPublicKey>(keyOperator.GetPublicKey());
|
||||
}
|
||||
// We don't know the actual scheme at this point, print both
|
||||
LogPrintf("MASTERNODE:\n blsPubKeyOperator legacy: %s\n blsPubKeyOperator basic: %s\n",
|
||||
activeMasternodeInfo.blsPubKeyOperator->ToString(true),
|
||||
activeMasternodeInfo.blsPubKeyOperator->ToString(false));
|
||||
} else {
|
||||
LOCK(activeMasternodeInfoCs);
|
||||
activeMasternodeInfo.blsKeyOperator = std::make_unique<CBLSSecretKey>();
|
||||
activeMasternodeInfo.blsPubKeyOperator = std::make_unique<CBLSPublicKey>();
|
||||
}
|
||||
|
||||
assert(!node.scheduler);
|
||||
node.scheduler = std::make_unique<CScheduler>();
|
||||
|
||||
@ -1875,10 +1844,20 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
|
||||
);
|
||||
RegisterValidationInterface(pdsNotificationInterface);
|
||||
|
||||
if (fMasternodeMode) {
|
||||
fMasternodeMode = false;
|
||||
std::string strMasterNodeBLSPrivKey = args.GetArg("-masternodeblsprivkey", "");
|
||||
if (!strMasterNodeBLSPrivKey.empty()) {
|
||||
CBLSSecretKey keyOperator(ParseHex(strMasterNodeBLSPrivKey));
|
||||
if (!keyOperator.IsValid()) {
|
||||
return InitError(_("Invalid masternodeblsprivkey. Please see documentation."));
|
||||
}
|
||||
fMasternodeMode = true;
|
||||
{
|
||||
// Create and register activeMasternodeManager, will init later in ThreadImport
|
||||
activeMasternodeManager = std::make_unique<CActiveMasternodeManager>(*node.connman, ::deterministicMNManager);
|
||||
RegisterValidationInterface(activeMasternodeManager.get());
|
||||
::activeMasternodeManager = std::make_unique<CActiveMasternodeManager>(keyOperator, *node.connman, ::deterministicMNManager);
|
||||
node.mn_activeman = ::activeMasternodeManager.get();
|
||||
RegisterValidationInterface(node.mn_activeman);
|
||||
}
|
||||
}
|
||||
|
||||
// ********************************************************* Step 7a: Load sporks
|
||||
@ -1975,7 +1954,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
|
||||
node.llmq_ctx->Stop();
|
||||
}
|
||||
node.llmq_ctx.reset();
|
||||
node.llmq_ctx.reset(new LLMQContext(chainman.ActiveChainstate(), *node.connman, *node.dmnman, *node.evodb, *node.mnhf_manager, *node.sporkman, *node.mempool, node.peerman, false, fReset || fReindexChainState));
|
||||
node.llmq_ctx.reset(new LLMQContext(chainman.ActiveChainstate(), *node.connman, *node.dmnman, *node.evodb, *node.mnhf_manager, *node.sporkman, *node.mempool, node.mn_activeman, node.peerman, false, fReset || fReindexChainState));
|
||||
// Have to start it early to let VerifyDB check ChainLock signatures in coinbase
|
||||
node.llmq_ctx->Start();
|
||||
|
||||
@ -2220,7 +2199,8 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
|
||||
|
||||
// ********************************************************* Step 7c: Setup CoinJoin
|
||||
|
||||
node.cj_ctx = std::make_unique<CJContext>(chainman.ActiveChainstate(), *node.connman, *node.dmnman, *node.mempool, *node.mn_sync, !ignores_incoming_txs);
|
||||
node.cj_ctx = std::make_unique<CJContext>(chainman.ActiveChainstate(), *node.connman, *node.dmnman, *node.mempool, node.mn_activeman,
|
||||
*node.mn_sync, !ignores_incoming_txs);
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
node.coinjoin_loader = interfaces::MakeCoinJoinLoader(*node.cj_ctx->walletman);
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <masternode/sync.h>
|
||||
|
||||
LLMQContext::LLMQContext(CChainState& chainstate, CConnman& connman, CDeterministicMNManager& dmnman, CEvoDB& evo_db,
|
||||
CMNHFManager& mnhfman, CSporkManager& sporkman, CTxMemPool& mempool,
|
||||
CMNHFManager& mnhfman, CSporkManager& sporkman, CTxMemPool& mempool, const CActiveMasternodeManager* mn_activeman,
|
||||
const std::unique_ptr<PeerManager>& peerman, bool unit_tests, bool wipe) :
|
||||
bls_worker{std::make_shared<CBLSWorker>()},
|
||||
dkg_debugman{std::make_unique<llmq::CDKGDebugManager>()},
|
||||
@ -29,14 +29,14 @@ LLMQContext::LLMQContext(CChainState& chainstate, CConnman& connman, CDeterminis
|
||||
llmq::quorumBlockProcessor = std::make_unique<llmq::CQuorumBlockProcessor>(chainstate, connman, dmnman, evo_db);
|
||||
return llmq::quorumBlockProcessor.get();
|
||||
}()},
|
||||
qdkgsman{std::make_unique<llmq::CDKGSessionManager>(*bls_worker, chainstate, connman, dmnman, *dkg_debugman, *quorum_block_processor, sporkman, unit_tests, wipe)},
|
||||
qdkgsman{std::make_unique<llmq::CDKGSessionManager>(*bls_worker, chainstate, connman, dmnman, *dkg_debugman, *quorum_block_processor, mn_activeman, sporkman, unit_tests, wipe)},
|
||||
qman{[&]() -> llmq::CQuorumManager* const {
|
||||
assert(llmq::quorumManager == nullptr);
|
||||
llmq::quorumManager = std::make_unique<llmq::CQuorumManager>(*bls_worker, chainstate, connman, dmnman, *qdkgsman, evo_db, *quorum_block_processor, sporkman, ::masternodeSync);
|
||||
llmq::quorumManager = std::make_unique<llmq::CQuorumManager>(*bls_worker, chainstate, connman, dmnman, *qdkgsman, evo_db, *quorum_block_processor, mn_activeman, sporkman, ::masternodeSync);
|
||||
return llmq::quorumManager.get();
|
||||
}()},
|
||||
sigman{std::make_unique<llmq::CSigningManager>(connman, *llmq::quorumManager, unit_tests, wipe)},
|
||||
shareman{std::make_unique<llmq::CSigSharesManager>(connman, *sigman, *llmq::quorumManager, sporkman, peerman)},
|
||||
sigman{std::make_unique<llmq::CSigningManager>(connman, mn_activeman, *llmq::quorumManager, unit_tests, wipe)},
|
||||
shareman{std::make_unique<llmq::CSigSharesManager>(connman, *sigman, mn_activeman, *llmq::quorumManager, sporkman, peerman)},
|
||||
clhandler{[&]() -> llmq::CChainLocksHandler* const {
|
||||
assert(llmq::chainLocksHandler == nullptr);
|
||||
llmq::chainLocksHandler = std::make_unique<llmq::CChainLocksHandler>(chainstate, connman, *::masternodeSync, *llmq::quorumManager, *sigman, *shareman, sporkman, mempool);
|
||||
@ -77,7 +77,9 @@ void LLMQContext::Start() {
|
||||
assert(isman == llmq::quorumInstantSendManager.get());
|
||||
|
||||
bls_worker->Start();
|
||||
if (fMasternodeMode) {
|
||||
qdkgsman->StartThreads();
|
||||
}
|
||||
qman->Start();
|
||||
shareman->RegisterAsRecoveredSigsListener();
|
||||
shareman->StartWorkerThread();
|
||||
@ -100,6 +102,8 @@ void LLMQContext::Stop() {
|
||||
shareman->UnregisterAsRecoveredSigsListener();
|
||||
sigman->StopWorkerThread();
|
||||
qman->Stop();
|
||||
if (fMasternodeMode) {
|
||||
qdkgsman->StopThreads();
|
||||
}
|
||||
bls_worker->Stop();
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
class CActiveMasternodeManager;
|
||||
class CBLSWorker;
|
||||
class CChainState;
|
||||
class CConnman;
|
||||
@ -34,7 +35,7 @@ struct LLMQContext {
|
||||
LLMQContext() = delete;
|
||||
LLMQContext(const LLMQContext&) = delete;
|
||||
LLMQContext(CChainState& chainstate, CConnman& connman, CDeterministicMNManager& dmnman, CEvoDB& evo_db,
|
||||
CMNHFManager& mnhfman, CSporkManager& sporkman, CTxMemPool& mempool,
|
||||
CMNHFManager& mnhfman, CSporkManager& sporkman, CTxMemPool& mempool, const CActiveMasternodeManager* mn_activeman,
|
||||
const std::unique_ptr<PeerManager>& peerman, bool unit_tests, bool wipe);
|
||||
~LLMQContext();
|
||||
|
||||
|
@ -199,7 +199,7 @@ void CDKGSession::SendContributions(CDKGPendingMessages& pendingMessages)
|
||||
|
||||
logger.Batch("encrypted contributions. time=%d", t1.count());
|
||||
|
||||
qc.sig = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.blsKeyOperator->Sign(qc.GetSignHash()));
|
||||
qc.sig = m_mn_activeman->Sign(qc.GetSignHash());
|
||||
|
||||
logger.Flush();
|
||||
|
||||
@ -316,7 +316,7 @@ void CDKGSession::ReceiveMessage(const CDKGContribution& qc, bool& retBan)
|
||||
|
||||
bool complain = false;
|
||||
CBLSSecretKey skContribution;
|
||||
if (!qc.contributions->Decrypt(*myIdx, WITH_LOCK(activeMasternodeInfoCs, return *activeMasternodeInfo.blsKeyOperator), skContribution, PROTOCOL_VERSION)) {
|
||||
if (!m_mn_activeman->Decrypt(*qc.contributions, *myIdx, skContribution, PROTOCOL_VERSION)) {
|
||||
logger.Batch("contribution from %s could not be decrypted", member->dmn->proTxHash.ToString());
|
||||
complain = true;
|
||||
} else if (member->idx != myIdx && ShouldSimulateError(DKGError::type::COMPLAIN_LIE)) {
|
||||
@ -517,7 +517,7 @@ void CDKGSession::SendComplaint(CDKGPendingMessages& pendingMessages)
|
||||
|
||||
logger.Batch("sending complaint. badCount=%d, complaintCount=%d", badCount, complaintCount);
|
||||
|
||||
qc.sig = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.blsKeyOperator->Sign(qc.GetSignHash()));
|
||||
qc.sig = m_mn_activeman->Sign(qc.GetSignHash());
|
||||
|
||||
logger.Flush();
|
||||
|
||||
@ -711,7 +711,7 @@ void CDKGSession::SendJustification(CDKGPendingMessages& pendingMessages, const
|
||||
return;
|
||||
}
|
||||
|
||||
qj.sig = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.blsKeyOperator->Sign(qj.GetSignHash()));
|
||||
qj.sig = m_mn_activeman->Sign(qj.GetSignHash());
|
||||
|
||||
logger.Flush();
|
||||
|
||||
@ -1003,7 +1003,7 @@ void CDKGSession::SendCommitment(CDKGPendingMessages& pendingMessages)
|
||||
(*commitmentHash.begin())++;
|
||||
}
|
||||
|
||||
qc.sig = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.blsKeyOperator->Sign(commitmentHash));
|
||||
qc.sig = m_mn_activeman->Sign(commitmentHash);
|
||||
qc.quorumSig = skShare.Sign(commitmentHash);
|
||||
|
||||
if (lieType == 3) {
|
||||
|
@ -15,11 +15,13 @@
|
||||
|
||||
#include <optional>
|
||||
|
||||
class UniValue;
|
||||
class CActiveMasternodeManager;
|
||||
class CInv;
|
||||
class CConnman;
|
||||
class CDeterministicMN;
|
||||
class CSporkManager;
|
||||
class UniValue;
|
||||
|
||||
using CDeterministicMNCPtr = std::shared_ptr<const CDeterministicMN>;
|
||||
|
||||
namespace llmq
|
||||
@ -273,6 +275,7 @@ private:
|
||||
CDeterministicMNManager& m_dmnman;
|
||||
CDKGSessionManager& dkgManager;
|
||||
CDKGDebugManager& dkgDebugManager;
|
||||
const CActiveMasternodeManager* m_mn_activeman;
|
||||
const CSporkManager& m_sporkman;
|
||||
|
||||
const CBlockIndex* m_quorum_base_block_index{nullptr};
|
||||
@ -314,8 +317,11 @@ private:
|
||||
std::set<uint256> validCommitments GUARDED_BY(invCs);
|
||||
|
||||
public:
|
||||
CDKGSession(const Consensus::LLMQParams& _params, CBLSWorker& _blsWorker, CDeterministicMNManager& dmnman, CDKGSessionManager& _dkgManager, CDKGDebugManager& _dkgDebugManager, CConnman& _connman, const CSporkManager& sporkman) :
|
||||
params(_params), blsWorker(_blsWorker), cache(_blsWorker), m_dmnman(dmnman), dkgManager(_dkgManager), dkgDebugManager(_dkgDebugManager), m_sporkman(sporkman), connman(_connman) {}
|
||||
CDKGSession(const Consensus::LLMQParams& _params, CBLSWorker& _blsWorker, CDeterministicMNManager& dmnman,
|
||||
CDKGSessionManager& _dkgManager, CDKGDebugManager& _dkgDebugManager, CConnman& _connman,
|
||||
const CActiveMasternodeManager* mn_activeman, const CSporkManager& sporkman) :
|
||||
params(_params), blsWorker(_blsWorker), cache(_blsWorker), m_dmnman(dmnman), dkgManager(_dkgManager),
|
||||
dkgDebugManager(_dkgDebugManager), m_mn_activeman(mn_activeman), m_sporkman(sporkman), connman(_connman) {}
|
||||
|
||||
bool Init(gsl::not_null<const CBlockIndex*> pQuorumBaseBlockIndex, Span<CDeterministicMNCPtr> mns, const uint256& _myProTxHash, int _quorumIndex);
|
||||
|
||||
|
@ -26,7 +26,8 @@ namespace llmq
|
||||
|
||||
CDKGSessionHandler::CDKGSessionHandler(CBLSWorker& _blsWorker, CChainState& chainstate, CConnman& _connman, CDeterministicMNManager& dmnman,
|
||||
CDKGDebugManager& _dkgDebugManager, CDKGSessionManager& _dkgManager, CQuorumBlockProcessor& _quorumBlockProcessor,
|
||||
const CSporkManager& sporkman, const Consensus::LLMQParams& _params, int _quorumIndex) :
|
||||
const CActiveMasternodeManager* mn_activeman, const CSporkManager& sporkman, const Consensus::LLMQParams& _params,
|
||||
int _quorumIndex) :
|
||||
blsWorker(_blsWorker),
|
||||
m_chainstate(chainstate),
|
||||
connman(_connman),
|
||||
@ -34,10 +35,11 @@ CDKGSessionHandler::CDKGSessionHandler(CBLSWorker& _blsWorker, CChainState& chai
|
||||
dkgDebugManager(_dkgDebugManager),
|
||||
dkgManager(_dkgManager),
|
||||
quorumBlockProcessor(_quorumBlockProcessor),
|
||||
m_mn_activeman(mn_activeman),
|
||||
m_sporkman(sporkman),
|
||||
params(_params),
|
||||
quorumIndex(_quorumIndex),
|
||||
curSession(std::make_unique<CDKGSession>(_params, _blsWorker, dmnman, _dkgManager, _dkgDebugManager, _connman, sporkman)),
|
||||
curSession(std::make_unique<CDKGSession>(_params, _blsWorker, dmnman, _dkgManager, _dkgDebugManager, _connman, m_mn_activeman, sporkman)),
|
||||
pendingContributions((size_t)_params.size * 2, MSG_QUORUM_CONTRIB), // we allow size*2 messages as we need to make sure we see bad behavior (double messages)
|
||||
pendingComplaints((size_t)_params.size * 2, MSG_QUORUM_COMPLAINT),
|
||||
pendingJustifications((size_t)_params.size * 2, MSG_QUORUM_JUSTIFICATION),
|
||||
@ -185,14 +187,14 @@ void CDKGSessionHandler::StopThread()
|
||||
|
||||
bool CDKGSessionHandler::InitNewQuorum(const CBlockIndex* pQuorumBaseBlockIndex)
|
||||
{
|
||||
curSession = std::make_unique<CDKGSession>(params, blsWorker, m_dmnman, dkgManager, dkgDebugManager, connman, m_sporkman);
|
||||
curSession = std::make_unique<CDKGSession>(params, blsWorker, m_dmnman, dkgManager, dkgDebugManager, connman, m_mn_activeman, m_sporkman);
|
||||
|
||||
if (!DeploymentDIP0003Enforced(pQuorumBaseBlockIndex->nHeight, Params().GetConsensus())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto mns = utils::GetAllQuorumMembers(params.type, m_dmnman, pQuorumBaseBlockIndex);
|
||||
if (!curSession->Init(pQuorumBaseBlockIndex, mns, WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash), quorumIndex)) {
|
||||
if (!curSession->Init(pQuorumBaseBlockIndex, mns, WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash()), quorumIndex)) {
|
||||
LogPrintf("CDKGSessionManager::%s -- height[%d] quorum initialization failed for %s qi[%d] mns[%d]\n", __func__, pQuorumBaseBlockIndex->nHeight, curSession->params.name, quorumIndex, mns.size());
|
||||
return false;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <map>
|
||||
#include <optional>
|
||||
|
||||
class CActiveMasternodeManager;
|
||||
class CBlockIndex;
|
||||
class CBLSWorker;
|
||||
class CChainState;
|
||||
@ -125,6 +126,7 @@ private:
|
||||
CDKGDebugManager& dkgDebugManager;
|
||||
CDKGSessionManager& dkgManager;
|
||||
CQuorumBlockProcessor& quorumBlockProcessor;
|
||||
const CActiveMasternodeManager* m_mn_activeman;
|
||||
const CSporkManager& m_sporkman;
|
||||
const Consensus::LLMQParams params;
|
||||
const int quorumIndex;
|
||||
@ -146,7 +148,8 @@ private:
|
||||
public:
|
||||
CDKGSessionHandler(CBLSWorker& _blsWorker, CChainState& chainstate, CConnman& _connman, CDeterministicMNManager& dmnman,
|
||||
CDKGDebugManager& _dkgDebugManager, CDKGSessionManager& _dkgManager, CQuorumBlockProcessor& _quorumBlockProcessor,
|
||||
const CSporkManager& sporkman, const Consensus::LLMQParams& _params, int _quorumIndex);
|
||||
const CActiveMasternodeManager* mn_activeman, const CSporkManager& sporkman, const Consensus::LLMQParams& _params,
|
||||
int _quorumIndex);
|
||||
~CDKGSessionHandler() = default;
|
||||
|
||||
void UpdatedBlockTip(const CBlockIndex *pindexNew);
|
||||
|
@ -25,8 +25,8 @@ static const std::string DB_SKCONTRIB = "qdkg_S";
|
||||
static const std::string DB_ENC_CONTRIB = "qdkg_E";
|
||||
|
||||
CDKGSessionManager::CDKGSessionManager(CBLSWorker& _blsWorker, CChainState& chainstate, CConnman& _connman, CDeterministicMNManager& dmnman,
|
||||
CDKGDebugManager& _dkgDebugManager, CQuorumBlockProcessor& _quorumBlockProcessor, const CSporkManager& sporkman,
|
||||
bool unitTests, bool fWipe) :
|
||||
CDKGDebugManager& _dkgDebugManager, CQuorumBlockProcessor& _quorumBlockProcessor, const CActiveMasternodeManager* mn_activeman,
|
||||
const CSporkManager& sporkman, bool unitTests, bool fWipe) :
|
||||
db(std::make_unique<CDBWrapper>(unitTests ? "" : (GetDataDir() / "llmq/dkgdb"), 1 << 20, unitTests, fWipe)),
|
||||
blsWorker(_blsWorker),
|
||||
m_chainstate(chainstate),
|
||||
@ -49,7 +49,7 @@ CDKGSessionManager::CDKGSessionManager(CBLSWorker& _blsWorker, CChainState& chai
|
||||
for (const auto i : irange::range(session_count)) {
|
||||
dkgSessionHandlers.emplace(std::piecewise_construct,
|
||||
std::forward_as_tuple(params.type, i),
|
||||
std::forward_as_tuple(blsWorker, m_chainstate, connman, dmnman, dkgDebugManager, *this, quorumBlockProcessor, spork_manager, params, i));
|
||||
std::forward_as_tuple(blsWorker, m_chainstate, connman, dmnman, dkgDebugManager, *this, quorumBlockProcessor, mn_activeman, spork_manager, params, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
class CActiveMasternodeManager;
|
||||
class CBlockIndex;
|
||||
class CChainState;
|
||||
class CDBWrapper;
|
||||
@ -66,8 +67,8 @@ private:
|
||||
|
||||
public:
|
||||
CDKGSessionManager(CBLSWorker& _blsWorker, CChainState& chainstate, CConnman& _connman, CDeterministicMNManager& dmnman,
|
||||
CDKGDebugManager& _dkgDebugManager, CQuorumBlockProcessor& _quorumBlockProcessor, const CSporkManager& sporkman,
|
||||
bool unitTests, bool fWipe);
|
||||
CDKGDebugManager& _dkgDebugManager, CQuorumBlockProcessor& _quorumBlockProcessor, const CActiveMasternodeManager* mn_activeman,
|
||||
const CSporkManager& sporkman, bool unitTests, bool fWipe);
|
||||
~CDKGSessionManager() = default;
|
||||
|
||||
void StartThreads();
|
||||
|
@ -101,9 +101,9 @@ bool CQuorum::SetVerificationVector(const std::vector<CBLSPublicKey>& quorumVecI
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CQuorum::SetSecretKeyShare(const CBLSSecretKey& secretKeyShare)
|
||||
bool CQuorum::SetSecretKeyShare(const CBLSSecretKey& secretKeyShare, const CActiveMasternodeManager& mn_activeman)
|
||||
{
|
||||
if (!secretKeyShare.IsValid() || (secretKeyShare.GetPublicKey() != GetPubKeyShare(WITH_LOCK(activeMasternodeInfoCs, return GetMemberIndex(activeMasternodeInfo.proTxHash))))) {
|
||||
if (!secretKeyShare.IsValid() || (secretKeyShare.GetPublicKey() != GetPubKeyShare(WITH_LOCK(mn_activeman.cs, return GetMemberIndex(mn_activeman.GetProTxHash()))))) {
|
||||
return false;
|
||||
}
|
||||
LOCK(cs);
|
||||
@ -205,8 +205,10 @@ bool CQuorum::ReadContributions(CEvoDB& evoDb)
|
||||
return true;
|
||||
}
|
||||
|
||||
CQuorumManager::CQuorumManager(CBLSWorker& _blsWorker, CChainState& chainstate, CConnman& _connman, CDeterministicMNManager& dmnman, CDKGSessionManager& _dkgManager,
|
||||
CEvoDB& _evoDb, CQuorumBlockProcessor& _quorumBlockProcessor, const CSporkManager& sporkman, const std::unique_ptr<CMasternodeSync>& mn_sync) :
|
||||
CQuorumManager::CQuorumManager(CBLSWorker& _blsWorker, CChainState& chainstate, CConnman& _connman, CDeterministicMNManager& dmnman,
|
||||
CDKGSessionManager& _dkgManager, CEvoDB& _evoDb, CQuorumBlockProcessor& _quorumBlockProcessor,
|
||||
const CActiveMasternodeManager* mn_activeman, const CSporkManager& sporkman,
|
||||
const std::unique_ptr<CMasternodeSync>& mn_sync) :
|
||||
blsWorker(_blsWorker),
|
||||
m_chainstate(chainstate),
|
||||
connman(_connman),
|
||||
@ -214,6 +216,7 @@ CQuorumManager::CQuorumManager(CBLSWorker& _blsWorker, CChainState& chainstate,
|
||||
dkgManager(_dkgManager),
|
||||
m_evoDb(_evoDb),
|
||||
quorumBlockProcessor(_quorumBlockProcessor),
|
||||
m_mn_activeman(mn_activeman),
|
||||
m_sporkman(sporkman),
|
||||
m_mn_sync(mn_sync)
|
||||
{
|
||||
@ -250,7 +253,12 @@ void CQuorumManager::TriggerQuorumDataRecoveryThreads(const CBlockIndex* pIndex)
|
||||
const auto vecQuorums = ScanQuorums(params.type, pIndex, params.keepOldConnections);
|
||||
|
||||
// First check if we are member of any quorum of this type
|
||||
auto proTxHash = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash);
|
||||
const uint256 proTxHash = [this]() {
|
||||
if (!fMasternodeMode) return uint256();
|
||||
assert(m_mn_activeman);
|
||||
return WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash());
|
||||
}();
|
||||
|
||||
bool fWeAreQuorumTypeMember = ranges::any_of(vecQuorums, [&proTxHash](const auto& pQuorum) {
|
||||
return pQuorum->IsValidMember(proTxHash);
|
||||
});
|
||||
@ -341,7 +349,12 @@ void CQuorumManager::CheckQuorumConnections(const Consensus::LLMQParams& llmqPar
|
||||
LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- llmqType[%d] h[%d] keeping mn quorum connections for quorum: [%d:%s]\n", __func__, ToUnderlying(llmqParams.type), pindexNew->nHeight, curDkgHeight, curDkgBlock.ToString());
|
||||
}
|
||||
|
||||
const auto myProTxHash = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash);
|
||||
const uint256 myProTxHash = [this]() {
|
||||
if (!fMasternodeMode) return uint256();
|
||||
assert(m_mn_activeman);
|
||||
return WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash());
|
||||
}();
|
||||
|
||||
bool isISType = llmqParams.type == Params().GetConsensus().llmqTypeDIP0024InstantSend;
|
||||
|
||||
bool watchOtherISQuorums = isISType && !myProTxHash.IsNull() &&
|
||||
@ -640,6 +653,8 @@ CQuorumCPtr CQuorumManager::GetQuorum(Consensus::LLMQType llmqType, gsl::not_nul
|
||||
|
||||
size_t CQuorumManager::GetQuorumRecoveryStartOffset(const CQuorumCPtr pQuorum, const CBlockIndex* pIndex) const
|
||||
{
|
||||
assert(m_mn_activeman);
|
||||
|
||||
auto mns = m_dmnman.GetListForBlock(pIndex);
|
||||
std::vector<uint256> vecProTxHashes;
|
||||
vecProTxHashes.reserve(mns.GetValidMNsCount());
|
||||
@ -649,10 +664,10 @@ size_t CQuorumManager::GetQuorumRecoveryStartOffset(const CQuorumCPtr pQuorum, c
|
||||
std::sort(vecProTxHashes.begin(), vecProTxHashes.end());
|
||||
size_t nIndex{0};
|
||||
{
|
||||
LOCK(activeMasternodeInfoCs);
|
||||
LOCK(m_mn_activeman->cs);
|
||||
for (const auto i : irange::range(vecProTxHashes.size())) {
|
||||
// cppcheck-suppress useStlAlgorithm
|
||||
if (activeMasternodeInfo.proTxHash == vecProTxHashes[i]) {
|
||||
if (m_mn_activeman->GetProTxHash() == vecProTxHashes[i]) {
|
||||
nIndex = i;
|
||||
break;
|
||||
}
|
||||
@ -813,6 +828,7 @@ PeerMsgRet CQuorumManager::ProcessMessage(CNode& pfrom, const std::string& msg_t
|
||||
|
||||
// Check if request has ENCRYPTED_CONTRIBUTIONS data
|
||||
if (request.GetDataMask() & CQuorumDataRequest::ENCRYPTED_CONTRIBUTIONS) {
|
||||
assert(fMasternodeMode);
|
||||
|
||||
if (WITH_LOCK(pQuorum->cs, return pQuorum->quorumVvec->size() != size_t(pQuorum->params.threshold))) {
|
||||
return errorHandler("No valid quorum verification vector available", 0); // Don't bump score because we asked for it
|
||||
@ -828,15 +844,14 @@ PeerMsgRet CQuorumManager::ProcessMessage(CNode& pfrom, const std::string& msg_t
|
||||
|
||||
std::vector<CBLSSecretKey> vecSecretKeys;
|
||||
vecSecretKeys.resize(vecEncrypted.size());
|
||||
auto secret = WITH_LOCK(activeMasternodeInfoCs, return *activeMasternodeInfo.blsKeyOperator);
|
||||
for (const auto i : irange::range(vecEncrypted.size())) {
|
||||
if (!vecEncrypted[i].Decrypt(memberIdx, secret, vecSecretKeys[i], PROTOCOL_VERSION)) {
|
||||
if (!Assert(m_mn_activeman)->Decrypt(vecEncrypted[i], memberIdx, vecSecretKeys[i], PROTOCOL_VERSION)) {
|
||||
return errorHandler("Failed to decrypt");
|
||||
}
|
||||
}
|
||||
|
||||
CBLSSecretKey secretKeyShare = blsWorker.AggregateSecretKeys(vecSecretKeys);
|
||||
if (!pQuorum->SetSecretKeyShare(secretKeyShare)) {
|
||||
if (!pQuorum->SetSecretKeyShare(secretKeyShare, *m_mn_activeman)) {
|
||||
return errorHandler("Invalid secret key share received");
|
||||
}
|
||||
}
|
||||
@ -878,6 +893,8 @@ void CQuorumManager::StartCachePopulatorThread(const CQuorumCPtr pQuorum) const
|
||||
|
||||
void CQuorumManager::StartQuorumDataRecoveryThread(const CQuorumCPtr pQuorum, const CBlockIndex* pIndex, uint16_t nDataMaskIn) const
|
||||
{
|
||||
assert(m_mn_activeman);
|
||||
|
||||
if (pQuorum->fQuorumDataRecoveryThreadRunning) {
|
||||
LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- Already running\n", __func__);
|
||||
return;
|
||||
@ -911,7 +928,7 @@ void CQuorumManager::StartQuorumDataRecoveryThread(const CQuorumCPtr pQuorum, co
|
||||
|
||||
vecMemberHashes.reserve(pQuorum->qc->validMembers.size());
|
||||
for (auto& member : pQuorum->members) {
|
||||
if (pQuorum->IsValidMember(member->proTxHash) && member->proTxHash != WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash)) {
|
||||
if (pQuorum->IsValidMember(member->proTxHash) && member->proTxHash != WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash())) {
|
||||
vecMemberHashes.push_back(member->proTxHash);
|
||||
}
|
||||
}
|
||||
@ -960,7 +977,7 @@ void CQuorumManager::StartQuorumDataRecoveryThread(const CQuorumCPtr pQuorum, co
|
||||
printLog("Connect");
|
||||
}
|
||||
|
||||
auto proTxHash = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash);
|
||||
auto proTxHash = WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash());
|
||||
connman.ForEachNode([&](CNode* pNode) {
|
||||
auto verifiedProRegTxHash = pNode->GetVerifiedProRegTxHash();
|
||||
if (pCurrentMemberHash == nullptr || verifiedProRegTxHash != *pCurrentMemberHash) {
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
|
||||
class CActiveMasternodeManager;
|
||||
class CBlockIndex;
|
||||
class CChainState;
|
||||
class CConnman;
|
||||
@ -192,7 +193,7 @@ public:
|
||||
void Init(CFinalCommitmentPtr _qc, const CBlockIndex* _pQuorumBaseBlockIndex, const uint256& _minedBlockHash, Span<CDeterministicMNCPtr> _members);
|
||||
|
||||
bool SetVerificationVector(const std::vector<CBLSPublicKey>& quorumVecIn);
|
||||
bool SetSecretKeyShare(const CBLSSecretKey& secretKeyShare);
|
||||
bool SetSecretKeyShare(const CBLSSecretKey& secretKeyShare, const CActiveMasternodeManager& mn_activeman);
|
||||
|
||||
bool HasVerificationVector() const;
|
||||
bool IsMember(const uint256& proTxHash) const;
|
||||
@ -223,6 +224,7 @@ private:
|
||||
CDKGSessionManager& dkgManager;
|
||||
CEvoDB& m_evoDb;
|
||||
CQuorumBlockProcessor& quorumBlockProcessor;
|
||||
const CActiveMasternodeManager* m_mn_activeman;
|
||||
const CSporkManager& m_sporkman;
|
||||
const std::unique_ptr<CMasternodeSync>& m_mn_sync;
|
||||
|
||||
@ -237,8 +239,9 @@ private:
|
||||
mutable CThreadInterrupt quorumThreadInterrupt;
|
||||
|
||||
public:
|
||||
CQuorumManager(CBLSWorker& _blsWorker, CChainState& chainstate, CConnman& _connman, CDeterministicMNManager& dmnman, CDKGSessionManager& _dkgManager,
|
||||
CEvoDB& _evoDb, CQuorumBlockProcessor& _quorumBlockProcessor, const CSporkManager& sporkman, const std::unique_ptr<CMasternodeSync>& mn_sync);
|
||||
CQuorumManager(CBLSWorker& _blsWorker, CChainState& chainstate, CConnman& _connman, CDeterministicMNManager& dmnman,
|
||||
CDKGSessionManager& _dkgManager, CEvoDB& _evoDb, CQuorumBlockProcessor& _quorumBlockProcessor,
|
||||
const CActiveMasternodeManager* mn_activeman, const CSporkManager& sporkman, const std::unique_ptr<CMasternodeSync>& mn_sync);
|
||||
~CQuorumManager() { Stop(); };
|
||||
|
||||
void Start();
|
||||
|
@ -539,9 +539,9 @@ void CRecoveredSigsDb::CleanupOldVotes(int64_t maxAge)
|
||||
|
||||
//////////////////
|
||||
|
||||
CSigningManager::CSigningManager(CConnman& _connman, const CQuorumManager& _qman,
|
||||
CSigningManager::CSigningManager(CConnman& _connman, const CActiveMasternodeManager* mn_activeman, const CQuorumManager& _qman,
|
||||
bool fMemory, bool fWipe) :
|
||||
db(fMemory, fWipe), connman(_connman), qman(_qman)
|
||||
db(fMemory, fWipe), connman(_connman), m_mn_activeman(mn_activeman), qman(_qman)
|
||||
{
|
||||
}
|
||||
|
||||
@ -895,9 +895,10 @@ void CSigningManager::UnregisterRecoveredSigsListener(CRecoveredSigsListener* l)
|
||||
|
||||
bool CSigningManager::AsyncSignIfMember(Consensus::LLMQType llmqType, CSigSharesManager& shareman, const uint256& id, const uint256& msgHash, const uint256& quorumHash, bool allowReSign)
|
||||
{
|
||||
if (!fMasternodeMode || WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash.IsNull())) {
|
||||
return false;
|
||||
}
|
||||
if (!fMasternodeMode) return false;
|
||||
|
||||
assert(m_mn_activeman);
|
||||
if (WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash().IsNull())) return false;
|
||||
|
||||
const CQuorumCPtr quorum = [&]() {
|
||||
if (quorumHash.IsNull()) {
|
||||
@ -919,7 +920,7 @@ bool CSigningManager::AsyncSignIfMember(Consensus::LLMQType llmqType, CSigShares
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!WITH_LOCK(activeMasternodeInfoCs, return quorum->IsValidMember(activeMasternodeInfo.proTxHash))) {
|
||||
if (!WITH_LOCK(m_mn_activeman->cs, return quorum->IsValidMember(m_mn_activeman->GetProTxHash()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
class CActiveMasternodeManager;
|
||||
class CConnman;
|
||||
class CDataStream;
|
||||
class CDBBatch;
|
||||
@ -162,6 +163,7 @@ private:
|
||||
|
||||
CRecoveredSigsDb db;
|
||||
CConnman& connman;
|
||||
const CActiveMasternodeManager* m_mn_activeman;
|
||||
const CQuorumManager& qman;
|
||||
|
||||
std::atomic<PeerManager*> m_peerman{nullptr};
|
||||
@ -177,7 +179,7 @@ private:
|
||||
std::vector<CRecoveredSigsListener*> recoveredSigsListeners GUARDED_BY(cs);
|
||||
|
||||
public:
|
||||
CSigningManager(CConnman& _connman, const CQuorumManager& _qman, bool fMemory, bool fWipe);
|
||||
CSigningManager(CConnman& _connman, const CActiveMasternodeManager* mn_activeman, const CQuorumManager& _qman, bool fMemory, bool fWipe);
|
||||
|
||||
bool AlreadyHave(const CInv& inv) const;
|
||||
bool GetRecoveredSigForGetData(const uint256& hash, CRecoveredSig& ret) const;
|
||||
|
@ -218,9 +218,10 @@ void CSigSharesManager::InterruptWorkerThread()
|
||||
void CSigSharesManager::ProcessMessage(const CNode& pfrom, const CSporkManager& sporkman, const std::string& msg_type, CDataStream& vRecv)
|
||||
{
|
||||
// non-masternodes are not interested in sigshares
|
||||
if (!fMasternodeMode || WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash.IsNull())) {
|
||||
return;
|
||||
}
|
||||
if (!fMasternodeMode) return;
|
||||
|
||||
assert(m_mn_activeman);
|
||||
if (WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash().IsNull())) return;
|
||||
|
||||
if (sporkman.IsSporkActive(SPORK_21_QUORUM_ALL_CONNECTED) && msg_type == NetMsgType::QSIGSHARE) {
|
||||
std::vector<CSigShare> receivedSigShares;
|
||||
@ -408,7 +409,7 @@ bool CSigSharesManager::ProcessMessageBatchedSigShares(const CNode& pfrom, const
|
||||
return true;
|
||||
}
|
||||
|
||||
if (bool ban{false}; !PreVerifyBatchedSigShares(qman, sessionInfo, batchedSigShares, ban)) {
|
||||
if (bool ban{false}; !PreVerifyBatchedSigShares(*Assert(m_mn_activeman), qman, sessionInfo, batchedSigShares, ban)) {
|
||||
return !ban;
|
||||
}
|
||||
|
||||
@ -457,6 +458,8 @@ bool CSigSharesManager::ProcessMessageBatchedSigShares(const CNode& pfrom, const
|
||||
|
||||
void CSigSharesManager::ProcessMessageSigShare(NodeId fromId, const CSigShare& sigShare)
|
||||
{
|
||||
assert(m_mn_activeman);
|
||||
|
||||
auto quorum = qman.GetQuorum(sigShare.getLlmqType(), sigShare.getQuorumHash());
|
||||
if (!quorum) {
|
||||
return;
|
||||
@ -465,7 +468,7 @@ void CSigSharesManager::ProcessMessageSigShare(NodeId fromId, const CSigShare& s
|
||||
// quorum is too old
|
||||
return;
|
||||
}
|
||||
if (!quorum->IsMember(WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash))) {
|
||||
if (!quorum->IsMember(WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash()))) {
|
||||
// we're not a member so we can't verify it (we actually shouldn't have received it)
|
||||
return;
|
||||
}
|
||||
@ -506,7 +509,8 @@ void CSigSharesManager::ProcessMessageSigShare(NodeId fromId, const CSigShare& s
|
||||
sigShare.GetSignHash().ToString(), sigShare.getId().ToString(), sigShare.getMsgHash().ToString(), sigShare.getQuorumMember(), fromId);
|
||||
}
|
||||
|
||||
bool CSigSharesManager::PreVerifyBatchedSigShares(const CQuorumManager& quorum_manager, const CSigSharesNodeState::SessionInfo& session, const CBatchedSigShares& batchedSigShares, bool& retBan)
|
||||
bool CSigSharesManager::PreVerifyBatchedSigShares(const CActiveMasternodeManager& mn_activeman, const CQuorumManager& quorum_manager,
|
||||
const CSigSharesNodeState::SessionInfo& session, const CBatchedSigShares& batchedSigShares, bool& retBan)
|
||||
{
|
||||
retBan = false;
|
||||
|
||||
@ -514,7 +518,7 @@ bool CSigSharesManager::PreVerifyBatchedSigShares(const CQuorumManager& quorum_m
|
||||
// quorum is too old
|
||||
return false;
|
||||
}
|
||||
if (!session.quorum->IsMember(WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash))) {
|
||||
if (!session.quorum->IsMember(WITH_LOCK(mn_activeman.cs, return mn_activeman.GetProTxHash()))) {
|
||||
// we're not a member so we can't verify it (we actually shouldn't have received it)
|
||||
return false;
|
||||
}
|
||||
@ -692,13 +696,14 @@ void CSigSharesManager::ProcessPendingSigShares(const std::vector<CSigShare>& si
|
||||
// sig shares are already verified when entering this method
|
||||
void CSigSharesManager::ProcessSigShare(const CSigShare& sigShare, const CConnman& connman, const CQuorumCPtr& quorum)
|
||||
{
|
||||
auto llmqType = quorum->params.type;
|
||||
assert(m_mn_activeman);
|
||||
|
||||
auto llmqType = quorum->params.type;
|
||||
bool canTryRecovery = false;
|
||||
|
||||
// prepare node set for direct-push in case this is our sig share
|
||||
std::set<NodeId> quorumNodes;
|
||||
if (!IsAllMembersConnectedEnabled(llmqType, m_sporkman) && sigShare.getQuorumMember() == quorum->GetMemberIndex(WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash))) {
|
||||
if (!IsAllMembersConnectedEnabled(llmqType, m_sporkman) && sigShare.getQuorumMember() == quorum->GetMemberIndex(WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash()))) {
|
||||
quorumNodes = connman.GetMasternodeQuorumNodes(sigShare.getLlmqType(), sigShare.getQuorumHash());
|
||||
}
|
||||
|
||||
@ -1488,8 +1493,10 @@ void CSigSharesManager::SignPendingSigShares()
|
||||
|
||||
std::optional<CSigShare> CSigSharesManager::CreateSigShare(const CQuorumCPtr& quorum, const uint256& id, const uint256& msgHash) const
|
||||
{
|
||||
assert(m_mn_activeman);
|
||||
|
||||
cxxtimer::Timer t(true);
|
||||
auto activeMasterNodeProTxHash = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash);
|
||||
auto activeMasterNodeProTxHash = WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash());
|
||||
|
||||
if (!quorum->IsValidMember(activeMasterNodeProTxHash)) {
|
||||
return std::nullopt;
|
||||
|
@ -401,6 +401,7 @@ private:
|
||||
|
||||
CConnman& connman;
|
||||
CSigningManager& sigman;
|
||||
const CActiveMasternodeManager* m_mn_activeman;
|
||||
const CQuorumManager& qman;
|
||||
const CSporkManager& m_sporkman;
|
||||
|
||||
@ -410,8 +411,9 @@ private:
|
||||
std::atomic<uint32_t> recoveredSigsCounter{0};
|
||||
|
||||
public:
|
||||
explicit CSigSharesManager(CConnman& _connman, CSigningManager& _sigman, const CQuorumManager& _qman, const CSporkManager& sporkman, const std::unique_ptr<PeerManager>& peerman) :
|
||||
connman(_connman), sigman(_sigman), qman(_qman), m_sporkman(sporkman), m_peerman(peerman)
|
||||
explicit CSigSharesManager(CConnman& _connman, CSigningManager& _sigman, const CActiveMasternodeManager* mn_activeman,
|
||||
const CQuorumManager& _qman, const CSporkManager& sporkman, const std::unique_ptr<PeerManager>& peerman) :
|
||||
connman(_connman), sigman(_sigman), m_mn_activeman(mn_activeman), qman(_qman), m_sporkman(sporkman), m_peerman(peerman)
|
||||
{
|
||||
workInterrupt.reset();
|
||||
};
|
||||
@ -443,7 +445,8 @@ private:
|
||||
void ProcessMessageSigShare(NodeId fromId, const CSigShare& sigShare);
|
||||
|
||||
static bool VerifySigSharesInv(Consensus::LLMQType llmqType, const CSigSharesInv& inv);
|
||||
static bool PreVerifyBatchedSigShares(const CQuorumManager& quorum_manager, const CSigSharesNodeState::SessionInfo& session, const CBatchedSigShares& batchedSigShares, bool& retBan);
|
||||
static bool PreVerifyBatchedSigShares(const CActiveMasternodeManager& mn_activeman, const CQuorumManager& quorum_manager,
|
||||
const CSigSharesNodeState::SessionInfo& session, const CBatchedSigShares& batchedSigShares, bool& retBan);
|
||||
|
||||
void CollectPendingSigSharesToVerify(size_t maxUniqueSessions,
|
||||
std::unordered_map<NodeId, std::vector<CSigShare>>& retSigShares,
|
||||
|
@ -4,24 +4,34 @@
|
||||
|
||||
#include <masternode/node.h>
|
||||
|
||||
#include <evo/deterministicmns.h>
|
||||
|
||||
#include <bls/bls_ies.h>
|
||||
#include <chainparams.h>
|
||||
#include <deploymentstatus.h>
|
||||
#include <evo/deterministicmns.h>
|
||||
#include <net.h>
|
||||
#include <netbase.h>
|
||||
#include <protocol.h>
|
||||
#include <util/check.h>
|
||||
#include <validation.h>
|
||||
#include <warnings.h>
|
||||
|
||||
// Keep track of the active Masternode
|
||||
RecursiveMutex activeMasternodeInfoCs;
|
||||
CActiveMasternodeInfo activeMasternodeInfo GUARDED_BY(activeMasternodeInfoCs);
|
||||
std::unique_ptr<CActiveMasternodeManager> activeMasternodeManager;
|
||||
|
||||
CActiveMasternodeManager::CActiveMasternodeManager(const CBLSSecretKey& sk, CConnman& connman, const std::unique_ptr<CDeterministicMNManager>& dmnman) :
|
||||
m_info(sk, sk.GetPublicKey()),
|
||||
m_connman{connman},
|
||||
m_dmnman{dmnman}
|
||||
{
|
||||
assert(sk.IsValid()); /* We can assume pk is valid if sk is valid */
|
||||
LogPrintf("MASTERNODE:\n blsPubKeyOperator legacy: %s\n blsPubKeyOperator basic: %s\n",
|
||||
m_info.blsPubKeyOperator.ToString(/*specificLegacyScheme=*/ true),
|
||||
m_info.blsPubKeyOperator.ToString(/*specificLegacyScheme=*/ false));
|
||||
}
|
||||
|
||||
std::string CActiveMasternodeManager::GetStateString() const
|
||||
{
|
||||
switch (state) {
|
||||
switch (WITH_LOCK(cs, return m_state)) {
|
||||
case MASTERNODE_WAITING_FOR_PROTX:
|
||||
return "WAITING_FOR_PROTX";
|
||||
case MASTERNODE_POSE_BANNED:
|
||||
@ -43,7 +53,8 @@ std::string CActiveMasternodeManager::GetStateString() const
|
||||
|
||||
std::string CActiveMasternodeManager::GetStatus() const
|
||||
{
|
||||
switch (state) {
|
||||
LOCK(cs);
|
||||
switch (m_state) {
|
||||
case MASTERNODE_WAITING_FOR_PROTX:
|
||||
return "Waiting for ProTx to appear on-chain";
|
||||
case MASTERNODE_POSE_BANNED:
|
||||
@ -57,7 +68,7 @@ std::string CActiveMasternodeManager::GetStatus() const
|
||||
case MASTERNODE_READY:
|
||||
return "Ready";
|
||||
case MASTERNODE_ERROR:
|
||||
return "Error. " + strError;
|
||||
return "Error. " + m_error;
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
@ -65,7 +76,7 @@ std::string CActiveMasternodeManager::GetStatus() const
|
||||
|
||||
void CActiveMasternodeManager::Init(const CBlockIndex* pindex)
|
||||
{
|
||||
LOCK2(cs_main, activeMasternodeInfoCs);
|
||||
LOCK(cs);
|
||||
|
||||
if (!fMasternodeMode) return;
|
||||
|
||||
@ -74,20 +85,20 @@ void CActiveMasternodeManager::Init(const CBlockIndex* pindex)
|
||||
// Check that our local network configuration is correct
|
||||
if (!fListen && Params().RequireRoutableExternalIP()) {
|
||||
// listen option is probably overwritten by something else, no good
|
||||
state = MASTERNODE_ERROR;
|
||||
strError = "Masternode must accept connections from outside. Make sure listen configuration option is not overwritten by some another parameter.";
|
||||
LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s\n", strError);
|
||||
m_state = MASTERNODE_ERROR;
|
||||
m_error = "Masternode must accept connections from outside. Make sure listen configuration option is not overwritten by some another parameter.";
|
||||
LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s\n", m_error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GetLocalAddress(activeMasternodeInfo.service)) {
|
||||
state = MASTERNODE_ERROR;
|
||||
if (!GetLocalAddress(m_info.service)) {
|
||||
m_state = MASTERNODE_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
CDeterministicMNList mnList = Assert(m_dmnman)->GetListForBlock(pindex);
|
||||
|
||||
CDeterministicMNCPtr dmn = mnList.GetMNByOperatorKey(*activeMasternodeInfo.blsPubKeyOperator);
|
||||
CDeterministicMNCPtr dmn = mnList.GetMNByOperatorKey(m_info.blsPubKeyOperator);
|
||||
if (!dmn) {
|
||||
// MN not appeared on the chain yet
|
||||
return;
|
||||
@ -95,87 +106,80 @@ void CActiveMasternodeManager::Init(const CBlockIndex* pindex)
|
||||
|
||||
if (!mnList.IsMNValid(dmn->proTxHash)) {
|
||||
if (mnList.IsMNPoSeBanned(dmn->proTxHash)) {
|
||||
state = MASTERNODE_POSE_BANNED;
|
||||
m_state = MASTERNODE_POSE_BANNED;
|
||||
} else {
|
||||
state = MASTERNODE_REMOVED;
|
||||
m_state = MASTERNODE_REMOVED;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
LogPrintf("CActiveMasternodeManager::Init -- proTxHash=%s, proTx=%s\n", dmn->proTxHash.ToString(), dmn->ToString());
|
||||
|
||||
if (activeMasternodeInfo.service != dmn->pdmnState->addr) {
|
||||
state = MASTERNODE_ERROR;
|
||||
strError = "Local address does not match the address from ProTx";
|
||||
LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s\n", strError);
|
||||
if (m_info.service != dmn->pdmnState->addr) {
|
||||
m_state = MASTERNODE_ERROR;
|
||||
m_error = "Local address does not match the address from ProTx";
|
||||
LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s\n", m_error);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check socket connectivity
|
||||
LogPrintf("CActiveMasternodeManager::Init -- Checking inbound connection to '%s'\n", activeMasternodeInfo.service.ToString());
|
||||
std::unique_ptr<Sock> sock = CreateSock(activeMasternodeInfo.service);
|
||||
LogPrintf("CActiveMasternodeManager::Init -- Checking inbound connection to '%s'\n", m_info.service.ToString());
|
||||
std::unique_ptr<Sock> sock = CreateSock(m_info.service);
|
||||
if (!sock) {
|
||||
state = MASTERNODE_ERROR;
|
||||
strError = "Could not create socket to connect to " + activeMasternodeInfo.service.ToString();
|
||||
LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s\n", strError);
|
||||
m_state = MASTERNODE_ERROR;
|
||||
m_error = "Could not create socket to connect to " + m_info.service.ToString();
|
||||
LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s\n", m_error);
|
||||
return;
|
||||
}
|
||||
bool fConnected = ConnectSocketDirectly(activeMasternodeInfo.service, *sock, nConnectTimeout, true) && IsSelectableSocket(sock->Get());
|
||||
bool fConnected = ConnectSocketDirectly(m_info.service, *sock, nConnectTimeout, true) && IsSelectableSocket(sock->Get());
|
||||
sock->Reset();
|
||||
|
||||
if (!fConnected && Params().RequireRoutableExternalIP()) {
|
||||
state = MASTERNODE_ERROR;
|
||||
strError = "Could not connect to " + activeMasternodeInfo.service.ToString();
|
||||
LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s\n", strError);
|
||||
m_state = MASTERNODE_ERROR;
|
||||
m_error = "Could not connect to " + m_info.service.ToString();
|
||||
LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s\n", m_error);
|
||||
return;
|
||||
}
|
||||
|
||||
activeMasternodeInfo.proTxHash = dmn->proTxHash;
|
||||
activeMasternodeInfo.outpoint = dmn->collateralOutpoint;
|
||||
activeMasternodeInfo.legacy = dmn->pdmnState->nVersion == CProRegTx::LEGACY_BLS_VERSION;
|
||||
state = MASTERNODE_READY;
|
||||
m_info.proTxHash = dmn->proTxHash;
|
||||
m_info.outpoint = dmn->collateralOutpoint;
|
||||
m_info.legacy = dmn->pdmnState->nVersion == CProRegTx::LEGACY_BLS_VERSION;
|
||||
m_state = MASTERNODE_READY;
|
||||
}
|
||||
|
||||
void CActiveMasternodeManager::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload)
|
||||
{
|
||||
LOCK2(cs_main, activeMasternodeInfoCs);
|
||||
|
||||
if (!fMasternodeMode) return;
|
||||
|
||||
if (!DeploymentDIP0003Enforced(pindexNew->nHeight, Params().GetConsensus())) return;
|
||||
|
||||
if (state == MASTERNODE_READY) {
|
||||
const auto [cur_state, cur_protx_hash] = WITH_LOCK(cs, return std::make_pair(m_state, m_info.proTxHash));
|
||||
if (cur_state == MASTERNODE_READY) {
|
||||
auto oldMNList = Assert(m_dmnman)->GetListForBlock(pindexNew->pprev);
|
||||
auto newMNList = m_dmnman->GetListForBlock(pindexNew);
|
||||
if (!newMNList.IsMNValid(activeMasternodeInfo.proTxHash)) {
|
||||
// MN disappeared from MN list
|
||||
state = MASTERNODE_REMOVED;
|
||||
activeMasternodeInfo.proTxHash = uint256();
|
||||
activeMasternodeInfo.outpoint.SetNull();
|
||||
auto reset = [this, pindexNew] (masternode_state_t state) -> void {
|
||||
LOCK(cs);
|
||||
m_state = state;
|
||||
m_info.proTxHash = uint256();
|
||||
m_info.outpoint.SetNull();
|
||||
// MN might have reappeared in same block with a new ProTx
|
||||
Init(pindexNew);
|
||||
return;
|
||||
};
|
||||
|
||||
if (!newMNList.IsMNValid(cur_protx_hash)) {
|
||||
// MN disappeared from MN list
|
||||
return reset(MASTERNODE_REMOVED);
|
||||
}
|
||||
|
||||
auto oldDmn = oldMNList.GetMN(activeMasternodeInfo.proTxHash);
|
||||
auto newDmn = newMNList.GetMN(activeMasternodeInfo.proTxHash);
|
||||
auto oldDmn = oldMNList.GetMN(cur_protx_hash);
|
||||
auto newDmn = newMNList.GetMN(cur_protx_hash);
|
||||
if (newDmn->pdmnState->pubKeyOperator != oldDmn->pdmnState->pubKeyOperator) {
|
||||
// MN operator key changed or revoked
|
||||
state = MASTERNODE_OPERATOR_KEY_CHANGED;
|
||||
activeMasternodeInfo.proTxHash = uint256();
|
||||
activeMasternodeInfo.outpoint.SetNull();
|
||||
// MN might have reappeared in same block with a new ProTx
|
||||
Init(pindexNew);
|
||||
return;
|
||||
return reset(MASTERNODE_OPERATOR_KEY_CHANGED);
|
||||
}
|
||||
|
||||
if (newDmn->pdmnState->addr != oldDmn->pdmnState->addr) {
|
||||
// MN IP changed
|
||||
state = MASTERNODE_PROTX_IP_CHANGED;
|
||||
activeMasternodeInfo.proTxHash = uint256();
|
||||
activeMasternodeInfo.outpoint.SetNull();
|
||||
Init(pindexNew);
|
||||
return;
|
||||
return reset(MASTERNODE_PROTX_IP_CHANGED);
|
||||
}
|
||||
} else {
|
||||
// MN might have (re)appeared with a new ProTx or we've found some peers
|
||||
@ -203,8 +207,8 @@ bool CActiveMasternodeManager::GetLocalAddress(CService& addrRet)
|
||||
if (!fFoundLocal) {
|
||||
bool empty = true;
|
||||
// If we have some peers, let's try to find our local address from one of them
|
||||
auto service = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.service);
|
||||
connman.ForEachNodeContinueIf(CConnman::AllNodes, [&](CNode* pnode) {
|
||||
auto service = WITH_LOCK(cs, return m_info.service);
|
||||
m_connman.ForEachNodeContinueIf(CConnman::AllNodes, [&](CNode* pnode) {
|
||||
empty = false;
|
||||
if (pnode->addr.IsIPv4())
|
||||
fFoundLocal = GetLocal(service, &pnode->addr) && IsValidNetAddr(service);
|
||||
@ -212,8 +216,9 @@ bool CActiveMasternodeManager::GetLocalAddress(CService& addrRet)
|
||||
});
|
||||
// nothing and no live connections, can't do anything for now
|
||||
if (empty) {
|
||||
strError = "Can't detect valid external address. Please consider using the externalip configuration option if problem persists. Make sure to use IPv4 address only.";
|
||||
LogPrintf("CActiveMasternodeManager::GetLocalAddress -- ERROR: %s\n", strError);
|
||||
LOCK(cs);
|
||||
m_error = "Can't detect valid external address. Please consider using the externalip configuration option if problem persists. Make sure to use IPv4 address only.";
|
||||
LogPrintf("CActiveMasternodeManager::GetLocalAddress -- ERROR: %s\n", m_error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -227,3 +232,34 @@ bool CActiveMasternodeManager::IsValidNetAddr(const CService& addrIn)
|
||||
return !Params().RequireRoutableExternalIP() ||
|
||||
(addrIn.IsIPv4() && IsReachable(addrIn) && addrIn.IsRoutable());
|
||||
}
|
||||
|
||||
template <template <typename> class EncryptedObj, typename Obj>
|
||||
[[nodiscard]] bool CActiveMasternodeManager::Decrypt(const EncryptedObj<Obj>& obj, size_t idx, Obj& ret_obj,
|
||||
int version) const
|
||||
{
|
||||
AssertLockNotHeld(cs);
|
||||
return WITH_LOCK(cs, return obj.Decrypt(idx, m_info.blsKeyOperator, ret_obj, version));
|
||||
}
|
||||
template bool CActiveMasternodeManager::Decrypt(const CBLSIESEncryptedObject<CBLSSecretKey>& obj, size_t idx,
|
||||
CBLSSecretKey& ret_obj, int version) const;
|
||||
template bool CActiveMasternodeManager::Decrypt(const CBLSIESMultiRecipientObjects<CBLSSecretKey>& obj, size_t idx,
|
||||
CBLSSecretKey& ret_obj, int version) const;
|
||||
|
||||
[[nodiscard]] CBLSSignature CActiveMasternodeManager::Sign(const uint256& hash) const
|
||||
{
|
||||
AssertLockNotHeld(cs);
|
||||
return WITH_LOCK(cs, return m_info.blsKeyOperator.Sign(hash));
|
||||
}
|
||||
|
||||
[[nodiscard]] CBLSSignature CActiveMasternodeManager::Sign(const uint256& hash, const bool is_legacy) const
|
||||
{
|
||||
AssertLockNotHeld(cs);
|
||||
return WITH_LOCK(cs, return m_info.blsKeyOperator.Sign(hash, is_legacy));
|
||||
}
|
||||
|
||||
// We need to pass a copy as opposed to a const ref because CBLSPublicKeyVersionWrapper
|
||||
// does not accept a const ref in its construction args
|
||||
[[nodiscard]] CBLSPublicKey CActiveMasternodeManager::GetPubKey() const
|
||||
{
|
||||
return m_info.blsPubKeyOperator;
|
||||
}
|
||||
|
@ -5,33 +5,28 @@
|
||||
#ifndef BITCOIN_MASTERNODE_NODE_H
|
||||
#define BITCOIN_MASTERNODE_NODE_H
|
||||
|
||||
#include <bls/bls.h>
|
||||
#include <netaddress.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <threadsafety.h>
|
||||
#include <validationinterface.h>
|
||||
|
||||
class CActiveMasternodeManager;
|
||||
class CBLSPublicKey;
|
||||
class CBLSSecretKey;
|
||||
class CDeterministicMNManager;
|
||||
|
||||
struct CActiveMasternodeInfo;
|
||||
|
||||
extern CActiveMasternodeInfo activeMasternodeInfo;
|
||||
extern RecursiveMutex activeMasternodeInfoCs;
|
||||
extern std::unique_ptr<CActiveMasternodeManager> activeMasternodeManager;
|
||||
|
||||
struct CActiveMasternodeInfo {
|
||||
// Keys for the active Masternode
|
||||
std::unique_ptr<CBLSPublicKey> blsPubKeyOperator;
|
||||
std::unique_ptr<CBLSSecretKey> blsKeyOperator;
|
||||
const CBLSSecretKey blsKeyOperator;
|
||||
const CBLSPublicKey blsPubKeyOperator;
|
||||
|
||||
// Initialized while registering Masternode
|
||||
uint256 proTxHash;
|
||||
COutPoint outpoint;
|
||||
CService service;
|
||||
bool legacy{true};
|
||||
};
|
||||
|
||||
CActiveMasternodeInfo(const CBLSSecretKey& blsKeyOperator, const CBLSPublicKey& blsPubKeyOperator) :
|
||||
blsKeyOperator(blsKeyOperator), blsPubKeyOperator(blsPubKeyOperator) {};
|
||||
};
|
||||
|
||||
class CActiveMasternodeManager final : public CValidationInterface
|
||||
{
|
||||
@ -46,16 +41,18 @@ public:
|
||||
MASTERNODE_ERROR,
|
||||
};
|
||||
|
||||
mutable RecursiveMutex cs;
|
||||
|
||||
private:
|
||||
masternode_state_t state{MASTERNODE_WAITING_FOR_PROTX};
|
||||
std::string strError;
|
||||
CConnman& connman;
|
||||
masternode_state_t m_state GUARDED_BY(cs) {MASTERNODE_WAITING_FOR_PROTX};
|
||||
CActiveMasternodeInfo m_info GUARDED_BY(cs);
|
||||
std::string m_error GUARDED_BY(cs);
|
||||
|
||||
CConnman& m_connman;
|
||||
const std::unique_ptr<CDeterministicMNManager>& m_dmnman;
|
||||
|
||||
public:
|
||||
explicit CActiveMasternodeManager(CConnman& _connman, const std::unique_ptr<CDeterministicMNManager>& dmnman) :
|
||||
connman(_connman), m_dmnman(dmnman) {};
|
||||
~CActiveMasternodeManager() = default;
|
||||
explicit CActiveMasternodeManager(const CBLSSecretKey& sk, CConnman& connman, const std::unique_ptr<CDeterministicMNManager>& dmnman);
|
||||
|
||||
void UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload) override;
|
||||
|
||||
@ -66,8 +63,23 @@ public:
|
||||
|
||||
static bool IsValidNetAddr(const CService& addrIn);
|
||||
|
||||
template <template <typename> class EncryptedObj, typename Obj>
|
||||
[[nodiscard]] bool Decrypt(const EncryptedObj<Obj>& obj, size_t idx, Obj& ret_obj, int version) const
|
||||
LOCKS_EXCLUDED(cs);
|
||||
[[nodiscard]] CBLSSignature Sign(const uint256& hash) const LOCKS_EXCLUDED(cs);
|
||||
[[nodiscard]] CBLSSignature Sign(const uint256& hash, const bool is_legacy) const LOCKS_EXCLUDED(cs);
|
||||
|
||||
/* TODO: Reconsider external locking */
|
||||
[[nodiscard]] const COutPoint& GetOutPoint() const EXCLUSIVE_LOCKS_REQUIRED(cs) { return m_info.outpoint; }
|
||||
[[nodiscard]] const uint256& GetProTxHash() const EXCLUSIVE_LOCKS_REQUIRED(cs) { return m_info.proTxHash; }
|
||||
[[nodiscard]] const CService& GetService() const EXCLUSIVE_LOCKS_REQUIRED(cs) { return m_info.service; }
|
||||
[[nodiscard]] CBLSPublicKey GetPubKey() const EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
[[nodiscard]] bool IsLegacy() const EXCLUSIVE_LOCKS_REQUIRED(cs) { return m_info.legacy; }
|
||||
|
||||
private:
|
||||
bool GetLocalAddress(CService& addrRet);
|
||||
};
|
||||
|
||||
extern std::unique_ptr<CActiveMasternodeManager> activeMasternodeManager;
|
||||
|
||||
#endif // BITCOIN_MASTERNODE_NODE_H
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
class ArgsManager;
|
||||
class BanMan;
|
||||
class CActiveMasternodeManager;
|
||||
class CAddrMan;
|
||||
class CBlockPolicyEstimator;
|
||||
class CConnman;
|
||||
@ -79,6 +80,7 @@ struct NodeContext {
|
||||
std::unique_ptr<CNetFulfilledRequestManager> netfulfilledman;
|
||||
std::unique_ptr<CSporkManager> sporkman;
|
||||
std::unique_ptr<LLMQContext> llmq_ctx;
|
||||
CActiveMasternodeManager* mn_activeman{nullptr};
|
||||
CDeterministicMNManager* dmnman{nullptr};
|
||||
CMasternodeMetaMan* mn_metaman{nullptr};
|
||||
CMasternodeSync* mn_sync{nullptr};
|
||||
|
@ -38,8 +38,9 @@ static RPCHelpMan coinjoin()
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
|
||||
if (fMasternodeMode)
|
||||
if (fMasternodeMode) {
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Client-side mixing is not supported on masternodes");
|
||||
}
|
||||
|
||||
if (!CCoinJoinClientOptions::IsEnabled()) {
|
||||
if (!gArgs.GetBoolArg("-enablecoinjoin", true)) {
|
||||
|
@ -315,11 +315,23 @@ static UniValue gobject_submit(const JSONRPCRequest& request)
|
||||
}
|
||||
|
||||
auto mnList = node.dmnman->GetListAtChainTip();
|
||||
bool fMnFound = WITH_LOCK(activeMasternodeInfoCs, return mnList.HasValidMNByCollateral(activeMasternodeInfo.outpoint));
|
||||
|
||||
if (fMasternodeMode) {
|
||||
CHECK_NONFATAL(node.mn_activeman);
|
||||
|
||||
LOCK(node.mn_activeman->cs);
|
||||
const bool fMnFound = mnList.HasValidMNByCollateral(node.mn_activeman->GetOutPoint());
|
||||
|
||||
LogPrint(BCLog::GOBJECT, "gobject_submit -- pubKeyOperator = %s, outpoint = %s, params.size() = %lld, fMnFound = %d\n",
|
||||
(WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.blsPubKeyOperator ? activeMasternodeInfo.blsPubKeyOperator->ToString(activeMasternodeInfo.legacy) : "N/A")),
|
||||
WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.outpoint.ToStringShort()), request.params.size(), fMnFound);
|
||||
node.mn_activeman->GetPubKey().ToString(node.mn_activeman->IsLegacy()),
|
||||
node.mn_activeman->GetOutPoint().ToStringShort(),
|
||||
request.params.size(),
|
||||
fMnFound);
|
||||
} else {
|
||||
LogPrint(BCLog::GOBJECT, "gobject_submit -- pubKeyOperator = N/A, outpoint = N/A, params.size() = %lld, fMnFound = %d\n",
|
||||
request.params.size(),
|
||||
false);
|
||||
}
|
||||
|
||||
// ASSEMBLE NEW GOVERNANCE OBJECT FROM USER PARAMETERS
|
||||
|
||||
|
@ -257,20 +257,22 @@ static UniValue masternode_status(const JSONRPCRequest& request)
|
||||
{
|
||||
masternode_status_help(request);
|
||||
|
||||
if (!fMasternodeMode)
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "This is not a masternode");
|
||||
if (!fMasternodeMode) {
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "This node does not run an active masternode.");
|
||||
}
|
||||
|
||||
const NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
CHECK_NONFATAL(node.mn_activeman);
|
||||
|
||||
UniValue mnObj(UniValue::VOBJ);
|
||||
CDeterministicMNCPtr dmn;
|
||||
{
|
||||
LOCK(activeMasternodeInfoCs);
|
||||
LOCK(node.mn_activeman->cs);
|
||||
|
||||
// keep compatibility with legacy status for now (might get deprecated/removed later)
|
||||
mnObj.pushKV("outpoint", activeMasternodeInfo.outpoint.ToStringShort());
|
||||
mnObj.pushKV("service", activeMasternodeInfo.service.ToString());
|
||||
dmn = node.dmnman->GetListAtChainTip().GetMN(activeMasternodeInfo.proTxHash);
|
||||
mnObj.pushKV("outpoint", node.mn_activeman->GetOutPoint().ToStringShort());
|
||||
mnObj.pushKV("service", node.mn_activeman->GetService().ToString());
|
||||
dmn = node.dmnman->GetListAtChainTip().GetMN(node.mn_activeman->GetProTxHash());
|
||||
}
|
||||
if (dmn) {
|
||||
mnObj.pushKV("proTxHash", dmn->proTxHash.ToString());
|
||||
@ -279,8 +281,8 @@ static UniValue masternode_status(const JSONRPCRequest& request)
|
||||
mnObj.pushKV("collateralIndex", (int)dmn->collateralOutpoint.n);
|
||||
mnObj.pushKV("dmnState", dmn->pdmnState->ToJson(dmn->nType));
|
||||
}
|
||||
mnObj.pushKV("state", activeMasternodeManager->GetStateString());
|
||||
mnObj.pushKV("status", activeMasternodeManager->GetStatus());
|
||||
mnObj.pushKV("state", node.mn_activeman->GetStateString());
|
||||
mnObj.pushKV("status", node.mn_activeman->GetStatus());
|
||||
|
||||
return mnObj;
|
||||
}
|
||||
|
@ -275,7 +275,8 @@ static void quorum_dkgstatus_help(const JSONRPCRequest& request)
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue quorum_dkgstatus(const JSONRPCRequest& request, CDeterministicMNManager& dmnman, const ChainstateManager& chainman, const CSporkManager& sporkman, const LLMQContext& llmq_ctx)
|
||||
static UniValue quorum_dkgstatus(const JSONRPCRequest& request, CDeterministicMNManager& dmnman, const CActiveMasternodeManager* mn_activeman,
|
||||
const ChainstateManager& chainman, const CSporkManager& sporkman, const LLMQContext& llmq_ctx)
|
||||
{
|
||||
quorum_dkgstatus_help(request);
|
||||
|
||||
@ -295,7 +296,11 @@ static UniValue quorum_dkgstatus(const JSONRPCRequest& request, CDeterministicMN
|
||||
CBlockIndex* pindexTip = WITH_LOCK(cs_main, return chainman.ActiveChain().Tip());
|
||||
int tipHeight = pindexTip->nHeight;
|
||||
|
||||
auto proTxHash = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash);
|
||||
const uint256 proTxHash = [&mn_activeman]() {
|
||||
if (!fMasternodeMode) return uint256();
|
||||
CHECK_NONFATAL(mn_activeman);
|
||||
return WITH_LOCK(mn_activeman->cs, return mn_activeman->GetProTxHash());
|
||||
}();
|
||||
|
||||
UniValue minableCommitments(UniValue::VARR);
|
||||
UniValue quorumArrConnections(UniValue::VARR);
|
||||
@ -879,7 +884,7 @@ static UniValue _quorum(const JSONRPCRequest& request)
|
||||
} else if (command == "quorumdkginfo") {
|
||||
return quorum_dkginfo(new_request, llmq_ctx, chainman);
|
||||
} else if (command == "quorumdkgstatus") {
|
||||
return quorum_dkgstatus(new_request, *node.dmnman, chainman, *node.sporkman, llmq_ctx);
|
||||
return quorum_dkgstatus(new_request, *node.dmnman, node.mn_activeman, chainman, *node.sporkman, llmq_ctx);
|
||||
} else if (command == "quorummemberof") {
|
||||
return quorum_memberof(new_request, chainman, node, llmq_ctx);
|
||||
} else if (command == "quorumsign" || command == "quorumverify" || command == "quorumhasrecsig" || command == "quorumgetrecsig" || command == "quorumisconflicting") {
|
||||
|
@ -111,11 +111,12 @@ void DashTestSetup(NodeContext& node, const CChainParams& chainparams)
|
||||
|
||||
::deterministicMNManager = std::make_unique<CDeterministicMNManager>(chainstate, *node.connman, *node.evodb);
|
||||
node.dmnman = ::deterministicMNManager.get();
|
||||
node.cj_ctx = std::make_unique<CJContext>(chainstate, *node.connman, *node.dmnman, *node.mempool, *node.mn_sync, /* relay_txes */ true);
|
||||
node.cj_ctx = std::make_unique<CJContext>(chainstate, *node.connman, *node.dmnman, *node.mempool, /* mn_activeman = */ nullptr, *node.mn_sync, /* relay_txes = */ true);
|
||||
#ifdef ENABLE_WALLET
|
||||
node.coinjoin_loader = interfaces::MakeCoinJoinLoader(*node.cj_ctx->walletman);
|
||||
#endif // ENABLE_WALLET
|
||||
node.llmq_ctx = std::make_unique<LLMQContext>(chainstate, *node.connman, *node.dmnman, *node.evodb, *node.mnhf_manager, *node.sporkman, *node.mempool, node.peerman, true, false);
|
||||
node.llmq_ctx = std::make_unique<LLMQContext>(chainstate, *node.connman, *node.dmnman, *node.evodb, *node.mnhf_manager, *node.sporkman, *node.mempool,
|
||||
/* mn_activeman = */ nullptr, node.peerman, /* unit_tests = */ true, /* wipe = */ false);
|
||||
node.chain_helper = std::make_unique<CChainstateHelper>(*node.cpoolman, *node.dmnman, *node.mnhf_manager, *node.govman, *(node.llmq_ctx->quorum_block_processor),
|
||||
chainparams.GetConsensus(), *node.mn_sync, *node.sporkman, *(node.llmq_ctx->clhandler));
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ EXPECTED_CIRCULAR_DEPENDENCIES=(
|
||||
"spork -> validation -> spork"
|
||||
"governance/governance -> validation -> governance/governance"
|
||||
"evo/deterministicmns -> validationinterface -> governance/vote -> evo/deterministicmns"
|
||||
"governance/vote -> validation -> validationinterface -> governance/vote"
|
||||
"governance/vote -> masternode/node -> validationinterface -> governance/vote"
|
||||
"llmq/signing -> masternode/node -> validationinterface -> llmq/signing"
|
||||
"evo/mnhftx -> validation -> evo/mnhftx"
|
||||
"evo/deterministicmns -> validation -> evo/deterministicmns"
|
||||
|
Loading…
Reference in New Issue
Block a user