Skip to content

Commit

Permalink
net: introduce masternode-only connections.
Browse files Browse the repository at this point in the history
Connections only used for quorums related messages.
  • Loading branch information
furszy committed Jan 7, 2022
1 parent 711b874 commit 26a3cf5
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/masternode-sync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ bool CMasternodeSync::SyncWithNode(CNode* pnode, bool fLegacyMnObsolete)
return false;
}

if (pnode->nVersion < ActiveProtocol()) {
if (pnode->nVersion < ActiveProtocol() || !pnode->CanRelay()) {
return true; // move to next peer
}

Expand Down
20 changes: 17 additions & 3 deletions src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,7 @@ void CNode::copyStats(CNodeStats& stats, const std::vector<bool>& m_asmap)
X(nRecvBytes);
}
X(fWhitelisted);
X(m_masternode_connection);

// It is common for nodes with good ping times to suddenly become lagged,
// due to a new block arriving or other large transfer.
Expand Down Expand Up @@ -1545,7 +1546,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
{
LOCK(cs_vNodes);
for (const CNode* pnode : vNodes) {
if (!pnode->fInbound && !pnode->fAddnode) {
if (!pnode->fInbound && !pnode->fAddnode && !pnode->m_masternode_connection) {
// Netgroups for inbound and addnode peers are not excluded because our goal here
// is to not use multiple of our limited outbound slots on a single netgroup
// but inbound and addnode peers do not use our outbound slots. Inbound peers
Expand Down Expand Up @@ -1723,7 +1724,7 @@ void CConnman::ThreadOpenAddedConnections()
}

// if successful, this moves the passed grant to the constructed node
void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant* grantOutbound, const char* pszDest, bool fOneShot, bool fFeeler, bool fAddnode)
void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant* grantOutbound, const char* pszDest, bool fOneShot, bool fFeeler, bool fAddnode, bool masternode_connection)
{
//
// Initiate outbound network connection
Expand Down Expand Up @@ -1751,6 +1752,8 @@ void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai
pnode->fFeeler = true;
if (fAddnode)
pnode->fAddnode = true;
if (masternode_connection)
pnode->m_masternode_connection = true;

m_msgproc->InitializeNode(pnode);
{
Expand All @@ -1761,6 +1764,8 @@ void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai

void CConnman::ThreadMessageHandler()
{
int64_t nLastSendMessagesTimeMasternodes = 0;

while (!flagInterruptMsgProc) {
std::vector<CNode*> vNodesCopy;
{
Expand All @@ -1773,6 +1778,13 @@ void CConnman::ThreadMessageHandler()

bool fMoreWork = false;

// Don't send other messages to quorum nodes too often
bool fSkipSendMessagesForMasternodes = true;
if (GetTimeMillis() - nLastSendMessagesTimeMasternodes >= 100) {
fSkipSendMessagesForMasternodes = false;
nLastSendMessagesTimeMasternodes = GetTimeMillis();
}

for (CNode* pnode : vNodesCopy) {
if (pnode->fDisconnect)
continue;
Expand All @@ -1784,7 +1796,7 @@ void CConnman::ThreadMessageHandler()
return;

// Send messages
{
if (!fSkipSendMessagesForMasternodes || !pnode->m_masternode_connection) {
LOCK(pnode->cs_sendProcessing);
m_msgproc->SendMessages(pnode, flagInterruptMsgProc);
}
Expand Down Expand Up @@ -2316,6 +2328,7 @@ void CConnman::RelayInv(CInv& inv)
for (CNode* pnode : vNodes){
if (!pnode->fSuccessfullyConnected) continue;
if ((pnode->nServices == NODE_BLOOM_WITHOUT_MN) && inv.IsMasterNodeType()) continue;
if (!pnode->CanRelay()) continue;
if (pnode->nVersion >= ActiveProtocol())
pnode->PushInventory(inv);
}
Expand Down Expand Up @@ -2401,6 +2414,7 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn
fWhitelisted = false;
fOneShot = false;
fAddnode = false;
m_masternode_connection = false;
fClient = false; // set by version message
fFeeler = false;
fSuccessfullyConnected = false;
Expand Down
7 changes: 6 additions & 1 deletion src/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ class CConnman
void Interrupt();
bool GetNetworkActive() const { return fNetworkActive; };
void SetNetworkActive(bool active);
void OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant* grantOutbound = nullptr, const char* strDest = nullptr, bool fOneShot = false, bool fFeeler = false, bool fAddnode = false);
void OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant* grantOutbound = nullptr, const char* strDest = nullptr, bool fOneShot = false, bool fFeeler = false, bool fAddnode = false, bool masternode_connection = false);
bool CheckIncomingNonce(uint64_t nonce);

bool ForNode(NodeId id, std::function<bool(CNode* pnode)> func);
Expand Down Expand Up @@ -535,6 +535,7 @@ class CNodeStats
double dPingWait;
std::string addrLocal;
uint32_t m_mapped_as;
bool m_masternode_connection;
};


Expand Down Expand Up @@ -626,6 +627,7 @@ class CNode
bool fFeeler; // If true this node is being used as a short lived feeler.
bool fOneShot;
bool fAddnode;
bool m_masternode_connection{false}; // If true this node is only used for quorum related messages.
bool fClient;
const bool fInbound;
/**
Expand Down Expand Up @@ -866,6 +868,9 @@ class CNode
std::string GetAddrName() const;
//! Sets the addrName only if it was not previously set
void MaybeSetAddrName(const std::string& addrNameIn);

// todo: add iqr connection
bool CanRelay() const { return !m_masternode_connection; }
};

class CExplicitNetCleanup
Expand Down
33 changes: 30 additions & 3 deletions src/net_processing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ void PushNodeVersion(CNode* pnode, CConnman* connman, int64_t nTime)
CAddress addrMe = CAddress(CService(), nLocalNodeServices);

connman->PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, PROTOCOL_VERSION, (uint64_t)nLocalNodeServices, nTime, addrYou, addrMe,
nonce, strSubVersion, nNodeStartingHeight, true));
nonce, strSubVersion, nNodeStartingHeight, true, pnode->m_masternode_connection));

if (fLogIPs)
LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nNodeStartingHeight, addrMe.ToString(), addrYou.ToString(), nodeid);
Expand Down Expand Up @@ -702,6 +702,10 @@ void PeerLogicValidation::UpdatedBlockTip(const CBlockIndex* pindexNew, const CB
const uint256& hashNewTip = pindexNew->GetBlockHash();
// Relay inventory, but don't relay old inventory during initial block download.
connman->ForEachNode([nNewHeight, hashNewTip](CNode* pnode) {
// Don't sync from MN only connections.
if (!pnode->CanRelay()) {
return;
}
if (nNewHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 0)) {
pnode->PushInventory(CInv(MSG_BLOCK, hashNewTip));
}
Expand Down Expand Up @@ -1159,6 +1163,22 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR
if (!vRecv.empty()) {
vRecv >> fRelay;
}
// Check if this is a quorum connection
if (!vRecv.empty()) {
bool fOtherMasternode = false;
vRecv >> fOtherMasternode;
if (pfrom->fInbound) {
pfrom->m_masternode_connection = fOtherMasternode;
if (fOtherMasternode) {
LogPrint(BCLog::NET, "peer=%d is an inbound masternode connection, not relaying anything to it\n", pfrom->GetId());
if (!fMasterNode) { // global MN flag
LogPrint(BCLog::NET, "but we're not a masternode, disconnecting\n");
pfrom->fDisconnect = true;
return true;
}
}
}
}

// Disconnect if we connected to ourself
if (pfrom->fInbound && !connman->CheckIncomingNonce(nNonce)) {
Expand Down Expand Up @@ -1456,6 +1476,13 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR


else if (strCommand == NetMsgType::GETBLOCKS || strCommand == NetMsgType::GETHEADERS) {

// Don't relay blocks inv to masternode-only connections
if (!pfrom->CanRelay()) {
LogPrint(BCLog::NET, "getblocks, don't relay blocks inv to masternode connection. peer=%d\n", pfrom->GetId());
return true;
}

CBlockLocator locator;
uint256 hashStop;
vRecv >> locator >> hashStop;
Expand Down Expand Up @@ -2221,7 +2248,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto, std::atomic<bool>& interruptM
if (pindexBestHeader == NULL)
pindexBestHeader = chainActive.Tip();
bool fFetch = state.fPreferredDownload || (nPreferredDownload == 0 && !pto->fClient && !pto->fOneShot); // Download if this is a nice peer, or we have no nice peers and this one might do.
if (!state.fSyncStarted && !pto->fClient && !fImporting && !fReindex) {
if (!state.fSyncStarted && !pto->fClient && !fImporting && !fReindex && pto->CanRelay()) {
// Only actively request headers from a single peer, unless we're close to end of initial download.
if ((nSyncStarted == 0 && fFetch) || pindexBestHeader->GetBlockTime() > GetAdjustedTime() - 6 * 60 * 60) { // NOTE: was "close to today" and 24h in Bitcoin
state.fSyncStarted = true;
Expand Down Expand Up @@ -2383,7 +2410,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto, std::atomic<bool>& interruptM
// Message: getdata (blocks)
//
std::vector<CInv> vGetData;
if (!pto->fClient && fFetch && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
if (!pto->fClient && pto->CanRelay() && fFetch && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
std::vector<const CBlockIndex*> vToDownload;
NodeId staller = -1;
FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller);
Expand Down
2 changes: 2 additions & 0 deletions src/rpc/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ UniValue getpeerinfo(const JSONRPCRequest& request)
" \"subver\": \"/Pivx Core:x.x.x.x/\", (string) The string version\n"
" \"inbound\": true|false, (boolean) Inbound (true) or Outbound (false)\n"
" \"addnode\": true|false, (boolean) Whether connection was due to addnode and is using an addnode slot\n"
" \"masternode\": true|false, (boolean) Whether the connection is only for masternode quorums related messages\n"
" \"startingheight\": n, (numeric) The starting height (block) of the peer\n"
" \"banscore\": n, (numeric) The ban score\n"
" \"synced_headers\": n, (numeric) The last header we have in common with this peer\n"
Expand Down Expand Up @@ -151,6 +152,7 @@ UniValue getpeerinfo(const JSONRPCRequest& request)
obj.pushKV("subver", stats.cleanSubVer);
obj.pushKV("inbound", stats.fInbound);
obj.pushKV("addnode", stats.fAddnode);
obj.pushKV("masternode", stats.m_masternode_connection);
obj.pushKV("startingheight", stats.nStartingHeight);
if (fStateStats) {
obj.pushKV("banscore", statestats.nMisbehavior);
Expand Down

0 comments on commit 26a3cf5

Please sign in to comment.