Merge pull request #4921 from PastaPastaPasta/v18.x-rc9

[v18.x] rc9 backports
This commit is contained in:
UdjinM6 2022-07-18 22:44:37 +03:00 committed by GitHub
commit fa12c9685c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 91 additions and 20 deletions

View File

@ -2,7 +2,7 @@ AC_PREREQ([2.69])
define(_CLIENT_VERSION_MAJOR, 18)
define(_CLIENT_VERSION_MINOR, 0)
define(_CLIENT_VERSION_BUILD, 0)
define(_CLIENT_VERSION_RC, 8)
define(_CLIENT_VERSION_RC, 9)
define(_CLIENT_VERSION_IS_RELEASE, false)
define(_COPYRIGHT_YEAR, 2022)
define(_COPYRIGHT_HOLDERS,[The %s developers])

View File

@ -732,6 +732,8 @@ std::optional<std::vector<CFinalCommitment>> CQuorumBlockProcessor::GetMineableC
break;
}
if (HasMinedCommitment(llmqParams.type, quorumHash)) continue;
LOCK(minableCommitmentsCs);
auto k = std::make_pair(llmqParams.type, quorumHash);

View File

@ -472,10 +472,9 @@ void CDKGSession::VerifyConnectionAndMinProtoVersions() const
logger.Batch("%s does not have min proto version %d (has %d)", m->dmn->proTxHash.ToString(), MIN_MASTERNODE_PROTO_VERSION, it->second);
}
auto lastOutbound = mmetaman.GetMetaInfo(m->dmn->proTxHash)->GetLastOutboundSuccess();
if (GetAdjustedTime() - lastOutbound > 60 * 60) {
if (mmetaman.GetMetaInfo(m->dmn->proTxHash)->OutboundFailedTooManyTimes()) {
m->badConnection = true;
logger.Batch("%s no outbound connection since %d seconds", m->dmn->proTxHash.ToString(), GetAdjustedTime() - lastOutbound);
logger.Batch("%s failed to connect to it too many times", m->dmn->proTxHash.ToString());
}
}
}

View File

@ -243,7 +243,7 @@ void CQuorumManager::UpdatedBlockTip(const CBlockIndex* pindexNew, bool fInitial
}
for (auto& params : Params().GetConsensus().llmqs) {
EnsureQuorumConnections(params, pindexNew);
CheckQuorumConnections(params, pindexNew);
}
{
@ -262,7 +262,7 @@ void CQuorumManager::UpdatedBlockTip(const CBlockIndex* pindexNew, bool fInitial
TriggerQuorumDataRecoveryThreads(pindexNew);
}
void CQuorumManager::EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pindexNew) const
void CQuorumManager::CheckQuorumConnections(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pindexNew) const
{
auto lastQuorums = ScanQuorums(llmqParams.type, pindexNew, (size_t)llmqParams.keepOldConnections);
@ -289,11 +289,36 @@ void CQuorumManager::EnsureQuorumConnections(const Consensus::LLMQParams& llmqPa
LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- llmqType[%d] h[%d] keeping mn quorum connections for quorum: [%d:%s]\n", __func__, int(llmqParams.type), pindexNew->nHeight, curDkgHeight, curDkgBlock.ToString());
}
const auto myProTxHash = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash);
bool isISType = llmqParams.type == Params().GetConsensus().llmqTypeInstantSend ||
llmqParams.type == Params().GetConsensus().llmqTypeDIP0024InstantSend;
bool watchOtherISQuorums = isISType && !myProTxHash.IsNull() &&
ranges::any_of(lastQuorums, [&myProTxHash](const auto& old_quorum){
return old_quorum->IsMember(myProTxHash);
});
for (const auto& quorum : lastQuorums) {
if (CLLMQUtils::EnsureQuorumConnections(llmqParams, quorum->m_quorum_base_block_index, WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash))) {
if (CLLMQUtils::EnsureQuorumConnections(llmqParams, quorum->m_quorum_base_block_index, myProTxHash)) {
if (connmanQuorumsToDelete.erase(quorum->qc->quorumHash) > 0) {
LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- llmqType[%d] h[%d] keeping mn quorum connections for quorum: [%d:%s]\n", __func__, int(llmqParams.type), pindexNew->nHeight, quorum->m_quorum_base_block_index->nHeight, quorum->m_quorum_base_block_index->GetBlockHash().ToString());
}
} else if (watchOtherISQuorums && !quorum->IsMember(myProTxHash)) {
std::set<uint256> connections;
const auto& cindexes = CLLMQUtils::CalcDeterministicWatchConnections(llmqParams.type, quorum->m_quorum_base_block_index, quorum->members.size(), 1);
for (auto idx : cindexes) {
connections.emplace(quorum->members[idx]->proTxHash);
}
if (!connections.empty()) {
if (!g_connman->HasMasternodeQuorumNodes(llmqParams.type, quorum->m_quorum_base_block_index->GetBlockHash())) {
LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- llmqType[%d] h[%d] adding mn inter-quorum connections for quorum: [%d:%s]\n", __func__, int(llmqParams.type), pindexNew->nHeight, quorum->m_quorum_base_block_index->nHeight, quorum->m_quorum_base_block_index->GetBlockHash().ToString());
g_connman->SetMasternodeQuorumNodes(llmqParams.type, quorum->m_quorum_base_block_index->GetBlockHash(), connections);
g_connman->SetMasternodeQuorumRelayMembers(llmqParams.type, quorum->m_quorum_base_block_index->GetBlockHash(), connections);
}
if (connmanQuorumsToDelete.erase(quorum->qc->quorumHash) > 0) {
LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- llmqType[%d] h[%d] keeping mn inter-quorum connections for quorum: [%d:%s]\n", __func__, int(llmqParams.type), pindexNew->nHeight, quorum->m_quorum_base_block_index->nHeight, quorum->m_quorum_base_block_index->GetBlockHash().ToString());
}
}
}
}
for (const auto& quorumHash : connmanQuorumsToDelete) {

View File

@ -224,7 +224,7 @@ public:
private:
// all private methods here are cs_main-free
void EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, const CBlockIndex *pindexNew) const;
void CheckQuorumConnections(const Consensus::LLMQParams& llmqParams, const CBlockIndex *pindexNew) const;
CQuorumPtr BuildQuorumFromCommitment(Consensus::LLMQType llmqType, const CBlockIndex* pQuorumBaseBlockIndex) const EXCLUSIVE_LOCKS_REQUIRED(quorumsCacheCs);
bool BuildQuorumContributions(const CFinalCommitmentPtr& fqc, const std::shared_ptr<CQuorum>& quorum) const;

