mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 12:32:48 +01:00
Merge pull request #3366 from codablock/pr_fix_mnconns
Multiple fixes for masternode connection handling
This commit is contained in:
commit
c0bb06e766
@ -395,6 +395,7 @@ public:
|
||||
fMineBlocksOnDemand = false;
|
||||
fAllowMultipleAddressesFromGroup = false;
|
||||
fAllowMultiplePorts = false;
|
||||
nLLMQConnectionRetryTimeout = 60;
|
||||
|
||||
nPoolMinParticipants = 3;
|
||||
nPoolMaxParticipants = 5; // TODO: bump on next HF / mandatory upgrade
|
||||
@ -571,6 +572,7 @@ public:
|
||||
fMineBlocksOnDemand = false;
|
||||
fAllowMultipleAddressesFromGroup = false;
|
||||
fAllowMultiplePorts = true;
|
||||
nLLMQConnectionRetryTimeout = 60;
|
||||
|
||||
nPoolMinParticipants = 3; // TODO drop to 2 with next mandatory upgrade
|
||||
nPoolMaxParticipants = 5;
|
||||
@ -727,6 +729,7 @@ public:
|
||||
fMineBlocksOnDemand = false;
|
||||
fAllowMultipleAddressesFromGroup = true;
|
||||
fAllowMultiplePorts = true;
|
||||
nLLMQConnectionRetryTimeout = 60;
|
||||
|
||||
nPoolMinParticipants = 3; // same, drop to 2 w/ breaking change
|
||||
nPoolMaxParticipants = 5;
|
||||
@ -837,6 +840,7 @@ public:
|
||||
fMineBlocksOnDemand = true;
|
||||
fAllowMultipleAddressesFromGroup = true;
|
||||
fAllowMultiplePorts = true;
|
||||
nLLMQConnectionRetryTimeout = 30; // must be lower then the LLMQ signing session timeout so that tests have control over failing behavior
|
||||
|
||||
nFulfilledRequestExpireTime = 5*60; // fulfilled requests expire in 5 minutes
|
||||
nPoolMinParticipants = 2;
|
||||
|
@ -70,6 +70,8 @@ public:
|
||||
bool AllowMultipleAddressesFromGroup() const { return fAllowMultipleAddressesFromGroup; }
|
||||
/** Allow nodes with the same address and multiple ports */
|
||||
bool AllowMultiplePorts() const { return fAllowMultiplePorts; }
|
||||
/** How long to wait until we allow retrying of a LLMQ connection */
|
||||
int LLMQConnectionRetryTimeout() const { return nLLMQConnectionRetryTimeout; }
|
||||
/** Return the BIP70 network string (main, test or regtest) */
|
||||
std::string NetworkIDString() const { return strNetworkID; }
|
||||
/** Return the list of hostnames to look up for DNS seeds */
|
||||
@ -112,6 +114,7 @@ protected:
|
||||
bool fMineBlocksOnDemand;
|
||||
bool fAllowMultipleAddressesFromGroup;
|
||||
bool fAllowMultiplePorts;
|
||||
int nLLMQConnectionRetryTimeout;
|
||||
CCheckpointData checkpointData;
|
||||
ChainTxData chainTxData;
|
||||
int nPoolMinParticipants;
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
CMasternodeMetaMan mmetaman;
|
||||
|
||||
const std::string CMasternodeMetaMan::SERIALIZATION_VERSION_STRING = "CMasternodeMetaMan-Version-1";
|
||||
const std::string CMasternodeMetaMan::SERIALIZATION_VERSION_STRING = "CMasternodeMetaMan-Version-2";
|
||||
|
||||
void CMasternodeMetaInfo::AddGovernanceVote(const uint256& nGovernanceObjectHash)
|
||||
{
|
||||
|
@ -33,6 +33,8 @@ private:
|
||||
// KEEP TRACK OF GOVERNANCE ITEMS EACH MASTERNODE HAS VOTE UPON FOR RECALCULATION
|
||||
std::map<uint256, int> mapGovernanceObjectsVotedOn;
|
||||
|
||||
int64_t lastOutboundAttempt = 0;
|
||||
|
||||
public:
|
||||
CMasternodeMetaInfo() {}
|
||||
explicit CMasternodeMetaInfo(const uint256& _proTxHash) : proTxHash(_proTxHash) {}
|
||||
@ -40,7 +42,8 @@ public:
|
||||
proTxHash(ref.proTxHash),
|
||||
nLastDsq(ref.nLastDsq),
|
||||
nMixingTxCount(ref.nMixingTxCount),
|
||||
mapGovernanceObjectsVotedOn(ref.mapGovernanceObjectsVotedOn)
|
||||
mapGovernanceObjectsVotedOn(ref.mapGovernanceObjectsVotedOn),
|
||||
lastOutboundAttempt(ref.lastOutboundAttempt)
|
||||
{
|
||||
}
|
||||
|
||||
@ -53,6 +56,7 @@ public:
|
||||
READWRITE(nLastDsq);
|
||||
READWRITE(nMixingTxCount);
|
||||
READWRITE(mapGovernanceObjectsVotedOn);
|
||||
READWRITE(lastOutboundAttempt);
|
||||
}
|
||||
|
||||
public:
|
||||
@ -66,6 +70,9 @@ public:
|
||||
void AddGovernanceVote(const uint256& nGovernanceObjectHash);
|
||||
|
||||
void RemoveGovernanceObject(const uint256& nGovernanceObjectHash);
|
||||
|
||||
void SetLastOutboundAttempt(int64_t t) { LOCK(cs); lastOutboundAttempt = t; }
|
||||
int64_t GetLastOutboundAttempt() const { LOCK(cs); return lastOutboundAttempt; }
|
||||
};
|
||||
typedef std::shared_ptr<CMasternodeMetaInfo> CMasternodeMetaInfoPtr;
|
||||
|
||||
|
78
src/net.cpp
78
src/net.cpp
@ -25,6 +25,7 @@
|
||||
#include <utilstrencodings.h>
|
||||
#include <validation.h>
|
||||
|
||||
#include <masternode/masternode-meta.h>
|
||||
#include <masternode/masternode-sync.h>
|
||||
#include <privatesend/privatesend.h>
|
||||
#include <evo/deterministicmns.h>
|
||||
@ -2099,6 +2100,8 @@ void CConnman::ThreadOpenMasternodeConnections()
|
||||
if (gArgs.IsArgSet("-connect") && gArgs.GetArgs("-connect").size() > 0)
|
||||
return;
|
||||
|
||||
auto& chainParams = Params();
|
||||
|
||||
while (!interruptNet)
|
||||
{
|
||||
if (!interruptNet.sleep_for(std::chrono::milliseconds(1000)))
|
||||
@ -2123,49 +2126,55 @@ void CConnman::ThreadOpenMasternodeConnections()
|
||||
|
||||
// NOTE: Process only one pending masternode at a time
|
||||
|
||||
CService addr;
|
||||
CDeterministicMNCPtr connectToDmn;
|
||||
{ // don't hold lock while calling OpenMasternodeConnection as cs_main is locked deep inside
|
||||
LOCK2(cs_vNodes, cs_vPendingMasternodes);
|
||||
|
||||
std::vector<CService> pending;
|
||||
for (const auto& group : masternodeQuorumNodes) {
|
||||
for (const auto& proRegTxHash : group.second) {
|
||||
auto dmn = mnList.GetMN(proRegTxHash);
|
||||
if (!dmn) {
|
||||
continue;
|
||||
}
|
||||
const auto& addr2 = dmn->pdmnState->addr;
|
||||
if (!connectedNodes.count(addr2) && !IsMasternodeOrDisconnectRequested(addr2) && !connectedProRegTxHashes.count(proRegTxHash)) {
|
||||
auto addrInfo = addrman.GetAddressInfo(addr2);
|
||||
// back off trying connecting to an address if we already tried recently
|
||||
if (addrInfo.IsValid() && nANow - addrInfo.nLastTry < 60) {
|
||||
if (!vPendingMasternodes.empty()) {
|
||||
auto dmn = mnList.GetValidMN(vPendingMasternodes.front());
|
||||
vPendingMasternodes.erase(vPendingMasternodes.begin());
|
||||
if (dmn && !connectedNodes.count(dmn->pdmnState->addr) && !IsMasternodeOrDisconnectRequested(dmn->pdmnState->addr)) {
|
||||
connectToDmn = dmn;
|
||||
LogPrint(BCLog::NET, "CConnman::%s -- opening pending masternode connection to %s, service=%s\n", __func__, dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToString(false));
|
||||
}
|
||||
}
|
||||
|
||||
if (!connectToDmn) {
|
||||
std::vector<CDeterministicMNCPtr> pending;
|
||||
for (const auto& group : masternodeQuorumNodes) {
|
||||
for (const auto& proRegTxHash : group.second) {
|
||||
auto dmn = mnList.GetMN(proRegTxHash);
|
||||
if (!dmn) {
|
||||
continue;
|
||||
}
|
||||
pending.emplace_back(addr2);
|
||||
const auto& addr2 = dmn->pdmnState->addr;
|
||||
if (!connectedNodes.count(addr2) && !IsMasternodeOrDisconnectRequested(addr2) && !connectedProRegTxHashes.count(proRegTxHash)) {
|
||||
int64_t lastAttempt = mmetaman.GetMetaInfo(dmn->proTxHash)->GetLastOutboundAttempt();
|
||||
// back off trying connecting to an address if we already tried recently
|
||||
if (nANow - lastAttempt < chainParams.LLMQConnectionRetryTimeout()) {
|
||||
continue;
|
||||
}
|
||||
pending.emplace_back(dmn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!vPendingMasternodes.empty()) {
|
||||
auto addr2 = vPendingMasternodes.front();
|
||||
vPendingMasternodes.erase(vPendingMasternodes.begin());
|
||||
if (!connectedNodes.count(addr2) && !IsMasternodeOrDisconnectRequested(addr2)) {
|
||||
pending.emplace_back(addr2);
|
||||
if (!pending.empty()) {
|
||||
connectToDmn = pending[GetRandInt(pending.size())];
|
||||
LogPrint(BCLog::NET, "CConnman::%s -- opening quorum connection to %s, service=%s\n", __func__, connectToDmn->proTxHash.ToString(), connectToDmn->pdmnState->addr.ToString(false));
|
||||
}
|
||||
}
|
||||
|
||||
if (pending.empty()) {
|
||||
// nothing to do, keep waiting
|
||||
continue;
|
||||
}
|
||||
|
||||
std::random_shuffle(pending.begin(), pending.end());
|
||||
addr = pending.front();
|
||||
}
|
||||
|
||||
OpenMasternodeConnection(CAddress(addr, NODE_NETWORK));
|
||||
if (!connectToDmn) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mmetaman.GetMetaInfo(connectToDmn->proTxHash)->SetLastOutboundAttempt(nANow);
|
||||
|
||||
OpenMasternodeConnection(CAddress(connectToDmn->pdmnState->addr, NODE_NETWORK));
|
||||
// should be in the list now if connection was opened
|
||||
ForNode(addr, CConnman::AllNodes, [&](CNode* pnode) {
|
||||
ForNode(connectToDmn->pdmnState->addr, CConnman::AllNodes, [&](CNode* pnode) {
|
||||
if (pnode->fDisconnect) {
|
||||
return false;
|
||||
}
|
||||
@ -2777,15 +2786,14 @@ bool CConnman::RemoveAddedNode(const std::string& strNode)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CConnman::AddPendingMasternode(const CService& service)
|
||||
bool CConnman::AddPendingMasternode(const uint256& proTxHash)
|
||||
{
|
||||
LOCK(cs_vPendingMasternodes);
|
||||
for(const auto& s : vPendingMasternodes) {
|
||||
if (service == s)
|
||||
return false;
|
||||
if (std::find(vPendingMasternodes.begin(), vPendingMasternodes.end(), proTxHash) != vPendingMasternodes.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
vPendingMasternodes.push_back(service);
|
||||
vPendingMasternodes.push_back(proTxHash);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -407,7 +407,7 @@ public:
|
||||
bool RemoveAddedNode(const std::string& node);
|
||||
std::vector<AddedNodeInfo> GetAddedNodeInfo();
|
||||
|
||||
bool AddPendingMasternode(const CService& addr);
|
||||
bool AddPendingMasternode(const uint256& proTxHash);
|
||||
bool AddMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash, const std::set<uint256>& proTxHashes);
|
||||
bool HasMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash);
|
||||
std::set<uint256> GetMasternodeQuorums(Consensus::LLMQType llmqType);
|
||||
@ -543,7 +543,7 @@ private:
|
||||
CCriticalSection cs_vOneShots;
|
||||
std::vector<std::string> vAddedNodes GUARDED_BY(cs_vAddedNodes);
|
||||
CCriticalSection cs_vAddedNodes;
|
||||
std::vector<CService> vPendingMasternodes;
|
||||
std::vector<uint256> vPendingMasternodes;
|
||||
std::map<std::pair<Consensus::LLMQType, uint256>, std::set<uint256>> masternodeQuorumNodes; // protected by cs_vPendingMasternodes
|
||||
mutable CCriticalSection cs_vPendingMasternodes;
|
||||
std::vector<CNode*> vNodes;
|
||||
|
@ -1081,7 +1081,7 @@ bool CPrivateSendClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymize
|
||||
nSessionDenom = dsq.nDenom;
|
||||
mixingMasternode = dmn;
|
||||
pendingDsaRequest = CPendingDsaRequest(dmn->pdmnState->addr, CPrivateSendAccept(nSessionDenom, txMyCollateral));
|
||||
connman.AddPendingMasternode(dmn->pdmnState->addr);
|
||||
connman.AddPendingMasternode(dmn->proTxHash);
|
||||
// TODO: add new state POOL_STATE_CONNECTING and bump MIN_PRIVATESEND_PEER_PROTO_VERSION
|
||||
SetState(POOL_STATE_QUEUE);
|
||||
nTimeLastSuccessfulStep = GetTime();
|
||||
@ -1158,7 +1158,7 @@ bool CPrivateSendClientSession::StartNewQueue(CAmount nBalanceNeedsAnonymized, C
|
||||
}
|
||||
|
||||
mixingMasternode = dmn;
|
||||
connman.AddPendingMasternode(dmn->pdmnState->addr);
|
||||
connman.AddPendingMasternode(dmn->proTxHash);
|
||||
pendingDsaRequest = CPendingDsaRequest(dmn->pdmnState->addr, CPrivateSendAccept(nSessionDenom, txMyCollateral));
|
||||
// TODO: add new state POOL_STATE_CONNECTING and bump MIN_PRIVATESEND_PEER_PROTO_VERSION
|
||||
SetState(POOL_STATE_QUEUE);
|
||||
|
@ -60,6 +60,9 @@ class LLMQ_IS_RetroactiveSigning(DashTestFramework):
|
||||
self.wait_for_tx(txid, self.nodes[1])
|
||||
self.wait_for_tx(txid, self.nodes[2])
|
||||
reconnect_isolated_node(self.nodes[3], 0)
|
||||
# Make sure nodes actually try re-connecting quorum connections
|
||||
self.bump_mocktime(30)
|
||||
set_node_times(self.nodes, self.mocktime)
|
||||
self.wait_for_mnauth(self.nodes[3], 2)
|
||||
# node 3 fully reconnected but the TX wasn't relayed to it, so there should be no IS lock
|
||||
self.wait_for_instantlock(txid, self.nodes[0], False, 5)
|
||||
@ -91,6 +94,9 @@ class LLMQ_IS_RetroactiveSigning(DashTestFramework):
|
||||
self.wait_for_tx(txid, self.nodes[1])
|
||||
self.wait_for_tx(txid, self.nodes[2])
|
||||
reconnect_isolated_node(self.nodes[3], 0)
|
||||
# Make sure nodes actually try re-connecting quorum connections
|
||||
self.bump_mocktime(30)
|
||||
set_node_times(self.nodes, self.mocktime)
|
||||
self.wait_for_mnauth(self.nodes[3], 2)
|
||||
# node 3 fully reconnected but the TX wasn't relayed to it, so there should be no IS lock
|
||||
self.wait_for_instantlock(txid, self.nodes[0], False, 5)
|
||||
@ -133,6 +139,9 @@ class LLMQ_IS_RetroactiveSigning(DashTestFramework):
|
||||
set_node_times(self.nodes, self.mocktime)
|
||||
time.sleep(2) # make sure Cleanup() is called
|
||||
reconnect_isolated_node(self.nodes[3], 0)
|
||||
# Make sure nodes actually try re-connecting quorum connections
|
||||
self.bump_mocktime(30)
|
||||
set_node_times(self.nodes, self.mocktime)
|
||||
self.wait_for_mnauth(self.nodes[3], 2)
|
||||
# node 3 fully reconnected but the signing session is already timed out on all nodes, so no IS lock
|
||||
self.wait_for_instantlock(txid, self.nodes[0], False, 5)
|
||||
@ -158,6 +167,9 @@ class LLMQ_IS_RetroactiveSigning(DashTestFramework):
|
||||
set_node_times(self.nodes, self.mocktime)
|
||||
time.sleep(2) # make sure Cleanup() is called
|
||||
reconnect_isolated_node(self.nodes[3], 0)
|
||||
# Make sure nodes actually try re-connecting quorum connections
|
||||
self.bump_mocktime(30)
|
||||
set_node_times(self.nodes, self.mocktime)
|
||||
self.wait_for_mnauth(self.nodes[3], 2)
|
||||
self.nodes[0].sendrawtransaction(rawtx)
|
||||
# Make sure nodes 1 and 2 received the TX
|
||||
|
Loading…
Reference in New Issue
Block a user