|
|
|
@ -123,11 +123,6 @@ namespace {
|
|
|
|
|
std::deque<std::pair<int64_t, MapRelay::iterator>> vRelayExpiration;
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// Registration of network node signals.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
struct CBlockReject {
|
|
|
|
@ -244,7 +239,7 @@ void UpdatePreferredDownload(CNode* node, CNodeState* state)
|
|
|
|
|
nPreferredDownload += state->fPreferredDownload;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PushNodeVersion(CNode *pnode, CConnman& connman, int64_t nTime)
|
|
|
|
|
void PushNodeVersion(CNode *pnode, CConnman* connman, int64_t nTime)
|
|
|
|
|
{
|
|
|
|
|
ServiceFlags nLocalNodeServices = pnode->GetLocalServices();
|
|
|
|
|
uint64_t nonce = pnode->GetLocalNonce();
|
|
|
|
@ -255,7 +250,7 @@ void PushNodeVersion(CNode *pnode, CConnman& connman, int64_t nTime)
|
|
|
|
|
CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService(), addr.nServices));
|
|
|
|
|
CAddress addrMe = CAddress(CService(), nLocalNodeServices);
|
|
|
|
|
|
|
|
|
|
connman.PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, PROTOCOL_VERSION, (uint64_t)nLocalNodeServices, nTime, addrYou, addrMe,
|
|
|
|
|
connman->PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, PROTOCOL_VERSION, (uint64_t)nLocalNodeServices, nTime, addrYou, addrMe,
|
|
|
|
|
nonce, strSubVersion, nNodeStartingHeight, ::fRelayTxes));
|
|
|
|
|
|
|
|
|
|
if (fLogIPs) {
|
|
|
|
@ -265,50 +260,6 @@ void PushNodeVersion(CNode *pnode, CConnman& connman, int64_t nTime)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InitializeNode(CNode *pnode, CConnman& connman) {
|
|
|
|
|
CAddress addr = pnode->addr;
|
|
|
|
|
std::string addrName = pnode->GetAddrName();
|
|
|
|
|
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) {
|
|
|
|
|
fUpdateConnectionTime = false;
|
|
|
|
|
LOCK(cs_main);
|
|
|
|
|
CNodeState *state = State(nodeid);
|
|
|
|
|
assert(state != nullptr);
|
|
|
|
|
|
|
|
|
|
if (state->fSyncStarted)
|
|
|
|
|
nSyncStarted--;
|
|
|
|
|
|
|
|
|
|
if (state->nMisbehavior == 0 && state->fCurrentlyConnected) {
|
|
|
|
|
fUpdateConnectionTime = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const QueuedBlock& entry : state->vBlocksInFlight) {
|
|
|
|
|
mapBlocksInFlight.erase(entry.hash);
|
|
|
|
|
}
|
|
|
|
|
EraseOrphansFor(nodeid);
|
|
|
|
|
nPreferredDownload -= state->fPreferredDownload;
|
|
|
|
|
nPeersWithValidatedDownloads -= (state->nBlocksInFlightValidHeaders != 0);
|
|
|
|
|
assert(nPeersWithValidatedDownloads >= 0);
|
|
|
|
|
|
|
|
|
|
mapNodeState.erase(nodeid);
|
|
|
|
|
|
|
|
|
|
if (mapNodeState.empty()) {
|
|
|
|
|
// Do a consistency check after the last peer is removed.
|
|
|
|
|
assert(mapBlocksInFlight.empty());
|
|
|
|
|
assert(nPreferredDownload == 0);
|
|
|
|
|
assert(nPeersWithValidatedDownloads == 0);
|
|
|
|
|
}
|
|
|
|
|
LogPrint(BCLog::NET, "Cleared nodestate for peer=%d\n", nodeid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Requires cs_main.
|
|
|
|
|
// Returns a bool indicating whether we requested this block.
|
|
|
|
|
// Also used if a block was /not/ received and timed out or started with another peer
|
|
|
|
@ -404,7 +355,7 @@ void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid, CConnman& connman) {
|
|
|
|
|
void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid, CConnman* connman) {
|
|
|
|
|
AssertLockHeld(cs_main);
|
|
|
|
|
CNodeState* nodestate = State(nodeid);
|
|
|
|
|
if (!nodestate || !nodestate->fSupportsDesiredCmpctVersion) {
|
|
|
|
@ -419,20 +370,20 @@ void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid, CConnman& connman) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
connman.ForNode(nodeid, [&connman](CNode* pfrom){
|
|
|
|
|
connman->ForNode(nodeid, [connman](CNode* pfrom){
|
|
|
|
|
bool fAnnounceUsingCMPCTBLOCK = false;
|
|
|
|
|
uint64_t nCMPCTBLOCKVersion = (pfrom->GetLocalServices() & NODE_WITNESS) ? 2 : 1;
|
|
|
|
|
if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
|
|
|
|
|
// As per BIP152, we only get 3 of our peers to announce
|
|
|
|
|
// blocks using compact encodings.
|
|
|
|
|
connman.ForNode(lNodesAnnouncingHeaderAndIDs.front(), [&connman, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion](CNode* pnodeStop){
|
|
|
|
|
connman.PushMessage(pnodeStop, CNetMsgMaker(pnodeStop->GetSendVersion()).Make(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion));
|
|
|
|
|
connman->ForNode(lNodesAnnouncingHeaderAndIDs.front(), [connman, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion](CNode* pnodeStop){
|
|
|
|
|
connman->PushMessage(pnodeStop, CNetMsgMaker(pnodeStop->GetSendVersion()).Make(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion));
|
|
|
|
|
return true;
|
|
|
|
|
});
|
|
|
|
|
lNodesAnnouncingHeaderAndIDs.pop_front();
|
|
|
|
|
}
|
|
|
|
|
fAnnounceUsingCMPCTBLOCK = true;
|
|
|
|
|
connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion));
|
|
|
|
|
connman->PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion));
|
|
|
|
|
lNodesAnnouncingHeaderAndIDs.push_back(pfrom->GetId());
|
|
|
|
|
return true;
|
|
|
|
|
});
|
|
|
|
@ -545,6 +496,50 @@ void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<con
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
void PeerLogicValidation::InitializeNode(CNode *pnode) {
|
|
|
|
|
CAddress addr = pnode->addr;
|
|
|
|
|
std::string addrName = pnode->GetAddrName();
|
|
|
|
|
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 PeerLogicValidation::FinalizeNode(NodeId nodeid, bool& fUpdateConnectionTime) {
|
|
|
|
|
fUpdateConnectionTime = false;
|
|
|
|
|
LOCK(cs_main);
|
|
|
|
|
CNodeState *state = State(nodeid);
|
|
|
|
|
assert(state != nullptr);
|
|
|
|
|
|
|
|
|
|
if (state->fSyncStarted)
|
|
|
|
|
nSyncStarted--;
|
|
|
|
|
|
|
|
|
|
if (state->nMisbehavior == 0 && state->fCurrentlyConnected) {
|
|
|
|
|
fUpdateConnectionTime = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const QueuedBlock& entry : state->vBlocksInFlight) {
|
|
|
|
|
mapBlocksInFlight.erase(entry.hash);
|
|
|
|
|
}
|
|
|
|
|
EraseOrphansFor(nodeid);
|
|
|
|
|
nPreferredDownload -= state->fPreferredDownload;
|
|
|
|
|
nPeersWithValidatedDownloads -= (state->nBlocksInFlightValidHeaders != 0);
|
|
|
|
|
assert(nPeersWithValidatedDownloads >= 0);
|
|
|
|
|
|
|
|
|
|
mapNodeState.erase(nodeid);
|
|
|
|
|
|
|
|
|
|
if (mapNodeState.empty()) {
|
|
|
|
|
// Do a consistency check after the last peer is removed.
|
|
|
|
|
assert(mapBlocksInFlight.empty());
|
|
|
|
|
assert(nPreferredDownload == 0);
|
|
|
|
|
assert(nPeersWithValidatedDownloads == 0);
|
|
|
|
|
}
|
|
|
|
|
LogPrint(BCLog::NET, "Cleared nodestate for peer=%d\n", nodeid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) {
|
|
|
|
|
LOCK(cs_main);
|
|
|
|
|
CNodeState *state = State(nodeid);
|
|
|
|
@ -560,22 +555,6 @@ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RegisterNodeSignals(CNodeSignals& nodeSignals)
|
|
|
|
|
{
|
|
|
|
|
nodeSignals.ProcessMessages.connect(&ProcessMessages);
|
|
|
|
|
nodeSignals.SendMessages.connect(&SendMessages);
|
|
|
|
|
nodeSignals.InitializeNode.connect(&InitializeNode);
|
|
|
|
|
nodeSignals.FinalizeNode.connect(&FinalizeNode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UnregisterNodeSignals(CNodeSignals& nodeSignals)
|
|
|
|
|
{
|
|
|
|
|
nodeSignals.ProcessMessages.disconnect(&ProcessMessages);
|
|
|
|
|
nodeSignals.SendMessages.disconnect(&SendMessages);
|
|
|
|
|
nodeSignals.InitializeNode.disconnect(&InitializeNode);
|
|
|
|
|
nodeSignals.FinalizeNode.disconnect(&FinalizeNode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// mapOrphanTransactions
|
|
|
|
@ -867,7 +846,7 @@ void PeerLogicValidation::BlockChecked(const CBlock& block, const CValidationSta
|
|
|
|
|
!IsInitialBlockDownload() &&
|
|
|
|
|
mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
|
|
|
|
|
if (it != mapBlockSource.end()) {
|
|
|
|
|
MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first, *connman);
|
|
|
|
|
MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first, connman);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (it != mapBlockSource.end())
|
|
|
|
@ -912,16 +891,16 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void RelayTransaction(const CTransaction& tx, CConnman& connman)
|
|
|
|
|
static void RelayTransaction(const CTransaction& tx, CConnman* connman)
|
|
|
|
|
{
|
|
|
|
|
CInv inv(MSG_TX, tx.GetHash());
|
|
|
|
|
connman.ForEachNode([&inv](CNode* pnode)
|
|
|
|
|
connman->ForEachNode([&inv](CNode* pnode)
|
|
|
|
|
{
|
|
|
|
|
pnode->PushInventory(inv);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void RelayAddress(const CAddress& addr, bool fReachable, CConnman& connman)
|
|
|
|
|
static void RelayAddress(const CAddress& addr, bool fReachable, CConnman* connman)
|
|
|
|
|
{
|
|
|
|
|
unsigned int nRelayNodes = fReachable ? 2 : 1; // limited relaying of addresses outside our network(s)
|
|
|
|
|
|
|
|
|
@ -929,7 +908,7 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman& connma
|
|
|
|
|
// Use deterministic randomness to send to the same nodes for 24 hours
|
|
|
|
|
// at a time so the addrKnowns of the chosen nodes prevent repeats
|
|
|
|
|
uint64_t hashAddr = addr.GetHash();
|
|
|
|
|
const CSipHasher hasher = connman.GetDeterministicRandomizer(RANDOMIZER_ID_ADDRESS_RELAY).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24*60*60));
|
|
|
|
|
const CSipHasher hasher = connman->GetDeterministicRandomizer(RANDOMIZER_ID_ADDRESS_RELAY).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24*60*60));
|
|
|
|
|
FastRandomContext insecure_rand;
|
|
|
|
|
|
|
|
|
|
std::array<std::pair<uint64_t, CNode*>,2> best{{{0, nullptr}, {0, nullptr}}};
|
|
|
|
@ -954,10 +933,10 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman& connma
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
connman.ForEachNodeThen(std::move(sortfunc), std::move(pushfunc));
|
|
|
|
|
connman->ForEachNodeThen(std::move(sortfunc), std::move(pushfunc));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParams, CConnman& connman, const std::atomic<bool>& interruptMsgProc)
|
|
|
|
|
void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParams, CConnman* connman, const std::atomic<bool>& interruptMsgProc)
|
|
|
|
|
{
|
|
|
|
|
std::deque<CInv>::iterator it = pfrom->vRecvGetData.begin();
|
|
|
|
|
std::vector<CInv> vNotFound;
|
|
|
|
@ -1019,7 +998,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
|
|
|
|
|
// disconnect node in case we have reached the outbound limit for serving historical blocks
|
|
|
|
|
// never disconnect whitelisted nodes
|
|
|
|
|
static const int nOneWeek = 7 * 24 * 60 * 60; // assume > 1 week = historical
|
|
|
|
|
if (send && connman.OutboundTargetReached(true) && ( ((pindexBestHeader != nullptr) && (pindexBestHeader->GetBlockTime() - mi->second->GetBlockTime() > nOneWeek)) || inv.type == MSG_FILTERED_BLOCK) && !pfrom->fWhitelisted)
|
|
|
|
|
if (send && connman->OutboundTargetReached(true) && ( ((pindexBestHeader != nullptr) && (pindexBestHeader->GetBlockTime() - mi->second->GetBlockTime() > nOneWeek)) || inv.type == MSG_FILTERED_BLOCK) && !pfrom->fWhitelisted)
|
|
|
|
|
{
|
|
|
|
|
LogPrint(BCLog::NET, "historical block serving limit reached, disconnect peer=%d\n", pfrom->GetId());
|
|
|
|
|
|
|
|
|
@ -1042,9 +1021,9 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
|
|
|
|
|
pblock = pblockRead;
|
|
|
|
|
}
|
|
|
|
|
if (inv.type == MSG_BLOCK)
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, *pblock));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, *pblock));
|
|
|
|
|
else if (inv.type == MSG_WITNESS_BLOCK)
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::BLOCK, *pblock));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::BLOCK, *pblock));
|
|
|
|
|
else if (inv.type == MSG_FILTERED_BLOCK)
|
|
|
|
|
{
|
|
|
|
|
bool sendMerkleBlock = false;
|
|
|
|
@ -1057,7 +1036,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (sendMerkleBlock) {
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::MERKLEBLOCK, merkleBlock));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(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 -
|
|
|
|
@ -1066,7 +1045,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<unsigned int, uint256> PairType;
|
|
|
|
|
for (PairType& pair : merkleBlock.vMatchedTxn)
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::TX, *pblock->vtx[pair.first]));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::TX, *pblock->vtx[pair.first]));
|
|
|
|
|
}
|
|
|
|
|
// else
|
|
|
|
|
// no response
|
|
|
|
@ -1081,13 +1060,13 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
|
|
|
|
|
int nSendFlags = fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS;
|
|
|
|
|
if (CanDirectFetch(consensusParams) && mi->second->nHeight >= chainActive.Height() - MAX_CMPCTBLOCK_DEPTH) {
|
|
|
|
|
if ((fPeerWantsWitness || !fWitnessesPresentInARecentCompactBlock) && a_recent_compact_block && a_recent_compact_block->header.GetHash() == mi->second->GetBlockHash()) {
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, *a_recent_compact_block));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, *a_recent_compact_block));
|
|
|
|
|
} else {
|
|
|
|
|
CBlockHeaderAndShortTxIDs cmpctblock(*pblock, fPeerWantsWitness);
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::BLOCK, *pblock));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::BLOCK, *pblock));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1099,7 +1078,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
|
|
|
|
|
// wait for other stuff first.
|
|
|
|
|
std::vector<CInv> vInv;
|
|
|
|
|
vInv.push_back(CInv(MSG_BLOCK, chainActive.Tip()->GetBlockHash()));
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::INV, vInv));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::INV, vInv));
|
|
|
|
|
pfrom->hashContinue.SetNull();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1111,14 +1090,14 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
|
|
|
|
|
auto mi = mapRelay.find(inv.hash);
|
|
|
|
|
int nSendFlags = (inv.type == MSG_TX ? SERIALIZE_TRANSACTION_NO_WITNESS : 0);
|
|
|
|
|
if (mi != mapRelay.end()) {
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *mi->second));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *mi->second));
|
|
|
|
|
push = true;
|
|
|
|
|
} else if (pfrom->timeLastMempoolReq) {
|
|
|
|
|
auto txinfo = mempool.info(inv.hash);
|
|
|
|
|
// To protect privacy, do not answer getdata using the mempool when
|
|
|
|
|
// that TX couldn't have been INVed in reply to a MEMPOOL request.
|
|
|
|
|
if (txinfo.tx && txinfo.nTime <= pfrom->timeLastMempoolReq) {
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *txinfo.tx));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::TX, *txinfo.tx));
|
|
|
|
|
push = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1145,7 +1124,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.
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::NOTFOUND, vNotFound));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::NOTFOUND, vNotFound));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1157,7 +1136,7 @@ uint32_t GetFetchFlags(CNode* pfrom) {
|
|
|
|
|
return nFetchFlags;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline void static SendBlockTransactions(const CBlock& block, const BlockTransactionsRequest& req, CNode* pfrom, CConnman& connman) {
|
|
|
|
|
inline void static SendBlockTransactions(const CBlock& block, const BlockTransactionsRequest& req, CNode* pfrom, CConnman* connman) {
|
|
|
|
|
BlockTransactions resp(req);
|
|
|
|
|
for (size_t i = 0; i < req.indexes.size(); i++) {
|
|
|
|
|
if (req.indexes[i] >= block.vtx.size()) {
|
|
|
|
@ -1171,10 +1150,10 @@ inline void static SendBlockTransactions(const CBlock& block, const BlockTransac
|
|
|
|
|
LOCK(cs_main);
|
|
|
|
|
const CNetMsgMaker msgMaker(pfrom->GetSendVersion());
|
|
|
|
|
int nSendFlags = State(pfrom->GetId())->fWantsCmpctWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS;
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::BLOCKTXN, resp));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::BLOCKTXN, resp));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman& connman, const std::atomic<bool>& interruptMsgProc)
|
|
|
|
|
bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman* connman, const std::atomic<bool>& interruptMsgProc)
|
|
|
|
|
{
|
|
|
|
|
LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->GetId());
|
|
|
|
|
if (gArgs.IsArgSet("-dropmessagestest") && GetRand(gArgs.GetArg("-dropmessagestest", 0)) == 0)
|
|
|
|
@ -1227,7 +1206,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
// Each connection can only send one version message
|
|
|
|
|
if (pfrom->nVersion != 0)
|
|
|
|
|
{
|
|
|
|
|
connman.PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_DUPLICATE, std::string("Duplicate version message")));
|
|
|
|
|
connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_DUPLICATE, std::string("Duplicate version message")));
|
|
|
|
|
LOCK(cs_main);
|
|
|
|
|
Misbehaving(pfrom->GetId(), 1);
|
|
|
|
|
return false;
|
|
|
|
@ -1251,12 +1230,12 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
nServices = ServiceFlags(nServiceInt);
|
|
|
|
|
if (!pfrom->fInbound)
|
|
|
|
|
{
|
|
|
|
|
connman.SetServices(pfrom->addr, nServices);
|
|
|
|
|
connman->SetServices(pfrom->addr, nServices);
|
|
|
|
|
}
|
|
|
|
|
if (pfrom->nServicesExpected & ~nServices)
|
|
|
|
|
{
|
|
|
|
|
LogPrint(BCLog::NET, "peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom->GetId(), nServices, pfrom->nServicesExpected);
|
|
|
|
|
connman.PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_NONSTANDARD,
|
|
|
|
|
connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_NONSTANDARD,
|
|
|
|
|
strprintf("Expected to offer services %08x", pfrom->nServicesExpected)));
|
|
|
|
|
pfrom->fDisconnect = true;
|
|
|
|
|
return false;
|
|
|
|
@ -1277,7 +1256,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
{
|
|
|
|
|
// disconnect from peers older than this proto version
|
|
|
|
|
LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->GetId(), nVersion);
|
|
|
|
|
connman.PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE,
|
|
|
|
|
connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE,
|
|
|
|
|
strprintf("Version must be %d or greater", MIN_PEER_PROTO_VERSION)));
|
|
|
|
|
pfrom->fDisconnect = true;
|
|
|
|
|
return false;
|
|
|
|
@ -1297,7 +1276,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
if (!vRecv.empty())
|
|
|
|
|
vRecv >> fRelay;
|
|
|
|
|
// Disconnect if we connected to ourself
|
|
|
|
|
if (pfrom->fInbound && !connman.CheckIncomingNonce(nNonce))
|
|
|
|
|
if (pfrom->fInbound && !connman->CheckIncomingNonce(nNonce))
|
|
|
|
|
{
|
|
|
|
|
LogPrintf("connected to self at %s, disconnecting\n", pfrom->addr.ToString());
|
|
|
|
|
pfrom->fDisconnect = true;
|
|
|
|
@ -1313,7 +1292,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
if (pfrom->fInbound)
|
|
|
|
|
PushNodeVersion(pfrom, connman, GetAdjustedTime());
|
|
|
|
|
|
|
|
|
|
connman.PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERACK));
|
|
|
|
|
connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERACK));
|
|
|
|
|
|
|
|
|
|
pfrom->nServices = nServices;
|
|
|
|
|
pfrom->SetAddrLocal(addrMe);
|
|
|
|
@ -1364,12 +1343,12 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get recent addresses
|
|
|
|
|
if (pfrom->fOneShot || pfrom->nVersion >= CADDR_TIME_VERSION || connman.GetAddressCount() < 1000)
|
|
|
|
|
if (pfrom->fOneShot || pfrom->nVersion >= CADDR_TIME_VERSION || connman->GetAddressCount() < 1000)
|
|
|
|
|
{
|
|
|
|
|
connman.PushMessage(pfrom, CNetMsgMaker(nSendVersion).Make(NetMsgType::GETADDR));
|
|
|
|
|
connman->PushMessage(pfrom, CNetMsgMaker(nSendVersion).Make(NetMsgType::GETADDR));
|
|
|
|
|
pfrom->fGetAddr = true;
|
|
|
|
|
}
|
|
|
|
|
connman.MarkAddressGood(pfrom->addr);
|
|
|
|
|
connman->MarkAddressGood(pfrom->addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string remoteAddr;
|
|
|
|
@ -1388,7 +1367,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
// If the peer is old enough to have the old alert system, send it the final alert.
|
|
|
|
|
if (pfrom->nVersion <= 70012) {
|
|
|
|
|
CDataStream finalAlert(ParseHex("60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50"), SER_NETWORK, PROTOCOL_VERSION);
|
|
|
|
|
connman.PushMessage(pfrom, CNetMsgMaker(nSendVersion).Make("alert", finalAlert));
|
|
|
|
|
connman->PushMessage(pfrom, CNetMsgMaker(nSendVersion).Make("alert", finalAlert));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Feeler connections exist only to verify if address is online.
|
|
|
|
@ -1426,7 +1405,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
// We send this to non-NODE NETWORK peers as well, because even
|
|
|
|
|
// non-NODE NETWORK peers can announce blocks (such as pruning
|
|
|
|
|
// nodes)
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::SENDHEADERS));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::SENDHEADERS));
|
|
|
|
|
}
|
|
|
|
|
if (pfrom->nVersion >= SHORT_IDS_BLOCKS_VERSION) {
|
|
|
|
|
// Tell our peer we are willing to provide version 1 or 2 cmpctblocks
|
|
|
|
@ -1437,9 +1416,9 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
bool fAnnounceUsingCMPCTBLOCK = false;
|
|
|
|
|
uint64_t nCMPCTBLOCKVersion = 2;
|
|
|
|
|
if (pfrom->GetLocalServices() & NODE_WITNESS)
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion));
|
|
|
|
|
nCMPCTBLOCKVersion = 1;
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion));
|
|
|
|
|
}
|
|
|
|
|
pfrom->fSuccessfullyConnected = true;
|
|
|
|
|
}
|
|
|
|
@ -1458,7 +1437,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
vRecv >> vAddr;
|
|
|
|
|
|
|
|
|
|
// Don't want addr from older versions unless seeding
|
|
|
|
|
if (pfrom->nVersion < CADDR_TIME_VERSION && connman.GetAddressCount() > 1000)
|
|
|
|
|
if (pfrom->nVersion < CADDR_TIME_VERSION && connman->GetAddressCount() > 1000)
|
|
|
|
|
return true;
|
|
|
|
|
if (vAddr.size() > 1000)
|
|
|
|
|
{
|
|
|
|
@ -1492,7 +1471,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
if (fReachable)
|
|
|
|
|
vAddrOk.push_back(addr);
|
|
|
|
|
}
|
|
|
|
|
connman.AddNewAddresses(vAddrOk, pfrom->addr, 2 * 60 * 60);
|
|
|
|
|
connman->AddNewAddresses(vAddrOk, pfrom->addr, 2 * 60 * 60);
|
|
|
|
|
if (vAddr.size() < 1000)
|
|
|
|
|
pfrom->fGetAddr = false;
|
|
|
|
|
if (pfrom->fOneShot)
|
|
|
|
@ -1570,7 +1549,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
// fell back to inv we probably have a reorg which we should get the headers for first,
|
|
|
|
|
// we now only provide a getheaders response here. When we receive the headers, we will
|
|
|
|
|
// then ask for the blocks we need.
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), inv.hash));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), inv.hash));
|
|
|
|
|
LogPrint(BCLog::NET, "getheaders (%d) %s to peer=%d\n", pindexBestHeader->nHeight, inv.hash.ToString(), pfrom->GetId());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1776,7 +1755,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
// will re-announce the new block via headers (or compact blocks again)
|
|
|
|
|
// in the SendMessages logic.
|
|
|
|
|
nodestate->pindexBestHeaderSent = pindex ? pindex : chainActive.Tip();
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::HEADERS, vHeaders));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::HEADERS, vHeaders));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1957,7 +1936,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
pfrom->GetId(),
|
|
|
|
|
FormatStateMessage(state));
|
|
|
|
|
if (state.GetRejectCode() > 0 && state.GetRejectCode() < REJECT_INTERNAL) // Never send AcceptToMemoryPool's internal codes over P2P
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(),
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(),
|
|
|
|
|
state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash));
|
|
|
|
|
if (nDoS > 0) {
|
|
|
|
|
Misbehaving(pfrom->GetId(), nDoS);
|
|
|
|
@ -1977,7 +1956,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
if (mapBlockIndex.find(cmpctblock.header.hashPrevBlock) == mapBlockIndex.end()) {
|
|
|
|
|
// Doesn't connect (or is genesis), instead of DoSing in AcceptBlockHeader, request deeper headers
|
|
|
|
|
if (!IsInitialBlockDownload())
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), uint256()));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), uint256()));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -2032,7 +2011,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
// so we just grab the block via normal getdata
|
|
|
|
|
std::vector<CInv> vInv(1);
|
|
|
|
|
vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(pfrom), cmpctblock.header.GetHash());
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv));
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
@ -2076,7 +2055,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
// Duplicate txindexes, the block is now in-flight, so just request it
|
|
|
|
|
std::vector<CInv> vInv(1);
|
|
|
|
|
vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(pfrom), cmpctblock.header.GetHash());
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2093,7 +2072,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
fProcessBLOCKTXN = true;
|
|
|
|
|
} else {
|
|
|
|
|
req.blockhash = pindex->GetBlockHash();
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETBLOCKTXN, req));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETBLOCKTXN, req));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// This block is either already in flight from a different
|
|
|
|
@ -2119,7 +2098,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
// mempool will probably be useless - request the block normally
|
|
|
|
|
std::vector<CInv> vInv(1);
|
|
|
|
|
vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(pfrom), cmpctblock.header.GetHash());
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv));
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
// If this was an announce-cmpctblock, we want the same treatment as a header message
|
|
|
|
@ -2193,7 +2172,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
// Might have collided, fall back to getdata now :(
|
|
|
|
|
std::vector<CInv> invs;
|
|
|
|
|
invs.push_back(CInv(MSG_BLOCK | GetFetchFlags(pfrom), resp.blockhash));
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, invs));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, invs));
|
|
|
|
|
} else {
|
|
|
|
|
// Block is either okay, or possibly we received
|
|
|
|
|
// READ_STATUS_CHECKBLOCK_FAILED.
|
|
|
|
@ -2274,7 +2253,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
// nUnconnectingHeaders gets reset back to 0.
|
|
|
|
|
if (mapBlockIndex.find(headers[0].hashPrevBlock) == mapBlockIndex.end() && nCount < MAX_BLOCKS_TO_ANNOUNCE) {
|
|
|
|
|
nodestate->nUnconnectingHeaders++;
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), uint256()));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), uint256()));
|
|
|
|
|
LogPrint(BCLog::NET, "received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d, nUnconnectingHeaders=%d)\n",
|
|
|
|
|
headers[0].GetHash().ToString(),
|
|
|
|
|
headers[0].hashPrevBlock.ToString(),
|
|
|
|
@ -2329,7 +2308,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
// TODO: optimize: if pindexLast is an ancestor of chainActive.Tip or pindexBestHeader, continue
|
|
|
|
|
// from there instead.
|
|
|
|
|
LogPrint(BCLog::NET, "more getheaders (%d) to end to peer=%d (startheight:%d)\n", pindexLast->nHeight, pfrom->GetId(), pfrom->nStartingHeight);
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexLast), uint256()));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexLast), uint256()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool fCanDirectFetch = CanDirectFetch(chainparams.GetConsensus());
|
|
|
|
@ -2379,7 +2358,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
// In any case, we want to download using a compact block, not a regular one
|
|
|
|
|
vGetData[0] = CInv(MSG_CMPCT_BLOCK, vGetData[0].hash);
|
|
|
|
|
}
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vGetData));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vGetData));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -2440,7 +2419,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
pfrom->fSentAddr = true;
|
|
|
|
|
|
|
|
|
|
pfrom->vAddrToSend.clear();
|
|
|
|
|
std::vector<CAddress> vAddr = connman.GetAddresses();
|
|
|
|
|
std::vector<CAddress> vAddr = connman->GetAddresses();
|
|
|
|
|
FastRandomContext insecure_rand;
|
|
|
|
|
for (const CAddress &addr : vAddr)
|
|
|
|
|
pfrom->PushAddress(addr, insecure_rand);
|
|
|
|
@ -2456,7 +2435,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (connman.OutboundTargetReached(false) && !pfrom->fWhitelisted)
|
|
|
|
|
if (connman->OutboundTargetReached(false) && !pfrom->fWhitelisted)
|
|
|
|
|
{
|
|
|
|
|
LogPrint(BCLog::NET, "mempool request with bandwidth limit reached, disconnect peer=%d\n", pfrom->GetId());
|
|
|
|
|
pfrom->fDisconnect = true;
|
|
|
|
@ -2485,7 +2464,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
// 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.
|
|
|
|
|
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::PONG, nonce));
|
|
|
|
|
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::PONG, nonce));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2631,13 +2610,13 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool SendRejectsAndCheckIfBanned(CNode* pnode, CConnman& connman)
|
|
|
|
|
static bool SendRejectsAndCheckIfBanned(CNode* pnode, CConnman* connman)
|
|
|
|
|
{
|
|
|
|
|
AssertLockHeld(cs_main);
|
|
|
|
|
CNodeState &state = *State(pnode->GetId());
|
|
|
|
|
|
|
|
|
|
for (const CBlockReject& reject : state.rejects) {
|
|
|
|
|
connman.PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, (std::string)NetMsgType::BLOCK, reject.chRejectCode, reject.strRejectReason, reject.hashBlock));
|
|
|
|
|
connman->PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, (std::string)NetMsgType::BLOCK, reject.chRejectCode, reject.strRejectReason, reject.hashBlock));
|
|
|
|
|
}
|
|
|
|
|
state.rejects.clear();
|
|
|
|
|
|
|
|
|
@ -2653,7 +2632,7 @@ static bool SendRejectsAndCheckIfBanned(CNode* pnode, CConnman& connman)
|
|
|
|
|
LogPrintf("Warning: not banning local peer %s!\n", pnode->addr.ToString());
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
connman.Ban(pnode->addr, BanReasonNodeMisbehaving);
|
|
|
|
|
connman->Ban(pnode->addr, BanReasonNodeMisbehaving);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
@ -2661,7 +2640,7 @@ static bool SendRejectsAndCheckIfBanned(CNode* pnode, CConnman& connman)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ProcessMessages(CNode* pfrom, CConnman& connman, const std::atomic<bool>& interruptMsgProc)
|
|
|
|
|
bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& interruptMsgProc)
|
|
|
|
|
{
|
|
|
|
|
const CChainParams& chainparams = Params();
|
|
|
|
|
//
|
|
|
|
@ -2695,7 +2674,7 @@ bool ProcessMessages(CNode* pfrom, CConnman& connman, const std::atomic<bool>& i
|
|
|
|
|
// Just take one message
|
|
|
|
|
msgs.splice(msgs.begin(), pfrom->vProcessMsg, pfrom->vProcessMsg.begin());
|
|
|
|
|
pfrom->nProcessQueueSize -= msgs.front().vRecv.size() + CMessageHeader::HEADER_SIZE;
|
|
|
|
|
pfrom->fPauseRecv = pfrom->nProcessQueueSize > connman.GetReceiveFloodSize();
|
|
|
|
|
pfrom->fPauseRecv = pfrom->nProcessQueueSize > connman->GetReceiveFloodSize();
|
|
|
|
|
fMoreWork = !pfrom->vProcessMsg.empty();
|
|
|
|
|
}
|
|
|
|
|
CNetMessage& msg(msgs.front());
|
|
|
|
@ -2744,7 +2723,7 @@ bool ProcessMessages(CNode* pfrom, CConnman& connman, const std::atomic<bool>& i
|
|
|
|
|
}
|
|
|
|
|
catch (const std::ios_base::failure& e)
|
|
|
|
|
{
|
|
|
|
|
connman.PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_MALFORMED, std::string("error parsing message")));
|
|
|
|
|
connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_MALFORMED, std::string("error parsing message")));
|
|
|
|
|
if (strstr(e.what(), "end of data"))
|
|
|
|
|
{
|
|
|
|
|
// Allow exceptions from under-length message on vRecv
|
|
|
|
@ -2798,7 +2777,7 @@ public:
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interruptMsgProc)
|
|
|
|
|
bool PeerLogicValidation::SendMessages(CNode* pto, std::atomic<bool>& interruptMsgProc)
|
|
|
|
|
{
|
|
|
|
|
const Consensus::Params& consensusParams = Params().GetConsensus();
|
|
|
|
|
{
|
|
|
|
@ -2830,11 +2809,11 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
|
|
|
|
|
pto->nPingUsecStart = GetTimeMicros();
|
|
|
|
|
if (pto->nVersion > BIP0031_VERSION) {
|
|
|
|
|
pto->nPingNonceSent = nonce;
|
|
|
|
|
connman.PushMessage(pto, msgMaker.Make(NetMsgType::PING, nonce));
|
|
|
|
|
connman->PushMessage(pto, msgMaker.Make(NetMsgType::PING, nonce));
|
|
|
|
|
} else {
|
|
|
|
|
// Peer is too old to support ping command with nonce, pong will never arrive.
|
|
|
|
|
pto->nPingNonceSent = 0;
|
|
|
|
|
connman.PushMessage(pto, msgMaker.Make(NetMsgType::PING));
|
|
|
|
|
connman->PushMessage(pto, msgMaker.Make(NetMsgType::PING));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2869,14 +2848,14 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
|
|
|
|
|
// receiver rejects addr messages larger than 1000
|
|
|
|
|
if (vAddr.size() >= 1000)
|
|
|
|
|
{
|
|
|
|
|
connman.PushMessage(pto, msgMaker.Make(NetMsgType::ADDR, vAddr));
|
|
|
|
|
connman->PushMessage(pto, msgMaker.Make(NetMsgType::ADDR, vAddr));
|
|
|
|
|
vAddr.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pto->vAddrToSend.clear();
|
|
|
|
|
if (!vAddr.empty())
|
|
|
|
|
connman.PushMessage(pto, msgMaker.Make(NetMsgType::ADDR, vAddr));
|
|
|
|
|
connman->PushMessage(pto, msgMaker.Make(NetMsgType::ADDR, vAddr));
|
|
|
|
|
// we only send the big addr message once
|
|
|
|
|
if (pto->vAddrToSend.capacity() > 40)
|
|
|
|
|
pto->vAddrToSend.shrink_to_fit();
|
|
|
|
@ -2903,7 +2882,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
|
|
|
|
|
if (pindexStart->pprev)
|
|
|
|
|
pindexStart = pindexStart->pprev;
|
|
|
|
|
LogPrint(BCLog::NET, "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->nHeight, pto->GetId(), pto->nStartingHeight);
|
|
|
|
|
connman.PushMessage(pto, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexStart), uint256()));
|
|
|
|
|
connman->PushMessage(pto, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexStart), uint256()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2912,7 +2891,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
|
|
|
|
|
// transactions become unconfirmed and spams other nodes.
|
|
|
|
|
if (!fReindex && !fImporting && !IsInitialBlockDownload())
|
|
|
|
|
{
|
|
|
|
|
GetMainSignals().Broadcast(nTimeBestReceived, &connman);
|
|
|
|
|
GetMainSignals().Broadcast(nTimeBestReceived, connman);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
@ -2996,10 +2975,10 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
|
|
|
|
|
LOCK(cs_most_recent_block);
|
|
|
|
|
if (most_recent_block_hash == pBestIndex->GetBlockHash()) {
|
|
|
|
|
if (state.fWantsCmpctWitness || !fWitnessesPresentInMostRecentCompactBlock)
|
|
|
|
|
connman.PushMessage(pto, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, *most_recent_compact_block));
|
|
|
|
|
connman->PushMessage(pto, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, *most_recent_compact_block));
|
|
|
|
|
else {
|
|
|
|
|
CBlockHeaderAndShortTxIDs cmpctblock(*most_recent_block, state.fWantsCmpctWitness);
|
|
|
|
|
connman.PushMessage(pto, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock));
|
|
|
|
|
connman->PushMessage(pto, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock));
|
|
|
|
|
}
|
|
|
|
|
fGotBlockFromCache = true;
|
|
|
|
|
}
|
|
|
|
@ -3009,7 +2988,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
|
|
|
|
|
bool ret = ReadBlockFromDisk(block, pBestIndex, consensusParams);
|
|
|
|
|
assert(ret);
|
|
|
|
|
CBlockHeaderAndShortTxIDs cmpctblock(block, state.fWantsCmpctWitness);
|
|
|
|
|
connman.PushMessage(pto, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock));
|
|
|
|
|
connman->PushMessage(pto, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock));
|
|
|
|
|
}
|
|
|
|
|
state.pindexBestHeaderSent = pBestIndex;
|
|
|
|
|
} else if (state.fPreferHeaders) {
|
|
|
|
@ -3022,7 +3001,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
|
|
|
|
|
LogPrint(BCLog::NET, "%s: sending header %s to peer=%d\n", __func__,
|
|
|
|
|
vHeaders.front().GetHash().ToString(), pto->GetId());
|
|
|
|
|
}
|
|
|
|
|
connman.PushMessage(pto, msgMaker.Make(NetMsgType::HEADERS, vHeaders));
|
|
|
|
|
connman->PushMessage(pto, msgMaker.Make(NetMsgType::HEADERS, vHeaders));
|
|
|
|
|
state.pindexBestHeaderSent = pBestIndex;
|
|
|
|
|
} else
|
|
|
|
|
fRevertToInv = true;
|
|
|
|
@ -3068,7 +3047,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
|
|
|
|
|
for (const uint256& hash : pto->vInventoryBlockToSend) {
|
|
|
|
|
vInv.push_back(CInv(MSG_BLOCK, hash));
|
|
|
|
|
if (vInv.size() == MAX_INV_SZ) {
|
|
|
|
|
connman.PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
|
|
|
|
|
connman->PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
|
|
|
|
|
vInv.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -3114,7 +3093,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
|
|
|
|
|
pto->filterInventoryKnown.insert(hash);
|
|
|
|
|
vInv.push_back(inv);
|
|
|
|
|
if (vInv.size() == MAX_INV_SZ) {
|
|
|
|
|
connman.PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
|
|
|
|
|
connman->PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
|
|
|
|
|
vInv.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -3180,7 +3159,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (vInv.size() == MAX_INV_SZ) {
|
|
|
|
|
connman.PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
|
|
|
|
|
connman->PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
|
|
|
|
|
vInv.clear();
|
|
|
|
|
}
|
|
|
|
|
pto->filterInventoryKnown.insert(hash);
|
|
|
|
@ -3188,7 +3167,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!vInv.empty())
|
|
|
|
|
connman.PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
|
|
|
|
|
connman->PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
|
|
|
|
|
|
|
|
|
|
// Detect whether we're stalling
|
|
|
|
|
nNow = GetTimeMicros();
|
|
|
|
@ -3283,7 +3262,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
|
|
|
|
|
vGetData.push_back(inv);
|
|
|
|
|
if (vGetData.size() >= 1000)
|
|
|
|
|
{
|
|
|
|
|
connman.PushMessage(pto, msgMaker.Make(NetMsgType::GETDATA, vGetData));
|
|
|
|
|
connman->PushMessage(pto, msgMaker.Make(NetMsgType::GETDATA, vGetData));
|
|
|
|
|
vGetData.clear();
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
@ -3293,7 +3272,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
|
|
|
|
|
pto->mapAskFor.erase(pto->mapAskFor.begin());
|
|
|
|
|
}
|
|
|
|
|
if (!vGetData.empty())
|
|
|
|
|
connman.PushMessage(pto, msgMaker.Make(NetMsgType::GETDATA, vGetData));
|
|
|
|
|
connman->PushMessage(pto, msgMaker.Make(NetMsgType::GETDATA, vGetData));
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Message: feefilter
|
|
|
|
@ -3310,7 +3289,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
|
|
|
|
|
// We always have a fee filter of at least minRelayTxFee
|
|
|
|
|
filterToSend = std::max(filterToSend, ::minRelayTxFee.GetFeePerK());
|
|
|
|
|
if (filterToSend != pto->lastSentFeeFilter) {
|
|
|
|
|
connman.PushMessage(pto, msgMaker.Make(NetMsgType::FEEFILTER, filterToSend));
|
|
|
|
|
connman->PushMessage(pto, msgMaker.Make(NetMsgType::FEEFILTER, filterToSend));
|
|
|
|
|
pto->lastSentFeeFilter = filterToSend;
|
|
|
|
|
}
|
|
|
|
|
pto->nextSendTimeFeeFilter = PoissonNextSend(timeNow, AVG_FEEFILTER_BROADCAST_INTERVAL);
|
|
|
|
|