View File

@ -701,13 +701,24 @@ std::set<size_t> CLLMQUtils::CalcDeterministicWatchConnections(Consensus::LLMQTy
bool CLLMQUtils::EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pQuorumBaseBlockIndex, const uint256& myProTxHash)
{
if (!fMasternodeMode && !CLLMQUtils::IsWatchQuorumsEnabled()) {
return false;
}
auto members = GetAllQuorumMembers(llmqParams.type, pQuorumBaseBlockIndex);
if (members.empty()) {
return false;
}
bool isMember = std::find_if(members.begin(), members.end(), [&](const auto& dmn) { return dmn->proTxHash == myProTxHash; }) != members.end();
if (!isMember && !CLLMQUtils::IsWatchQuorumsEnabled()) {
return false;
}
LogPrint(BCLog::NET_NETCONN, "CLLMQUtils::%s -- isMember=%d for quorum %s:\n",
__func__, isMember, pQuorumBaseBlockIndex->GetBlockHash().ToString());
std::set<uint256> connections;
std::set<uint256> relayMembers;
if (isMember) {

View File

@ -2478,8 +2478,7 @@ void CConnman::ThreadOpenMasternodeConnections()
LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- connection failed for masternode %s, service=%s\n", __func__, connectToDmn->proTxHash.ToString(), connectToDmn->pdmnState->addr.ToString(false));
// Will take a few consequent failed attempts to PoSe-punish a MN.
if (mmetaman.GetMetaInfo(connectToDmn->proTxHash)->OutboundFailedTooManyTimes()) {
LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- failed to connect to masternode %s too many times, resetting outbound success time\n", __func__, connectToDmn->proTxHash.ToString());
mmetaman.GetMetaInfo(connectToDmn->proTxHash)->SetLastOutboundSuccess(0);
LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- failed to connect to masternode %s too many times\n", __func__, connectToDmn->proTxHash.ToString());
}
}
}
@ -3362,6 +3361,9 @@ size_t CConnman::GetNodeCount(NumConnections flags)
if (pnode->fDisconnect) {
continue;
}
if ((flags & CONNECTIONS_VERIFIED) && pnode->GetVerifiedProRegTxHash().IsNull()) {
continue;
}
if (flags & (pnode->fInbound ? CONNECTIONS_IN : CONNECTIONS_OUT)) {
nNum++;
}

View File

