From b621cfb5fb44bf1ed736aa19e0d4c7b4c405d4f4 Mon Sep 17 00:00:00 2001
From: Oleg Girko
Date: Thu, 27 Jul 2017 15:28:05 +0100
Subject: [PATCH] Backport Bitcoin PR#8708: net: have CConnman handle message
sending (#1553)
* serialization: teach serializers variadics
Also add a variadic CDataStream ctor for ease-of-use.
* connman is in charge of pushing messages
The changes here are dense and subtle, but hopefully all is more explicit
than before.
- CConnman is now in charge of sending data rather than the nodes themselves.
This is necessary because many decisions need to be made with all nodes in
mind, and a model that requires the nodes calling up to their manager quickly
turns to spaghetti.
- The per-node-serializer (ssSend) has been replaced with a (quasi-)const
send-version. Since the send version for serialization can only change once
per connection, we now explicitly tag messages with INIT_PROTO_VERSION if
they are sent before the handshake. With this done, there's no need to lock
for access to nSendVersion.
Also, a new stream is used for each message, so there's no need to lock
during the serialization process.
- This takes care of accounting for optimistic sends, so the
nOptimisticBytesWritten hack can be removed.
- -dropmessagestest and -fuzzmessagestest have not been preserved, as I suspect
they haven't been used in years.
* net: switch all callers to connman for pushing messages
Drop all of the old stuff.
* drop the optimistic write counter hack
This is now handled properly in realtime.
* net: remove now-unused ssSend and Fuzz
* net: construct CNodeStates in place
* net: handle version push in InitializeNode
---
src/alert.cpp | 4 +-
src/alert.h | 3 +-
src/governance.cpp | 8 +-
src/main.cpp | 144 ++++++++++--------
src/masternode-payments.cpp | 8 +-
src/masternode-sync.cpp | 12 +-
src/masternodeman.cpp | 10 +-
src/net.cpp | 186 +++++++----------------
src/net.h | 281 +++++++----------------------------
src/privatesend-client.cpp | 8 +-
src/privatesend-server.cpp | 6 +-
src/privatesend.cpp | 2 +-
src/sendalert.cpp | 2 +-
src/serialize.h | 49 ++++++
src/spork.cpp | 2 +-
src/streams.h | 7 +
src/test/DoS_tests.cpp | 12 +-
src/test/serialize_tests.cpp | 71 ++++++++-
18 files changed, 363 insertions(+), 452 deletions(-)
diff --git a/src/alert.cpp b/src/alert.cpp
index 75cfb091af1fd..1dc272cda886d 100644
--- a/src/alert.cpp
+++ b/src/alert.cpp
@@ -125,7 +125,7 @@ bool CAlert::AppliesToMe() const
return AppliesTo(PROTOCOL_VERSION, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector()));
}
-bool CAlert::RelayTo(CNode* pnode) const
+bool CAlert::RelayTo(CNode* pnode, CConnman& connman) const
{
if (!IsInEffect())
return false;
@@ -139,7 +139,7 @@ bool CAlert::RelayTo(CNode* pnode) const
AppliesToMe() ||
GetAdjustedTime() < nRelayUntil)
{
- pnode->PushMessage(NetMsgType::ALERT, *this);
+ connman.PushMessage(pnode, NetMsgType::ALERT, *this);
return true;
}
}
diff --git a/src/alert.h b/src/alert.h
index a0b16d5731836..f2201172430dd 100644
--- a/src/alert.h
+++ b/src/alert.h
@@ -16,6 +16,7 @@
class CAlert;
class CNode;
+class CConnman;
class uint256;
extern std::map mapAlerts;
@@ -99,7 +100,7 @@ class CAlert : public CUnsignedAlert
bool Cancels(const CAlert& alert) const;
bool AppliesTo(int nVersion, const std::string& strSubVerIn) const;
bool AppliesToMe() const;
- bool RelayTo(CNode* pnode) const;
+ bool RelayTo(CNode* pnode, CConnman& connman) const;
bool Sign();
bool CheckSignature(const std::vector& alertKey) const;
bool ProcessAlert(const std::vector& alertKey, bool fThread = true); // fThread means run -alertnotify in a free-running thread
diff --git a/src/governance.cpp b/src/governance.cpp
index f3caefb26abb1..22c781500a652 100644
--- a/src/governance.cpp
+++ b/src/governance.cpp
@@ -834,8 +834,8 @@ void CGovernanceManager::Sync(CNode* pfrom, const uint256& nProp, const CBloomFi
}
}
- pfrom->PushMessage(NetMsgType::SYNCSTATUSCOUNT, MASTERNODE_SYNC_GOVOBJ, nObjCount);
- pfrom->PushMessage(NetMsgType::SYNCSTATUSCOUNT, MASTERNODE_SYNC_GOVOBJ_VOTE, nVoteCount);
+ g_connman->PushMessage(pfrom, NetMsgType::SYNCSTATUSCOUNT, MASTERNODE_SYNC_GOVOBJ, nObjCount);
+ g_connman->PushMessage(pfrom, NetMsgType::SYNCSTATUSCOUNT, MASTERNODE_SYNC_GOVOBJ_VOTE, nVoteCount);
LogPrintf("CGovernanceManager::Sync -- sent %d objects and %d votes to peer=%d\n", nObjCount, nVoteCount, pfrom->id);
}
@@ -1147,7 +1147,7 @@ void CGovernanceManager::RequestGovernanceObject(CNode* pfrom, const uint256& nH
LogPrint("gobject", "CGovernanceObject::RequestGovernanceObject -- hash = %s (peer=%d)\n", nHash.ToString(), pfrom->GetId());
if(pfrom->nVersion < GOVERNANCE_FILTER_PROTO_VERSION) {
- pfrom->PushMessage(NetMsgType::MNGOVERNANCESYNC, nHash);
+ g_connman->PushMessage(pfrom, NetMsgType::MNGOVERNANCESYNC, nHash);
return;
}
@@ -1170,7 +1170,7 @@ void CGovernanceManager::RequestGovernanceObject(CNode* pfrom, const uint256& nH
}
LogPrint("gobject", "CGovernanceManager::RequestGovernanceObject -- nHash %s nVoteCount %d peer=%d\n", nHash.ToString(), nVoteCount, pfrom->id);
- pfrom->PushMessage(NetMsgType::MNGOVERNANCESYNC, nHash, filter);
+ g_connman->PushMessage(pfrom, NetMsgType::MNGOVERNANCESYNC, nHash, filter);
}
int CGovernanceManager::RequestGovernanceObjectVotes(CNode* pnode)
diff --git a/src/main.cpp b/src/main.cpp
index 85b9a75f61e77..433b598b15f25 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -19,6 +19,7 @@
#include "init.h"
#include "merkleblock.h"
#include "net.h"
+#include "netbase.h"
#include "policy/policy.h"
#include "pow.h"
#include "primitives/block.h"
@@ -246,7 +247,7 @@ struct CBlockReject {
*/
struct CNodeState {
//! The peer's address
- CService address;
+ const CService address;
//! Whether we have a fully established connection.
bool fCurrentlyConnected;
//! Accumulated misbehaviour score for this peer.
@@ -254,7 +255,7 @@ struct CNodeState {
//! Whether this peer should be disconnected and banned (unless whitelisted).
bool fShouldBan;
//! String name of this peer (debugging/logging purposes).
- std::string name;
+ const std::string name;
//! List of asynchronously-determined block rejections to notify this peer about.
std::vector rejects;
//! The best known block we know this peer has announced.
@@ -279,7 +280,7 @@ struct CNodeState {
//! Whether this peer wants invs or headers (when possible) for block announcements.
bool fPreferHeaders;
- CNodeState() {
+ CNodeState(CAddress addrIn, std::string addrNameIn) : address(addrIn), name(addrNameIn) {
fCurrentlyConnected = false;
nMisbehavior = 0;
fShouldBan = false;
@@ -318,11 +319,36 @@ void UpdatePreferredDownload(CNode* node, CNodeState* state)
nPreferredDownload += state->fPreferredDownload;
}
-void InitializeNode(NodeId nodeid, const CNode *pnode) {
- LOCK(cs_main);
- CNodeState &state = mapNodeState.insert(std::make_pair(nodeid, CNodeState())).first->second;
- state.name = pnode->addrName;
- state.address = pnode->addr;
+void PushNodeVersion(CNode *pnode, CConnman& connman, int64_t nTime)
+{
+ ServiceFlags nLocalNodeServices = pnode->GetLocalServices();
+ uint64_t nonce = pnode->GetLocalNonce();
+ int nNodeStartingHeight = pnode->GetMyStartingHeight();
+ NodeId nodeid = pnode->GetId();
+ CAddress addr = pnode->addr;
+
+ CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0", 0), addr.nServices));
+ CAddress addrMe = GetLocalAddress(&addr, nLocalNodeServices);
+
+ connman.PushMessageWithVersion(pnode, INIT_PROTO_VERSION, NetMsgType::VERSION, PROTOCOL_VERSION, (uint64_t)nLocalNodeServices, nTime, addrYou, addrMe,
+ nonce, strSubVersion, nNodeStartingHeight, ::fRelayTxes);
+
+ if (fLogIPs)
+ LogPrint("net", "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nNodeStartingHeight, addrMe.ToString(), addrYou.ToString(), nodeid);
+ else
+ LogPrint("net", "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nNodeStartingHeight, addrMe.ToString(), nodeid);
+}
+
+void InitializeNode(CNode *pnode, CConnman& connman) {
+ CAddress addr = pnode->addr;
+ std::string addrName = pnode->addrName;
+ NodeId nodeid = pnode->GetId();
+ {
+ LOCK(cs_main);
+ mapNodeState.emplace_hint(mapNodeState.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(addr, std::move(addrName)));
+ }
+ if(!pnode->fInbound)
+ PushNodeVersion(pnode, connman, GetTime());
}
void FinalizeNode(NodeId nodeid, bool& fUpdateConnectionTime) {
@@ -5057,14 +5083,14 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
if (!ReadBlockFromDisk(block, (*mi).second, consensusParams))
assert(!"cannot load block from disk");
if (inv.type == MSG_BLOCK)
- pfrom->PushMessage(NetMsgType::BLOCK, block);
+ connman.PushMessage(pfrom, NetMsgType::BLOCK, block);
else // MSG_FILTERED_BLOCK)
{
LOCK(pfrom->cs_filter);
if (pfrom->pfilter)
{
CMerkleBlock merkleBlock(block, *pfrom->pfilter);
- pfrom->PushMessage(NetMsgType::MERKLEBLOCK, merkleBlock);
+ connman.PushMessage(pfrom, NetMsgType::MERKLEBLOCK, merkleBlock);
// CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see
// This avoids hurting performance by pointlessly requiring a round-trip
// Note that there is currently no way for a node to request any single transactions we didn't send here -
@@ -5073,7 +5099,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
// however we MUST always provide at least what the remote peer needs
typedef std::pair PairType;
BOOST_FOREACH(PairType& pair, merkleBlock.vMatchedTxn)
- pfrom->PushMessage(NetMsgType::TX, block.vtx[pair.first]);
+ connman.PushMessage(pfrom, NetMsgType::TX, block.vtx[pair.first]);
}
// else
// no response
@@ -5087,7 +5113,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
// wait for other stuff first.
vector vInv;
vInv.push_back(CInv(MSG_BLOCK, chainActive.Tip()->GetBlockHash()));
- pfrom->PushMessage(NetMsgType::INV, vInv);
+ connman.PushMessage(pfrom, NetMsgType::INV, vInv);
pfrom->hashContinue.SetNull();
}
}
@@ -5107,7 +5133,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
}
}
if(pushed)
- pfrom->PushMessage(inv.GetCommand(), ss);
+ connman.PushMessage(pfrom, inv.GetCommand(), ss);
}
if (!pushed && inv.type == MSG_TX) {
@@ -5116,7 +5142,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(1000);
ss << tx;
- pfrom->PushMessage(NetMsgType::TX, ss);
+ connman.PushMessage(pfrom, NetMsgType::TX, ss);
pushed = true;
}
}
@@ -5127,7 +5153,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(1000);
ss << txLockRequest;
- pfrom->PushMessage(NetMsgType::TXLOCKREQUEST, ss);
+ connman.PushMessage(pfrom, NetMsgType::TXLOCKREQUEST, ss);
pushed = true;
}
}
@@ -5138,7 +5164,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(1000);
ss << vote;
- pfrom->PushMessage(NetMsgType::TXLOCKVOTE, ss);
+ connman.PushMessage(pfrom, NetMsgType::TXLOCKVOTE, ss);
pushed = true;
}
}
@@ -5148,7 +5174,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(1000);
ss << mapSporks[inv.hash];
- pfrom->PushMessage(NetMsgType::SPORK, ss);
+ connman.PushMessage(pfrom, NetMsgType::SPORK, ss);
pushed = true;
}
}
@@ -5158,7 +5184,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(1000);
ss << mnpayments.mapMasternodePaymentVotes[inv.hash];
- pfrom->PushMessage(NetMsgType::MASTERNODEPAYMENTVOTE, ss);
+ connman.PushMessage(pfrom, NetMsgType::MASTERNODEPAYMENTVOTE, ss);
pushed = true;
}
}
@@ -5174,7 +5200,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(1000);
ss << mnpayments.mapMasternodePaymentVotes[hash];
- pfrom->PushMessage(NetMsgType::MASTERNODEPAYMENTVOTE, ss);
+ connman.PushMessage(pfrom, NetMsgType::MASTERNODEPAYMENTVOTE, ss);
}
}
}
@@ -5187,7 +5213,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(1000);
ss << mnodeman.mapSeenMasternodeBroadcast[inv.hash].second;
- pfrom->PushMessage(NetMsgType::MNANNOUNCE, ss);
+ connman.PushMessage(pfrom, NetMsgType::MNANNOUNCE, ss);
pushed = true;
}
}
@@ -5197,7 +5223,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(1000);
ss << mnodeman.mapSeenMasternodePing[inv.hash];
- pfrom->PushMessage(NetMsgType::MNPING, ss);
+ connman.PushMessage(pfrom, NetMsgType::MNPING, ss);
pushed = true;
}
}
@@ -5208,7 +5234,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(1000);
ss << dstx;
- pfrom->PushMessage(NetMsgType::DSTX, ss);
+ connman.PushMessage(pfrom, NetMsgType::DSTX, ss);
pushed = true;
}
}
@@ -5227,7 +5253,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
}
LogPrint("net", "ProcessGetData -- MSG_GOVERNANCE_OBJECT: topush = %d, inv = %s\n", topush, inv.ToString());
if(topush) {
- pfrom->PushMessage(NetMsgType::MNGOVERNANCEOBJECT, ss);
+ connman.PushMessage(pfrom, NetMsgType::MNGOVERNANCEOBJECT, ss);
pushed = true;
}
}
@@ -5245,7 +5271,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
}
if(topush) {
LogPrint("net", "ProcessGetData -- pushing: inv = %s\n", inv.ToString());
- pfrom->PushMessage(NetMsgType::MNGOVERNANCEOBJECTVOTE, ss);
+ connman.PushMessage(pfrom, NetMsgType::MNGOVERNANCEOBJECTVOTE, ss);
pushed = true;
}
}
@@ -5255,7 +5281,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(1000);
ss << mnodeman.mapSeenMasternodeVerification[inv.hash];
- pfrom->PushMessage(NetMsgType::MNVERIFY, ss);
+ connman.PushMessage(pfrom, NetMsgType::MNVERIFY, ss);
pushed = true;
}
}
@@ -5282,7 +5308,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
// do that because they want to know about (and store and rebroadcast and
// risk analyze) the dependencies of transactions relevant to them, without
// having to download the entire memory pool.
- pfrom->PushMessage(NetMsgType::NOTFOUND, vNotFound);
+ connman.PushMessage(pfrom, NetMsgType::NOTFOUND, vNotFound);
}
}
@@ -5327,7 +5353,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// Each connection can only send one version message
if (pfrom->nVersion != 0)
{
- pfrom->PushMessage(NetMsgType::REJECT, strCommand, REJECT_DUPLICATE, string("Duplicate version message"));
+ connman.PushMessageWithVersion(pfrom, INIT_PROTO_VERSION, NetMsgType::REJECT, strCommand, REJECT_DUPLICATE, string("Duplicate version message"));
LOCK(cs_main);
Misbehaving(pfrom->GetId(), 1);
return false;
@@ -5347,7 +5373,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (pfrom->nServicesExpected & ~pfrom->nServices)
{
LogPrint("net", "peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom->id, pfrom->nServices, pfrom->nServicesExpected);
- pfrom->PushMessage(NetMsgType::REJECT, strCommand, REJECT_NONSTANDARD,
+ connman.PushMessageWithVersion(pfrom, INIT_PROTO_VERSION, NetMsgType::REJECT, strCommand, REJECT_NONSTANDARD,
strprintf("Expected to offer services %08x", pfrom->nServicesExpected));
pfrom->fDisconnect = true;
return false;
@@ -5357,7 +5383,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
{
// disconnect from peers older than this proto version
LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, pfrom->nVersion);
- pfrom->PushMessage(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE,
+ connman.PushMessageWithVersion(pfrom, INIT_PROTO_VERSION, NetMsgType::REJECT, strCommand, REJECT_OBSOLETE,
strprintf("Version must be %d or greater", MIN_PEER_PROTO_VERSION));
pfrom->fDisconnect = true;
return false;
@@ -5394,7 +5420,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// Be shy and don't send version until we hear
if (pfrom->fInbound)
- pfrom->PushVersion();
+ PushNodeVersion(pfrom, connman, GetAdjustedTime());
pfrom->fClient = !(pfrom->nServices & NODE_NETWORK);
@@ -5405,8 +5431,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
// Change version
- pfrom->PushMessage(NetMsgType::VERACK);
- pfrom->ssSend.SetVersion(min(pfrom->nVersion, PROTOCOL_VERSION));
+ connman.PushMessageWithVersion(pfrom, INIT_PROTO_VERSION, NetMsgType::VERACK);
+ pfrom->SetSendVersion(min(pfrom->nVersion, PROTOCOL_VERSION));
if (!pfrom->fInbound)
{
@@ -5428,7 +5454,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// Get recent addresses
if (pfrom->fOneShot || pfrom->nVersion >= CADDR_TIME_VERSION || connman.GetAddressCount() < 1000)
{
- pfrom->PushMessage(NetMsgType::GETADDR);
+ connman.PushMessage(pfrom, NetMsgType::GETADDR);
pfrom->fGetAddr = true;
}
connman.MarkAddressGood(pfrom->addr);
@@ -5444,7 +5470,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
{
LOCK(cs_mapAlerts);
BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
- item.second.RelayTo(pfrom);
+ item.second.RelayTo(pfrom, connman);
}
pfrom->fSuccessfullyConnected = true;
@@ -5488,7 +5514,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// We send this to non-NODE NETWORK peers as well, because even
// non-NODE NETWORK peers can announce blocks (such as pruning
// nodes)
- pfrom->PushMessage(NetMsgType::SENDHEADERS);
+ connman.PushMessage(pfrom, NetMsgType::SENDHEADERS);
}
}
@@ -5593,7 +5619,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// time the block arrives, the header chain leading up to it is already validated. Not
// doing this will result in the received block being rejected as an orphan in case it is
// not a direct successor.
- pfrom->PushMessage(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), inv.hash);
+ connman.PushMessage(pfrom, NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), inv.hash);
CNodeState *nodestate = State(pfrom->GetId());
if (CanDirectFetch(chainparams.GetConsensus()) &&
nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
@@ -5623,7 +5649,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
if (!vToFetch.empty())
- pfrom->PushMessage(NetMsgType::GETDATA, vToFetch);
+ connman.PushMessage(pfrom, NetMsgType::GETDATA, vToFetch);
}
@@ -5738,7 +5764,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// headers message). In both cases it's safe to update
// pindexBestHeaderSent to be our tip.
nodestate->pindexBestHeaderSent = pindex ? pindex : chainActive.Tip();
- pfrom->PushMessage(NetMsgType::HEADERS, vHeaders);
+ connman.PushMessage(pfrom, NetMsgType::HEADERS, vHeaders);
}
@@ -5949,7 +5975,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom->id,
FormatStateMessage(state));
if (state.GetRejectCode() < REJECT_INTERNAL) // Never send AcceptToMemoryPool's internal codes over P2P
- pfrom->PushMessage(NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(),
+ connman.PushMessage(pfrom, NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(),
state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash);
if (nDoS > 0)
Misbehaving(pfrom->GetId(), nDoS);
@@ -6009,7 +6035,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// TODO: optimize: if pindexLast is an ancestor of chainActive.Tip or pindexBestHeader, continue
// from there instead.
LogPrint("net", "more getheaders (%d) to end to peer=%d (startheight:%d)\n", pindexLast->nHeight, pfrom->id, pfrom->nStartingHeight);
- pfrom->PushMessage(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexLast), uint256());
+ connman.PushMessage(pfrom, NetMsgType::GETHEADERS, chainActive.GetLocator(pindexLast), uint256());
}
bool fCanDirectFetch = CanDirectFetch(chainparams.GetConsensus());
@@ -6054,7 +6080,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pindexLast->GetBlockHash().ToString(), pindexLast->nHeight);
}
if (vGetData.size() > 0) {
- pfrom->PushMessage(NetMsgType::GETDATA, vGetData);
+ connman.PushMessage(pfrom, NetMsgType::GETDATA, vGetData);
}
}
}
@@ -6085,7 +6111,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
int nDoS;
if (state.IsInvalid(nDoS)) {
assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes
- pfrom->PushMessage(NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(),
+ connman.PushMessage(pfrom, NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(),
state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash);
if (nDoS > 0) {
LOCK(cs_main);
@@ -6138,12 +6164,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
vInv.push_back(inv);
if (vInv.size() == MAX_INV_SZ) {
- pfrom->PushMessage(NetMsgType::INV, vInv);
+ connman.PushMessage(pfrom, NetMsgType::INV, vInv);
vInv.clear();
}
}
if (vInv.size() > 0)
- pfrom->PushMessage(NetMsgType::INV, vInv);
+ connman.PushMessage(pfrom, NetMsgType::INV, vInv);
}
@@ -6164,7 +6190,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// it, if the remote node sends a ping once per second and this node takes 5
// seconds to respond to each, the 5th ping the remote sends would appear to
// return very quickly.
- pfrom->PushMessage(NetMsgType::PONG, nonce);
+ connman.PushMessage(pfrom, NetMsgType::PONG, nonce);
}
}
@@ -6239,8 +6265,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// Relay
pfrom->setKnown.insert(alertHash);
{
- connman.ForEachNode([&alert](CNode* pnode) {
- alert.RelayTo(pnode);
+ connman.ForEachNode([&alert, &connman](CNode* pnode) {
+ alert.RelayTo(pnode, connman);
});
}
}
@@ -6452,7 +6478,7 @@ bool ProcessMessages(CNode* pfrom, CConnman& connman)
}
catch (const std::ios_base::failure& e)
{
- pfrom->PushMessage(NetMsgType::REJECT, strCommand, REJECT_MALFORMED, string("error parsing message"));
+ connman.PushMessageWithVersion(pfrom, INIT_PROTO_VERSION, NetMsgType::REJECT, strCommand, REJECT_MALFORMED, string("error parsing message"));
if (strstr(e.what(), "end of data"))
{
// Allow exceptions from under-length message on vRecv
@@ -6520,11 +6546,11 @@ bool SendMessages(CNode* pto, CConnman& connman)
pto->nPingUsecStart = GetTimeMicros();
if (pto->nVersion > BIP0031_VERSION) {
pto->nPingNonceSent = nonce;
- pto->PushMessage(NetMsgType::PING, nonce);
+ connman.PushMessage(pto, NetMsgType::PING, nonce);
} else {
// Peer is too old to support ping command with nonce, pong will never arrive.
pto->nPingNonceSent = 0;
- pto->PushMessage(NetMsgType::PING);
+ connman.PushMessage(pto, NetMsgType::PING);
}
}
@@ -6555,14 +6581,14 @@ bool SendMessages(CNode* pto, CConnman& connman)
// receiver rejects addr messages larger than 1000
if (vAddr.size() >= 1000)
{
- pto->PushMessage(NetMsgType::ADDR, vAddr);
+ connman.PushMessage(pto, NetMsgType::ADDR, vAddr);
vAddr.clear();
}
}
}
pto->vAddrToSend.clear();
if (!vAddr.empty())
- pto->PushMessage(NetMsgType::ADDR, vAddr);
+ connman.PushMessage(pto, NetMsgType::ADDR, vAddr);
}
CNodeState &state = *State(pto->GetId());
@@ -6582,7 +6608,7 @@ bool SendMessages(CNode* pto, CConnman& connman)
}
BOOST_FOREACH(const CBlockReject& reject, state.rejects)
- pto->PushMessage(NetMsgType::REJECT, (string)NetMsgType::BLOCK, reject.chRejectCode, reject.strRejectReason, reject.hashBlock);
+ connman.PushMessage(pto, NetMsgType::REJECT, (string)NetMsgType::BLOCK, reject.chRejectCode, reject.strRejectReason, reject.hashBlock);
state.rejects.clear();
// Start block sync
@@ -6605,7 +6631,7 @@ bool SendMessages(CNode* pto, CConnman& connman)
if (pindexStart->pprev)
pindexStart = pindexStart->pprev;
LogPrint("net", "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->nHeight, pto->id, pto->nStartingHeight);
- pto->PushMessage(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexStart), uint256());
+ connman.PushMessage(pto, NetMsgType::GETHEADERS, chainActive.GetLocator(pindexStart), uint256());
}
}
@@ -6719,7 +6745,7 @@ bool SendMessages(CNode* pto, CConnman& connman)
LogPrint("net", "%s: sending header %s to peer=%d\n", __func__,
vHeaders.front().GetHash().ToString(), pto->id);
}
- pto->PushMessage(NetMsgType::HEADERS, vHeaders);
+ connman.PushMessage(pto, NetMsgType::HEADERS, vHeaders);
state.pindexBestHeaderSent = pBestIndex;
}
pto->vBlockHashesToAnnounce.clear();
@@ -6770,7 +6796,7 @@ bool SendMessages(CNode* pto, CConnman& connman)
if (vInv.size() >= 1000)
{
LogPrint("net", "SendMessages -- pushing inv's: count=%d peer=%d\n", vInv.size(), pto->id);
- pto->PushMessage(NetMsgType::INV, vInv);
+ connman.PushMessage(pto, NetMsgType::INV, vInv);
vInv.clear();
}
}
@@ -6778,7 +6804,7 @@ bool SendMessages(CNode* pto, CConnman& connman)
}
if (!vInv.empty()) {
LogPrint("net", "SendMessages -- pushing tailing inv's: count=%d peer=%d\n", vInv.size(), pto->id);
- pto->PushMessage(NetMsgType::INV, vInv);
+ connman.PushMessage(pto, NetMsgType::INV, vInv);
}
// Detect whether we're stalling
@@ -6838,7 +6864,7 @@ bool SendMessages(CNode* pto, CConnman& connman)
vGetData.push_back(inv);
if (vGetData.size() >= 1000)
{
- pto->PushMessage(NetMsgType::GETDATA, vGetData);
+ connman.PushMessage(pto, NetMsgType::GETDATA, vGetData);
LogPrint("net", "SendMessages -- GETDATA -- pushed size = %lu peer=%d\n", vGetData.size(), pto->id);
vGetData.clear();
}
@@ -6850,7 +6876,7 @@ bool SendMessages(CNode* pto, CConnman& connman)
pto->mapAskFor.erase(pto->mapAskFor.begin());
}
if (!vGetData.empty()) {
- pto->PushMessage(NetMsgType::GETDATA, vGetData);
+ connman.PushMessage(pto, NetMsgType::GETDATA, vGetData);
LogPrint("net", "SendMessages -- GETDATA -- pushed size = %lu peer=%d\n", vGetData.size(), pto->id);
}
diff --git a/src/masternode-payments.cpp b/src/masternode-payments.cpp
index 9ad0bdc9c11d4..a61bb8ed50268 100644
--- a/src/masternode-payments.cpp
+++ b/src/masternode-payments.cpp
@@ -842,7 +842,7 @@ void CMasternodePayments::Sync(CNode* pnode)
}
LogPrintf("CMasternodePayments::Sync -- Sent %d votes to peer %d\n", nInvCount, pnode->id);
- pnode->PushMessage(NetMsgType::SYNCSTATUSCOUNT, MASTERNODE_SYNC_MNW, nInvCount);
+ g_connman->PushMessage(pnode, NetMsgType::SYNCSTATUSCOUNT, MASTERNODE_SYNC_MNW, nInvCount);
}
// Request low data/unknown payment blocks in batches directly from some node instead of/after preliminary Sync.
@@ -864,7 +864,7 @@ void CMasternodePayments::RequestLowDataPaymentBlocks(CNode* pnode)
// We should not violate GETDATA rules
if(vToFetch.size() == MAX_INV_SZ) {
LogPrintf("CMasternodePayments::SyncLowDataPaymentBlocks -- asking peer %d for %d blocks\n", pnode->id, MAX_INV_SZ);
- pnode->PushMessage(NetMsgType::GETDATA, vToFetch);
+ g_connman->PushMessage(pnode, NetMsgType::GETDATA, vToFetch);
// Start filling new batch
vToFetch.clear();
}
@@ -912,7 +912,7 @@ void CMasternodePayments::RequestLowDataPaymentBlocks(CNode* pnode)
// We should not violate GETDATA rules
if(vToFetch.size() == MAX_INV_SZ) {
LogPrintf("CMasternodePayments::SyncLowDataPaymentBlocks -- asking peer %d for %d payment blocks\n", pnode->id, MAX_INV_SZ);
- pnode->PushMessage(NetMsgType::GETDATA, vToFetch);
+ g_connman->PushMessage(pnode, NetMsgType::GETDATA, vToFetch);
// Start filling new batch
vToFetch.clear();
}
@@ -921,7 +921,7 @@ void CMasternodePayments::RequestLowDataPaymentBlocks(CNode* pnode)
// Ask for the rest of it
if(!vToFetch.empty()) {
LogPrintf("CMasternodePayments::SyncLowDataPaymentBlocks -- asking peer %d for %d payment blocks\n", pnode->id, vToFetch.size());
- pnode->PushMessage(NetMsgType::GETDATA, vToFetch);
+ g_connman->PushMessage(pnode, NetMsgType::GETDATA, vToFetch);
}
}
diff --git a/src/masternode-sync.cpp b/src/masternode-sync.cpp
index 5331c35ac92c4..619b7b3fca0b1 100644
--- a/src/masternode-sync.cpp
+++ b/src/masternode-sync.cpp
@@ -324,12 +324,12 @@ void CMasternodeSync::ProcessTick()
if(Params().NetworkIDString() == CBaseChainParams::REGTEST)
{
if(nRequestedMasternodeAttempt <= 2) {
- pnode->PushMessage(NetMsgType::GETSPORKS); //get current network sporks
+ g_connman->PushMessageWithVersion(pnode, INIT_PROTO_VERSION, NetMsgType::GETSPORKS); //get current network sporks
} else if(nRequestedMasternodeAttempt < 4) {
mnodeman.DsegUpdate(pnode);
} else if(nRequestedMasternodeAttempt < 6) {
int nMnCount = mnodeman.CountMasternodes();
- pnode->PushMessage(NetMsgType::MASTERNODEPAYMENTSYNC, nMnCount); //sync payment votes
+ g_connman->PushMessage(pnode, NetMsgType::MASTERNODEPAYMENTSYNC, nMnCount); //sync payment votes
SendGovernanceSyncRequest(pnode);
} else {
nRequestedMasternodeAssets = MASTERNODE_SYNC_FINISHED;
@@ -355,7 +355,7 @@ void CMasternodeSync::ProcessTick()
// only request once from each peer
netfulfilledman.AddFulfilledRequest(pnode->addr, "spork-sync");
// get current network sporks
- pnode->PushMessage(NetMsgType::GETSPORKS);
+ g_connman->PushMessageWithVersion(pnode, INIT_PROTO_VERSION, NetMsgType::GETSPORKS);
LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d -- requesting sporks from peer %d\n", nTick, nRequestedMasternodeAssets, pnode->id);
continue; // always get sporks first, switch to the next node without waiting for the next tick
}
@@ -431,7 +431,7 @@ void CMasternodeSync::ProcessTick()
nRequestedMasternodeAttempt++;
// ask node for all payment votes it has (new nodes will only return votes for future payments)
- pnode->PushMessage(NetMsgType::MASTERNODEPAYMENTSYNC, mnpayments.GetStorageLimit());
+ g_connman->PushMessage(pnode, NetMsgType::MASTERNODEPAYMENTSYNC, mnpayments.GetStorageLimit());
// ask node for missing pieces only (old nodes will not be asked)
mnpayments.RequestLowDataPaymentBlocks(pnode);
@@ -511,10 +511,10 @@ void CMasternodeSync::SendGovernanceSyncRequest(CNode* pnode)
CBloomFilter filter;
filter.clear();
- pnode->PushMessage(NetMsgType::MNGOVERNANCESYNC, uint256(), filter);
+ g_connman->PushMessage(pnode, NetMsgType::MNGOVERNANCESYNC, uint256(), filter);
}
else {
- pnode->PushMessage(NetMsgType::MNGOVERNANCESYNC, uint256());
+ g_connman->PushMessage(pnode, NetMsgType::MNGOVERNANCESYNC, uint256());
}
}
diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp
index 263f96ae5facc..37c4d7fb28bb5 100644
--- a/src/masternodeman.cpp
+++ b/src/masternodeman.cpp
@@ -162,7 +162,7 @@ void CMasternodeMan::AskForMN(CNode* pnode, const CTxIn &vin)
}
mWeAskedForMasternodeListEntry[vin.prevout][pnode->addr] = GetTime() + DSEG_UPDATE_SECONDS;
- pnode->PushMessage(NetMsgType::DSEG, vin);
+ g_connman->PushMessage(pnode, NetMsgType::DSEG, vin);
}
void CMasternodeMan::Check()
@@ -438,7 +438,7 @@ void CMasternodeMan::DsegUpdate(CNode* pnode)
}
}
- pnode->PushMessage(NetMsgType::DSEG, CTxIn());
+ g_connman->PushMessage(pnode, NetMsgType::DSEG, CTxIn());
int64_t askAgain = GetTime() + DSEG_UPDATE_SECONDS;
mWeAskedForMasternodeList[pnode->addr] = askAgain;
@@ -926,7 +926,7 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
}
if(vin == CTxIn()) {
- pfrom->PushMessage(NetMsgType::SYNCSTATUSCOUNT, MASTERNODE_SYNC_LIST, nInvCount);
+ g_connman->PushMessage(pfrom, NetMsgType::SYNCSTATUSCOUNT, MASTERNODE_SYNC_LIST, nInvCount);
LogPrintf("DSEG -- Sent %d Masternode invs to peer %d\n", nInvCount, pfrom->id);
return;
}
@@ -1109,7 +1109,7 @@ bool CMasternodeMan::SendVerifyRequest(const CAddress& addr, const std::vectornHeight - 1);
mWeAskedForVerification[addr] = mnv;
LogPrintf("CMasternodeMan::SendVerifyRequest -- verifying node using nonce %d addr=%s\n", mnv.nonce, addr.ToString());
- pnode->PushMessage(NetMsgType::MNVERIFY, mnv);
+ g_connman->PushMessage(pnode, NetMsgType::MNVERIFY, mnv);
return true;
}
@@ -1150,7 +1150,7 @@ void CMasternodeMan::SendVerifyReply(CNode* pnode, CMasternodeVerification& mnv)
return;
}
- pnode->PushMessage(NetMsgType::MNVERIFY, mnv);
+ g_connman->PushMessage(pnode, NetMsgType::MNVERIFY, mnv);
netfulfilledman.AddFulfilledRequest(pnode->addr, strprintf("%s", NetMsgType::MNVERIFY)+"-reply");
}
diff --git a/src/net.cpp b/src/net.cpp
index 8cc53081dfa96..1c652767da207 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -411,17 +411,17 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
// Add node
CNode* pnode = new CNode(GetNewNodeId(), nLocalServices, GetBestHeight(), hSocket, addrConnect, pszDest ? pszDest : "", false, true);
- GetNodeSignals().InitializeNode(pnode->GetId(), pnode);
+ pnode->nServicesExpected = ServiceFlags(addrConnect.nServices & nRelevantServices);
pnode->nTimeConnected = GetTime();
if(fConnectToMasternode) {
pnode->AddRef();
pnode->fMasternode = true;
}
+ GetNodeSignals().InitializeNode(pnode, *this);
LOCK(cs_vNodes);
vNodes.push_back(pnode);
- pnode->nServicesExpected = ServiceFlags(addrConnect.nServices & nRelevantServices);
return pnode;
} else if (!proxyConnectionFailed) {
@@ -468,23 +468,6 @@ void CNode::CloseSocketDisconnect()
vRecvMsg.clear();
}
-void CNode::PushVersion()
-{
- int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime());
- CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0", 0), addr.nServices));
- CAddress addrMe = GetLocalAddress(&addr, nLocalServices);
- if (fLogIPs)
- LogPrint("net", "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nMyStartingHeight, addrMe.ToString(), addrYou.ToString(), id);
- else
- LogPrint("net", "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nMyStartingHeight, addrMe.ToString(), id);
- PushMessage(NetMsgType::VERSION, PROTOCOL_VERSION, (uint64_t)nLocalServices, nTime, addrYou, addrMe,
- nLocalHostNonce, strSubVersion, nMyStartingHeight, !GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY));
-}
-
-
-
-
-
void CConnman::ClearBanned()
{
{
@@ -1074,8 +1057,8 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
}
CNode* pnode = new CNode(GetNewNodeId(), nLocalServices, GetBestHeight(), hSocket, addr, "", true);
- GetNodeSignals().InitializeNode(pnode->GetId(), pnode);
pnode->fWhitelisted = whitelisted;
+ GetNodeSignals().InitializeNode(pnode, *this);
LogPrint("net", "connection from %s accepted\n", addr.ToString());
@@ -1100,7 +1083,7 @@ void CConnman::ThreadSocketHandler()
BOOST_FOREACH(CNode* pnode, vNodesCopy)
{
if (pnode->fDisconnect ||
- (pnode->GetRefCount() <= 0 && pnode->vRecvMsg.empty() && pnode->nSendSize == 0 && pnode->ssSend.empty()))
+ (pnode->GetRefCount() <= 0 && pnode->vRecvMsg.empty() && pnode->nSendSize == 0))
{
LogPrintf("ThreadSocketHandler -- removing node: peer=%d addr=%s nRefCount=%d fNetworkNode=%d fInbound=%d fMasternode=%d\n",
pnode->id, pnode->addr.ToString(), pnode->GetRefCount(), pnode->fNetworkNode, pnode->fInbound, pnode->fMasternode);
@@ -1210,10 +1193,6 @@ void CConnman::ThreadSocketHandler()
{
TRY_LOCK(pnode->cs_vSend, lockSend);
if (lockSend) {
- if (pnode->nOptimisticBytesWritten) {
- RecordBytesSent(pnode->nOptimisticBytesWritten);
- pnode->nOptimisticBytesWritten = 0;
- }
if (!pnode->vSendMsg.empty()) {
FD_SET(pnode->hSocket, &fdsetSend);
continue;
@@ -1829,7 +1808,7 @@ void CConnman::ThreadMnbRequestConnections()
}
// ask for data
- pnode->PushMessage(NetMsgType::GETDATA, vToFetch);
+ PushMessage(pnode, NetMsgType::GETDATA, vToFetch);
pnode->Release();
}
@@ -2160,7 +2139,7 @@ bool CConnman::Start(boost::thread_group& threadGroup, CScheduler& scheduler, st
if (pnodeLocalHost == NULL) {
pnodeLocalHost = new CNode(GetNewNodeId(), nLocalServices, GetBestHeight(), INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
- GetNodeSignals().InitializeNode(pnodeLocalHost->GetId(), pnodeLocalHost);
+ GetNodeSignals().InitializeNode(pnodeLocalHost, *this);
}
//
@@ -2579,48 +2558,13 @@ int CConnman::GetBestHeight() const
return nBestHeight.load(std::memory_order_acquire);
}
-void CNode::Fuzz(int nChance)
-{
- if (!fSuccessfullyConnected) return; // Don't fuzz initial handshake
- if (GetRand(nChance) != 0) return; // Fuzz 1 of every nChance messages
-
- switch (GetRand(3))
- {
- case 0:
- // xor a random byte with a random value:
- if (!ssSend.empty()) {
- CDataStream::size_type pos = GetRand(ssSend.size());
- ssSend[pos] ^= (unsigned char)(GetRand(256));
- }
- break;
- case 1:
- // delete a random byte:
- if (!ssSend.empty()) {
- CDataStream::size_type pos = GetRand(ssSend.size());
- ssSend.erase(ssSend.begin()+pos);
- }
- break;
- case 2:
- // insert a random byte at a random position
- {
- CDataStream::size_type pos = GetRand(ssSend.size());
- char ch = (char)GetRand(256);
- ssSend.insert(ssSend.begin()+pos, ch);
- }
- break;
- }
- // Chance of more than one change half the time:
- // (more changes exponentially less likely):
- Fuzz(2);
-}
-
unsigned int CConnman::GetReceiveFloodSize() const { return nReceiveFloodSize; }
unsigned int CConnman::GetSendBufferSize() const{ return nSendBufferMaxSize; }
CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNameIn, bool fInboundIn, bool fNetworkNodeIn) :
- ssSend(SER_NETWORK, INIT_PROTO_VERSION),
addrKnown(5000, 0.001),
- filterInventoryKnown(50000, 0.000001)
+ filterInventoryKnown(50000, 0.000001),
+ nSendVersion(0)
{
nServices = NODE_NONE;
nServicesExpected = NODE_NONE;
@@ -2668,7 +2612,6 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn
nMinPingUsecTime = std::numeric_limits::max();
vchKeyedNetGroup = CalculateKeyedNetGroup(addr);
id = idIn;
- nOptimisticBytesWritten = 0;
nLocalServices = nLocalServicesIn;
GetRandBytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
@@ -2685,10 +2628,6 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn
LogPrint("net", "Added connection to %s peer=%d\n", addrName, id);
else
LogPrint("net", "Added connection peer=%d\n", id);
-
- // Be shy and don't send version until we hear
- if (hSocket != INVALID_SOCKET && !fInbound)
- PushVersion();
}
CNode::~CNode()
@@ -2745,69 +2684,6 @@ void CNode::AskFor(const CInv& inv)
mapAskFor.insert(std::make_pair(nRequestTime, inv));
}
-void CNode::BeginMessage(const char* pszCommand) EXCLUSIVE_LOCK_FUNCTION(cs_vSend)
-{
- ENTER_CRITICAL_SECTION(cs_vSend);
- assert(ssSend.size() == 0);
- ssSend << CMessageHeader(Params().MessageStart(), pszCommand, 0);
- LogPrint("net", "sending: %s ", SanitizeString(pszCommand));
-}
-
-void CNode::AbortMessage() UNLOCK_FUNCTION(cs_vSend)
-{
- ssSend.clear();
-
- LEAVE_CRITICAL_SECTION(cs_vSend);
-
- LogPrint("net", "(aborted)\n");
-}
-
-void CNode::EndMessage(const char* pszCommand) UNLOCK_FUNCTION(cs_vSend)
-{
- // The -*messagestest options are intentionally not documented in the help message,
- // since they are only used during development to debug the networking code and are
- // not intended for end-users.
- if (mapArgs.count("-dropmessagestest") && GetRand(GetArg("-dropmessagestest", 2)) == 0)
- {
- LogPrint("net", "dropmessages DROPPING SEND MESSAGE\n");
- AbortMessage();
- return;
- }
- if (mapArgs.count("-fuzzmessagestest"))
- Fuzz(GetArg("-fuzzmessagestest", 10));
-
- if (ssSend.size() == 0)
- {
- LEAVE_CRITICAL_SECTION(cs_vSend);
- return;
- }
- // Set the size
- unsigned int nSize = ssSend.size() - CMessageHeader::HEADER_SIZE;
- WriteLE32((uint8_t*)&ssSend[CMessageHeader::MESSAGE_SIZE_OFFSET], nSize);
-
- //log total amount of bytes per command
- mapSendBytesPerMsgCmd[std::string(pszCommand)] += nSize + CMessageHeader::HEADER_SIZE;
-
- // Set the checksum
- uint256 hash = Hash(ssSend.begin() + CMessageHeader::HEADER_SIZE, ssSend.end());
- unsigned int nChecksum = 0;
- memcpy(&nChecksum, &hash, sizeof(nChecksum));
- assert(ssSend.size () >= CMessageHeader::CHECKSUM_OFFSET + sizeof(nChecksum));
- memcpy((char*)&ssSend[CMessageHeader::CHECKSUM_OFFSET], &nChecksum, sizeof(nChecksum));
-
- LogPrint("net", "(%d bytes) peer=%d\n", nSize, id);
-
- std::deque::iterator it = vSendMsg.insert(vSendMsg.end(), CSerializeData());
- ssSend.GetAndClear(*it);
- nSendSize += (*it).size();
-
- // If write queue empty, attempt "optimistic write"
- if (it == vSendMsg.begin())
- nOptimisticBytesWritten += SocketSendData(this);
-
- LEAVE_CRITICAL_SECTION(cs_vSend);
-}
-
std::vector CNode::CalculateKeyedNetGroup(CAddress& address)
{
if(vchSecretKey.size() == 0) {
@@ -2829,6 +2705,52 @@ std::vector CNode::CalculateKeyedNetGroup(CAddress& address)
return vch;
}
+CDataStream CConnman::BeginMessage(CNode* pnode, int nVersion, int flags, const std::string& sCommand)
+{
+ return {SER_NETWORK, (nVersion ? nVersion : pnode->GetSendVersion()) | flags, CMessageHeader(Params().MessageStart(), sCommand.c_str(), 0) };
+}
+
+void CConnman::EndMessage(CDataStream& strm)
+{
+ // Set the size
+ assert(strm.size () >= CMessageHeader::HEADER_SIZE);
+ unsigned int nSize = strm.size() - CMessageHeader::HEADER_SIZE;
+ WriteLE32((uint8_t*)&strm[CMessageHeader::MESSAGE_SIZE_OFFSET], nSize);
+ // Set the checksum
+ uint256 hash = Hash(strm.begin() + CMessageHeader::HEADER_SIZE, strm.end());
+ memcpy((char*)&strm[CMessageHeader::CHECKSUM_OFFSET], hash.begin(), CMessageHeader::CHECKSUM_SIZE);
+
+}
+
+void CConnman::PushMessage(CNode* pnode, CDataStream& strm, const std::string& sCommand)
+{
+ if(strm.empty())
+ return;
+
+ unsigned int nSize = strm.size() - CMessageHeader::HEADER_SIZE;
+ LogPrint("net", "sending %s (%d bytes) peer=%d\n", SanitizeString(sCommand.c_str()), nSize, pnode->id);
+
+ size_t nBytesSent = 0;
+ {
+ LOCK(pnode->cs_vSend);
+ if(pnode->hSocket == INVALID_SOCKET) {
+ return;
+ }
+ bool optimisticSend(pnode->vSendMsg.empty());
+ pnode->vSendMsg.emplace_back(strm.begin(), strm.end());
+
+ //log total amount of bytes per command
+ pnode->mapSendBytesPerMsgCmd[sCommand] += strm.size();
+ pnode->nSendSize += strm.size();
+
+ // If write queue empty, attempt "optimistic write"
+ if (optimisticSend == true)
+ nBytesSent = SocketSendData(pnode);
+ }
+ if (nBytesSent)
+ RecordBytesSent(nBytesSent);
+}
+
bool CConnman::ForNode(const CService& addr, std::function func)
{
CNode* found = nullptr;
diff --git a/src/net.h b/src/net.h
index f0ae9d9776ccf..49b8ca97dd3d3 100644
--- a/src/net.h
+++ b/src/net.h
@@ -142,6 +142,33 @@ class CConnman
bool ForNode(NodeId id, std::function func);
bool ForNode(const CService& addr, std::function func);
+ template
+ void PushMessageWithVersionAndFlag(CNode* pnode, int nVersion, int flag, const std::string& sCommand, Args&&... args)
+ {
+ auto msg(BeginMessage(pnode, nVersion, flag, sCommand));
+ ::SerializeMany(msg, msg.nType, msg.nVersion, std::forward(args)...);
+ EndMessage(msg);
+ PushMessage(pnode, msg, sCommand);
+ }
+
+ template
+ void PushMessageWithFlag(CNode* pnode, int flag, const std::string& sCommand, Args&&... args)
+ {
+ PushMessageWithVersionAndFlag(pnode, 0, flag, sCommand, std::forward(args)...);
+ }
+
+ template
+ void PushMessageWithVersion(CNode* pnode, int nVersion, const std::string& sCommand, Args&&... args)
+ {
+ PushMessageWithVersionAndFlag(pnode, nVersion, 0, sCommand, std::forward(args)...);
+ }
+
+ template
+ void PushMessage(CNode* pnode, const std::string& sCommand, Args&&... args)
+ {
+ PushMessageWithVersionAndFlag(pnode, 0, 0, sCommand, std::forward(args)...);
+ }
+
template
bool ForEachNodeContinueIf(Callable&& func)
{
@@ -352,6 +379,10 @@ class CConnman
unsigned int GetReceiveFloodSize() const;
+ CDataStream BeginMessage(CNode* node, int nVersion, int flags, const std::string& sCommand);
+ void PushMessage(CNode* pnode, CDataStream& strm, const std::string& sCommand);
+ void EndMessage(CDataStream& strm);
+
// Network stats
void RecordBytesRecv(uint64_t bytes);
void RecordBytesSent(uint64_t bytes);
@@ -433,7 +464,7 @@ struct CNodeSignals
{
boost::signals2::signal ProcessMessages;
boost::signals2::signal SendMessages;
- boost::signals2::signal InitializeNode;
+ boost::signals2::signal InitializeNode;
boost::signals2::signal FinalizeNode;
};
@@ -560,15 +591,14 @@ class CNetMessage {
/** Information about a peer */
class CNode
{
+ friend class CConnman;
public:
// socket
ServiceFlags nServices;
ServiceFlags nServicesExpected;
SOCKET hSocket;
- CDataStream ssSend;
size_t nSendSize; // total size of all vSendMsg entries
size_t nSendOffset; // offset inside the first vSendMsg already sent
- uint64_t nOptimisticBytesWritten;
uint64_t nSendBytes;
std::deque vSendMsg;
CCriticalSection cs_vSend;
@@ -620,9 +650,6 @@ class CNode
mapMsgCmdSize mapSendBytesPerMsgCmd;
mapMsgCmdSize mapRecvBytesPerMsgCmd;
- // Basic fuzz-testing
- void Fuzz(int nChance); // modifies ssSend
-
public:
uint256 hashContinue;
int nStartingHeight;
@@ -679,6 +706,7 @@ class CNode
uint64_t nLocalHostNonce;
ServiceFlags nLocalServices;
int nMyStartingHeight;
+ int nSendVersion;
public:
NodeId GetId() const {
@@ -689,6 +717,10 @@ class CNode
return nLocalHostNonce;
}
+ int GetMyStartingHeight() const {
+ return nMyStartingHeight;
+ }
+
int GetRefCount()
{
LOCK(cs_nRefCount);
@@ -715,6 +747,25 @@ class CNode
BOOST_FOREACH(CNetMessage &msg, vRecvMsg)
msg.SetVersion(nVersionIn);
}
+ void SetSendVersion(int nVersionIn)
+ {
+ // Send version may only be changed in the version message, and
+ // only one version message is allowed per session. We can therefore
+ // treat this value as const and even atomic as long as it's only used
+ // once the handshake is complete. Any attempt to set this twice is an
+ // error.
+ assert(nSendVersion == 0);
+ nSendVersion = nVersionIn;
+ }
+
+ int GetSendVersion() const
+ {
+ // The send version should always be explicitly set to
+ // INIT_PROTO_VERSION rather than using this value until the handshake
+ // is complete. See PushMessageWithVersion().
+ assert(nSendVersion != 0);
+ return nSendVersion;
+ }
CNode* AddRef()
{
@@ -781,224 +832,6 @@ class CNode
void AskFor(const CInv& inv);
- // TODO: Document the postcondition of this function. Is cs_vSend locked?
- void BeginMessage(const char* pszCommand) EXCLUSIVE_LOCK_FUNCTION(cs_vSend);
-
- // TODO: Document the precondition of this function. Is cs_vSend locked?
- void AbortMessage() UNLOCK_FUNCTION(cs_vSend);
-
- // TODO: Document the precondition of this function. Is cs_vSend locked?
- void EndMessage(const char* pszCommand) UNLOCK_FUNCTION(cs_vSend);
-
- void PushVersion();
-
-
- void PushMessage(const char* pszCommand)
- {
- try
- {
- BeginMessage(pszCommand);
- EndMessage(pszCommand);
- }
- catch (...)
- {
- AbortMessage();
- throw;
- }
- }
-
- template
- void PushMessage(const char* pszCommand, const T1& a1)
- {
- try
- {
- BeginMessage(pszCommand);
- ssSend << a1;
- EndMessage(pszCommand);
- }
- catch (...)
- {
- AbortMessage();
- throw;
- }
- }
-
- template
- void PushMessage(const char* pszCommand, const T1& a1, const T2& a2)
- {
- try
- {
- BeginMessage(pszCommand);
- ssSend << a1 << a2;
- EndMessage(pszCommand);
- }
- catch (...)
- {
- AbortMessage();
- throw;
- }
- }
-
- template
- void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3)
- {
- try
- {
- BeginMessage(pszCommand);
- ssSend << a1 << a2 << a3;
- EndMessage(pszCommand);
- }
- catch (...)
- {
- AbortMessage();
- throw;
- }
- }
-
- template
- void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4)
- {
- try
- {
- BeginMessage(pszCommand);
- ssSend << a1 << a2 << a3 << a4;
- EndMessage(pszCommand);
- }
- catch (...)
- {
- AbortMessage();
- throw;
- }
- }
-
- template
- void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5)
- {
- try
- {
- BeginMessage(pszCommand);
- ssSend << a1 << a2 << a3 << a4 << a5;
- EndMessage(pszCommand);
- }
- catch (...)
- {
- AbortMessage();
- throw;
- }
- }
-
- template
- void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6)
- {
- try
- {
- BeginMessage(pszCommand);
- ssSend << a1 << a2 << a3 << a4 << a5 << a6;
- EndMessage(pszCommand);
- }
- catch (...)
- {
- AbortMessage();
- throw;
- }
- }
-
- template
- void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7)
- {
- try
- {
- BeginMessage(pszCommand);
- ssSend << a1 << a2 << a3 << a4 << a5 << a6 << a7;
- EndMessage(pszCommand);
- }
- catch (...)
- {
- AbortMessage();
- throw;
- }
- }
-
- template
- void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7, const T8& a8)
- {
- try
- {
- BeginMessage(pszCommand);
- ssSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8;
- EndMessage(pszCommand);
- }
- catch (...)
- {
- AbortMessage();
- throw;
- }
- }
-
- template
- void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7, const T8& a8, const T9& a9)
- {
- try
- {
- BeginMessage(pszCommand);
- ssSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8 << a9;
- EndMessage(pszCommand);
- }
- catch (...)
- {
- AbortMessage();
- throw;
- }
- }
-
- template
- void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7, const T8& a8, const T9& a9, const T10& a10)
- {
- try
- {
- BeginMessage(pszCommand);
- ssSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8 << a9 << a10;
- EndMessage(pszCommand);
- }
- catch (...)
- {
- AbortMessage();
- throw;
- }
- }
-
- template
- void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7, const T8& a8, const T9& a9, const T10& a10, const T11& a11)
- {
- try
- {
- BeginMessage(pszCommand);
- ssSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8 << a9 << a10 << a11;
- EndMessage(pszCommand);
- }
- catch (...)
- {
- AbortMessage();
- throw;
- }
- }
-
- template
- void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7, const T8& a8, const T9& a9, const T10& a10, const T11& a11, const T12& a12)
- {
- try
- {
- BeginMessage(pszCommand);
- ssSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8 << a9 << a10 << a11 << a12;
- EndMessage(pszCommand);
- }
- catch (...)
- {
- AbortMessage();
- throw;
- }
- }
-
void CloseSocketDisconnect();
void copyStats(CNodeStats &stats);
diff --git a/src/privatesend-client.cpp b/src/privatesend-client.cpp
index 8ee4fd028935f..cde47427bf022 100644
--- a/src/privatesend-client.cpp
+++ b/src/privatesend-client.cpp
@@ -552,7 +552,7 @@ bool CPrivateSendClient::SignFinalTransaction(const CTransaction& finalTransacti
// push all of our signatures to the Masternode
LogPrintf("CPrivateSendClient::SignFinalTransaction -- pushing sigs to the masternode, finalMutableTransaction=%s", finalMutableTransaction.ToString());
- pnode->PushMessage(NetMsgType::DSSIGNFINALTX, sigs);
+ g_connman->PushMessage(pnode, NetMsgType::DSSIGNFINALTX, sigs);
SetState(POOL_STATE_SIGNING);
nTimeLastSuccessfulStep = GetTimeMillis();
@@ -870,7 +870,7 @@ bool CPrivateSendClient::JoinExistingQueue(CAmount nBalanceNeedsAnonymized)
infoMixingMasternode = infoMn;
nSessionDenom = dsq.nDenom;
- pnode->PushMessage(NetMsgType::DSACCEPT, nSessionDenom, txMyCollateral);
+ g_connman->PushMessage(pnode, NetMsgType::DSACCEPT, nSessionDenom, txMyCollateral);
LogPrintf("CPrivateSendClient::JoinExistingQueue -- connected (from queue), sending DSACCEPT: nSessionDenom: %d (%s), addr=%s\n",
nSessionDenom, CPrivateSend::GetDenominationsToString(nSessionDenom), pnode->addr.ToString());
strAutoDenomResult = _("Mixing in progress...");
@@ -953,7 +953,7 @@ bool CPrivateSendClient::StartNewQueue(CAmount nValueMin, CAmount nBalanceNeedsA
nSessionDenom = CPrivateSend::GetDenominationsByAmounts(vecAmounts);
}
- pnode->PushMessage(NetMsgType::DSACCEPT, nSessionDenom, txMyCollateral);
+ g_connman->PushMessage(pnode, NetMsgType::DSACCEPT, nSessionDenom, txMyCollateral);
LogPrintf("CPrivateSendClient::StartNewQueue -- connected, sending DSACCEPT, nSessionDenom: %d (%s)\n",
nSessionDenom, CPrivateSend::GetDenominationsToString(nSessionDenom));
strAutoDenomResult = _("Mixing in progress...");
@@ -1374,7 +1374,7 @@ void CPrivateSendClient::RelayIn(const CDarkSendEntry& entry)
g_connman->ForNode(infoMixingMasternode.addr, [&entry](CNode* pnode) {
LogPrintf("CPrivateSendClient::RelayIn -- found master, relaying message to %s\n", pnode->addr.ToString());
- pnode->PushMessage(NetMsgType::DSVIN, entry);
+ g_connman->PushMessage(pnode, NetMsgType::DSVIN, entry);
return true;
});
}
diff --git a/src/privatesend-server.cpp b/src/privatesend-server.cpp
index 0eb592f70989f..8a3b58e119bbd 100644
--- a/src/privatesend-server.cpp
+++ b/src/privatesend-server.cpp
@@ -802,7 +802,7 @@ void CPrivateSendServer::RelayFinalTransaction(const CTransaction& txFinal)
// final mixing tx with empty signatures should be relayed to mixing participants only
for (const auto entry : vecEntries) {
bool fOk = g_connman->ForNode(entry.addr, [&txFinal, this](CNode* pnode) {
- pnode->PushMessage(NetMsgType::DSFINALTX, nSessionID, txFinal);
+ g_connman->PushMessage(pnode, NetMsgType::DSFINALTX, nSessionID, txFinal);
return true;
});
if(!fOk) {
@@ -816,7 +816,7 @@ void CPrivateSendServer::RelayFinalTransaction(const CTransaction& txFinal)
void CPrivateSendServer::PushStatus(CNode* pnode, PoolStatusUpdate nStatusUpdate, PoolMessage nMessageID)
{
if(!pnode) return;
- pnode->PushMessage(NetMsgType::DSSTATUSUPDATE, nSessionID, (int)nState, (int)vecEntries.size(), (int)nStatusUpdate, (int)nMessageID);
+ g_connman->PushMessage(pnode, NetMsgType::DSSTATUSUPDATE, nSessionID, (int)nState, (int)vecEntries.size(), (int)nStatusUpdate, (int)nMessageID);
}
void CPrivateSendServer::RelayStatus(PoolStatusUpdate nStatusUpdate, PoolMessage nMessageID)
@@ -863,7 +863,7 @@ void CPrivateSendServer::RelayCompletedTransaction(PoolMessage nMessageID)
// final mixing tx with empty signatures should be relayed to mixing participants only
for (const auto entry : vecEntries) {
bool fOk = g_connman->ForNode(entry.addr, [&nMessageID, this](CNode* pnode) {
- pnode->PushMessage(NetMsgType::DSCOMPLETE, nSessionID, (int)nMessageID);
+ g_connman->PushMessage(pnode, NetMsgType::DSCOMPLETE, nSessionID, (int)nMessageID);
return true;
});
if(!fOk) {
diff --git a/src/privatesend.cpp b/src/privatesend.cpp
index 31efaa80a8631..bc2503417da40 100644
--- a/src/privatesend.cpp
+++ b/src/privatesend.cpp
@@ -77,7 +77,7 @@ bool CDarksendQueue::Relay()
std::vector vNodesCopy = g_connman->CopyNodeVector();
BOOST_FOREACH(CNode* pnode, vNodesCopy)
if(pnode->nVersion >= MIN_PRIVATESEND_PEER_PROTO_VERSION)
- pnode->PushMessage(NetMsgType::DSQUEUE, (*this));
+ g_connman->PushMessage(pnode, NetMsgType::DSQUEUE, (*this));
g_connman->ReleaseNodeVector(vNodesCopy);
return true;
diff --git a/src/sendalert.cpp b/src/sendalert.cpp
index 53cd3fc847bf2..cbc1bc6369ef9 100644
--- a/src/sendalert.cpp
+++ b/src/sendalert.cpp
@@ -101,7 +101,7 @@ void ThreadSendAlert(CConnman& connman)
int nSent = 0;
{
g_connman->ForEachNode([&alert2, &nSent](CNode* pnode) {
- if (alert2.RelayTo(pnode))
+ if (alert2.RelayTo(pnode, *g_connman))
{
printf("ThreadSendAlert() : Sent alert to %s\n", pnode->addr.ToString().c_str());
nSent++;
diff --git a/src/serialize.h b/src/serialize.h
index 649fe69728aee..cf4267f6b47cf 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -173,6 +173,7 @@ enum
};
#define READWRITE(obj) (::SerReadWrite(s, (obj), nType, nVersion, ser_action))
+#define READWRITEMANY(...) (::SerReadWriteMany(s, nType, nVersion, ser_action, __VA_ARGS__))
/**
* Implement three methods for serializable objects. These are actually wrappers over
@@ -983,4 +984,52 @@ class CSizeComputer
}
};
+template
+void SerializeMany(Stream& s, int nType, int nVersion)
+{
+}
+
+template
+void SerializeMany(Stream& s, int nType, int nVersion, Arg&& arg)
+{
+ ::Serialize(s, std::forward(arg), nType, nVersion);
+}
+
+template
+void SerializeMany(Stream& s, int nType, int nVersion, Arg&& arg, Args&&... args)
+{
+ ::Serialize(s, std::forward(arg), nType, nVersion);
+ ::SerializeMany(s, nType, nVersion, std::forward(args)...);
+}
+
+template
+inline void UnserializeMany(Stream& s, int nType, int nVersion)
+{
+}
+
+template
+inline void UnserializeMany(Stream& s, int nType, int nVersion, Arg& arg)
+{
+ ::Unserialize(s, arg, nType, nVersion);
+}
+
+template
+inline void UnserializeMany(Stream& s, int nType, int nVersion, Arg& arg, Args&... args)
+{
+ ::Unserialize(s, arg, nType, nVersion);
+ ::UnserializeMany(s, nType, nVersion, args...);
+}
+
+template
+inline void SerReadWriteMany(Stream& s, int nType, int nVersion, CSerActionSerialize ser_action, Args&&... args)
+{
+ ::SerializeMany(s, nType, nVersion, std::forward(args)...);
+}
+
+template
+inline void SerReadWriteMany(Stream& s, int nType, int nVersion, CSerActionUnserialize ser_action, Args&... args)
+{
+ ::UnserializeMany(s, nType, nVersion, args...);
+}
+
#endif // BITCOIN_SERIALIZE_H
diff --git a/src/spork.cpp b/src/spork.cpp
index 788f7ac08737b..af4ad9480695a 100644
--- a/src/spork.cpp
+++ b/src/spork.cpp
@@ -64,7 +64,7 @@ void CSporkManager::ProcessSpork(CNode* pfrom, std::string& strCommand, CDataStr
std::map::iterator it = mapSporksActive.begin();
while(it != mapSporksActive.end()) {
- pfrom->PushMessage(NetMsgType::SPORK, it->second);
+ g_connman->PushMessage(pfrom, NetMsgType::SPORK, it->second);
it++;
}
}
diff --git a/src/streams.h b/src/streams.h
index 0fc6135a6a793..3d887feb3b765 100644
--- a/src/streams.h
+++ b/src/streams.h
@@ -79,6 +79,13 @@ class CDataStream
Init(nTypeIn, nVersionIn);
}
+ template
+ CDataStream(int nTypeIn, int nVersionIn, Args&&... args)
+ {
+ Init(nTypeIn, nVersionIn);
+ ::SerializeMany(*this, nType, nVersion, std::forward(args)...);
+ }
+
void Init(int nTypeIn, int nVersionIn)
{
nReadPos = 0;
diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp
index cc65784d2cf75..16f596414ca51 100644
--- a/src/test/DoS_tests.cpp
+++ b/src/test/DoS_tests.cpp
@@ -49,7 +49,8 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
connman->ClearBanned();
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, "", true);
- GetNodeSignals().InitializeNode(dummyNode1.GetId(), &dummyNode1);
+ dummyNode1.SetSendVersion(PROTOCOL_VERSION);
+ GetNodeSignals().InitializeNode(&dummyNode1, *connman);
dummyNode1.nVersion = 1;
Misbehaving(dummyNode1.GetId(), 100); // Should get banned
SendMessages(&dummyNode1, *connman);
@@ -58,7 +59,8 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
CAddress addr2(ip(0xa0b0c002), NODE_NONE);
CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, "", true);
- GetNodeSignals().InitializeNode(dummyNode2.GetId(), &dummyNode2);
+ dummyNode2.SetSendVersion(PROTOCOL_VERSION);
+ GetNodeSignals().InitializeNode(&dummyNode2, *connman);
dummyNode2.nVersion = 1;
Misbehaving(dummyNode2.GetId(), 50);
SendMessages(&dummyNode2, *connman);
@@ -75,7 +77,8 @@ BOOST_AUTO_TEST_CASE(DoS_banscore)
mapArgs["-banscore"] = "111"; // because 11 is my favorite number
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, "", true);
- GetNodeSignals().InitializeNode(dummyNode1.GetId(), &dummyNode1);
+ dummyNode1.SetSendVersion(PROTOCOL_VERSION);
+ GetNodeSignals().InitializeNode(&dummyNode1, *connman);
dummyNode1.nVersion = 1;
Misbehaving(dummyNode1.GetId(), 100);
SendMessages(&dummyNode1, *connman);
@@ -97,7 +100,8 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
CAddress addr(ip(0xa0b0c001), NODE_NONE);
CNode dummyNode(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr, "", true);
- GetNodeSignals().InitializeNode(dummyNode.GetId(), &dummyNode);
+ dummyNode.SetSendVersion(PROTOCOL_VERSION);
+ GetNodeSignals().InitializeNode(&dummyNode, *connman);
dummyNode.nVersion = 1;
Misbehaving(dummyNode.GetId(), 100);
diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp
index 3b76f2129d374..0a253e1fe5c4d 100644
--- a/src/test/serialize_tests.cpp
+++ b/src/test/serialize_tests.cpp
@@ -10,11 +10,54 @@
#include
#include
-
using namespace std;
BOOST_FIXTURE_TEST_SUITE(serialize_tests, BasicTestingSetup)
+class CSerializeMethodsTestSingle
+{
+protected:
+ int intval;
+ bool boolval;
+ std::string stringval;
+ const char* charstrval;
+ CTransaction txval;
+public:
+ CSerializeMethodsTestSingle() = default;
+ CSerializeMethodsTestSingle(int intvalin, bool boolvalin, std::string stringvalin, const char* charstrvalin, CTransaction txvalin) : intval(intvalin), boolval(boolvalin), stringval(std::move(stringvalin)), charstrval(charstrvalin), txval(txvalin){}
+ ADD_SERIALIZE_METHODS;
+
+ template
+ inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ READWRITE(intval);
+ READWRITE(boolval);
+ READWRITE(stringval);
+ READWRITE(FLATDATA(charstrval));
+ READWRITE(txval);
+ }
+
+ bool operator==(const CSerializeMethodsTestSingle& rhs)
+ {
+ return intval == rhs.intval && \
+ boolval == rhs.boolval && \
+ stringval == rhs.stringval && \
+ strcmp(charstrval, rhs.charstrval) == 0 && \
+ txval == rhs.txval;
+ }
+};
+
+class CSerializeMethodsTestMany : public CSerializeMethodsTestSingle
+{
+public:
+ using CSerializeMethodsTestSingle::CSerializeMethodsTestSingle;
+ ADD_SERIALIZE_METHODS;
+
+ template
+ inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ READWRITEMANY(intval, boolval, stringval, FLATDATA(charstrval), txval);
+ }
+};
+
BOOST_AUTO_TEST_CASE(sizes)
{
BOOST_CHECK_EQUAL(sizeof(char), GetSerializeSize(char(0), 0));
@@ -325,4 +368,30 @@ BOOST_AUTO_TEST_CASE(check_backward_compatibility)
BOOST_REQUIRE(new_src.field1 == old_dest.field1);
}
+BOOST_AUTO_TEST_CASE(class_methods)
+{
+ int intval(100);
+ bool boolval(true);
+ std::string stringval("testing");
+ const char* charstrval("testing charstr");
+ CMutableTransaction txval;
+ CSerializeMethodsTestSingle methodtest1(intval, boolval, stringval, charstrval, txval);
+ CSerializeMethodsTestMany methodtest2(intval, boolval, stringval, charstrval, txval);
+ CSerializeMethodsTestSingle methodtest3;
+ CSerializeMethodsTestMany methodtest4;
+ CDataStream ss(SER_DISK, PROTOCOL_VERSION);
+ BOOST_CHECK(methodtest1 == methodtest2);
+ ss << methodtest1;
+ ss >> methodtest4;
+ ss << methodtest2;
+ ss >> methodtest3;
+ BOOST_CHECK(methodtest1 == methodtest2);
+ BOOST_CHECK(methodtest2 == methodtest3);
+ BOOST_CHECK(methodtest3 == methodtest4);
+
+ CDataStream ss2(SER_DISK, PROTOCOL_VERSION, intval, boolval, stringval, FLATDATA(charstrval), txval);
+ ss2 >> methodtest3;
+ BOOST_CHECK(methodtest3 == methodtest4);
+}
+
BOOST_AUTO_TEST_SUITE_END()