@ -142,6 +142,9 @@ public:
CONNECTIONS_IN = (1U << 0),
CONNECTIONS_OUT = (1U << 1),
CONNECTIONS_ALL = (CONNECTIONS_IN | CONNECTIONS_OUT),
CONNECTIONS_VERIFIED = (1U << 2),
CONNECTIONS_VERIFIED_IN = (CONNECTIONS_VERIFIED | CONNECTIONS_IN),
CONNECTIONS_VERIFIED_OUT = (CONNECTIONS_VERIFIED | CONNECTIONS_OUT),
};
enum SocketEventsMode {

View File

@ -494,7 +494,12 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request)
" ],\n"
" \"localrelay\" : true|false, (boolean) true if transaction relay is requested from peers\n"
" \"timeoffset\" : xxxxx, (numeric) the time offset\n"
" \"connections\" : xxxxx, (numeric) the number of connections\n"
" \"connections\" : xxxxx, (numeric) the number of inbound and outbound connections\n"
" \"inboundconnections\" : xxxxx, (numeric) the number of inbound connections\n"
" \"outboundconnections\" : xxxxx, (numeric) the number of outbound connections\n"
" \"mnconnections\" : xxxxx, (numeric) the number of verified mn connections\n"
" \"inboundmnconnections\" : xxxxx, (numeric) the number of inbound verified mn connections\n"
" \"outboundmnconnections\" : xxxxx, (numeric) the number of outbound verified mn connections\n"
" \"networkactive\" : true|false, (boolean) whether p2p networking is enabled\n"
" \"socketevents\" : \"xxx/\", (string) the socket events mode, either kqueue, epoll, poll or select\n"
" \"networks\" : [ (json array) information per network\n"
@ -542,6 +547,11 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request)
if (g_connman) {
obj.pushKV("networkactive", g_connman->GetNetworkActive());
obj.pushKV("connections", (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL));
obj.pushKV("inboundconnections", (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_IN));
obj.pushKV("outboundconnections", (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_OUT));
obj.pushKV("mnconnections", (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_VERIFIED));
obj.pushKV("inboundmnconnections", (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_VERIFIED_IN));
obj.pushKV("outboundmnconnections", (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_VERIFIED_OUT));
std::string strSocketEvents;
switch (g_connman->GetSocketEventsMode()) {
case CConnman::SOCKETEVENTS_SELECT:

View File

@ -69,6 +69,20 @@ class LLMQConnections(DashTestFramework):
self.check_reconnects(4)
self.log.info("check that inter-quorum masternode conections are added")
added = False
for mn in self.mninfo:
if len(mn.node.quorum("memberof", mn.proTxHash)) > 0:
try:
with mn.node.assert_debug_log(['adding mn inter-quorum connections']):
self.mine_quorum()
added = True
except:
pass # it's ok to not add connections sometimes
if added:
break
assert added # no way we added none
def check_reconnects(self, expected_connection_count):
self.log.info("disable and re-enable networking on all masternodes")
for mn in self.mninfo:

View File

@ -66,7 +66,7 @@ class LLMQSimplePoSeTest(DashTestFramework):
def isolate_mn(self, mn):
mn.node.setnetworkactive(False)
wait_until(lambda: mn.node.getconnectioncount() == 0)
return True
return True, True
def close_mn_port(self, mn):
self.stop_node(mn.node.index)
@ -77,14 +77,14 @@ class LLMQSimplePoSeTest(DashTestFramework):
if mn2 is not mn:
connect_nodes(mn.node, mn2.node.index)
self.reset_probe_timeouts()
return False
return False, False
def force_old_mn_proto(self, mn):
self.stop_node(mn.node.index)
self.start_masternode(mn, ["-pushversion=70216"])
connect_nodes(mn.node, 0)
self.reset_probe_timeouts()
return False
return False, True
def test_no_banning(self, expected_connections=None):
for i in range(3):
@ -98,15 +98,20 @@ class LLMQSimplePoSeTest(DashTestFramework):
expected_contributors = len(mninfos_online)
for i in range(2):
mn = mninfos_valid.pop()
went_offline = invalidate_proc(mn)
went_offline, instant_ban = invalidate_proc(mn)
if went_offline:
mninfos_online.remove(mn)
expected_contributors -= 1
t = time.time()
while (not self.check_banned(mn)) and (time.time() - t) < 120:
self.reset_probe_timeouts()
self.mine_quorum(expected_connections=expected_connections, expected_members=expected_contributors, expected_contributions=expected_contributors, expected_complaints=expected_contributors-1, expected_commitments=expected_contributors, mninfos_online=mninfos_online, mninfos_valid=mninfos_valid)
# NOTE: Min PoSe penalty is 100 (see CDeterministicMNList::CalcMaxPoSePenalty()),
# so nodes are PoSe-banned in the same DKG they misbehave without being PoSe-punished first.
if not instant_ban:
# it's ok to miss probes/quorum connections up to 5 times
for i in range(5):
self.reset_probe_timeouts()
self.mine_quorum(expected_connections=expected_connections, expected_members=expected_contributors, expected_contributions=expected_contributors, expected_complaints=0, expected_commitments=expected_contributors, mninfos_online=mninfos_online, mninfos_valid=mninfos_valid)
self.reset_probe_timeouts()
self.mine_quorum(expected_connections=expected_connections, expected_members=expected_contributors, expected_contributions=expected_contributors, expected_complaints=expected_contributors-1, expected_commitments=expected_contributors, mninfos_online=mninfos_online, mninfos_valid=mninfos_valid)
assert self.check_banned(mn)
@ -144,7 +149,7 @@ class LLMQSimplePoSeTest(DashTestFramework):
def reset_probe_timeouts(self):
# Make sure all masternodes will reconnect/re-probe
self.bump_mocktime(50 * 60 + 1)
self.bump_mocktime(10 * 60 + 1)
# Sleep a couple of seconds to let mn sync tick to happen
time.sleep(2)