Changeset View
Changeset View
Standalone View
Standalone View
src/net_processing.cpp
Show All 35 Lines | |||||
#include <validationinterface.h> | #include <validationinterface.h> | ||||
#if defined(NDEBUG) | #if defined(NDEBUG) | ||||
#error "Bitcoin cannot be compiled without assertions." | #error "Bitcoin cannot be compiled without assertions." | ||||
#endif | #endif | ||||
// Used only to inform the wallet of when we last received a block. | // Used only to inform the wallet of when we last received a block. | ||||
std::atomic<int64_t> nTimeBestReceived(0); | std::atomic<int64_t> nTimeBestReceived(0); | ||||
bool g_enable_bip61 = DEFAULT_ENABLE_BIP61; | |||||
struct IteratorComparator { | struct IteratorComparator { | ||||
template <typename I> bool operator()(const I &a, const I &b) { | template <typename I> bool operator()(const I &a, const I &b) { | ||||
return &(*a) < &(*b); | return &(*a) < &(*b); | ||||
} | } | ||||
}; | }; | ||||
struct COrphanTx { | struct COrphanTx { | ||||
▲ Show 20 Lines • Show All 1,777 Lines • ▼ Show 20 Lines | if (strCommand == NetMsgType::REJECT) { | ||||
LogPrint(BCLog::NET, "Unparseable reject message received\n"); | LogPrint(BCLog::NET, "Unparseable reject message received\n"); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
else if (strCommand == NetMsgType::VERSION) { | else if (strCommand == NetMsgType::VERSION) { | ||||
// Each connection can only send one version message | // Each connection can only send one version message | ||||
if (pfrom->nVersion != 0) { | if (pfrom->nVersion != 0) { | ||||
if (g_enable_bip61) { | |||||
connman->PushMessage( | connman->PushMessage( | ||||
pfrom, | pfrom, | ||||
CNetMsgMaker(INIT_PROTO_VERSION) | CNetMsgMaker(INIT_PROTO_VERSION) | ||||
.Make(NetMsgType::REJECT, strCommand, REJECT_DUPLICATE, | .Make(NetMsgType::REJECT, strCommand, REJECT_DUPLICATE, | ||||
std::string("Duplicate version message"))); | std::string("Duplicate version message"))); | ||||
} | |||||
LOCK(cs_main); | LOCK(cs_main); | ||||
Misbehaving(pfrom, 1, "multiple-version"); | Misbehaving(pfrom, 1, "multiple-version"); | ||||
return false; | return false; | ||||
} | } | ||||
int64_t nTime; | int64_t nTime; | ||||
CAddress addrMe; | CAddress addrMe; | ||||
CAddress addrFrom; | CAddress addrFrom; | ||||
Show All 16 Lines | else if (strCommand == NetMsgType::VERSION) { | ||||
if (!pfrom->fInbound && !pfrom->fFeeler && | if (!pfrom->fInbound && !pfrom->fFeeler && | ||||
!pfrom->m_manual_connection && | !pfrom->m_manual_connection && | ||||
!HasAllDesirableServiceFlags(nServices)) { | !HasAllDesirableServiceFlags(nServices)) { | ||||
LogPrint(BCLog::NET, | LogPrint(BCLog::NET, | ||||
"peer=%d does not offer the expected services " | "peer=%d does not offer the expected services " | ||||
"(%08x offered, %08x expected); disconnecting\n", | "(%08x offered, %08x expected); disconnecting\n", | ||||
pfrom->GetId(), nServices, | pfrom->GetId(), nServices, | ||||
GetDesirableServiceFlags(nServices)); | GetDesirableServiceFlags(nServices)); | ||||
if (g_enable_bip61) { | |||||
connman->PushMessage( | connman->PushMessage( | ||||
pfrom, | pfrom, | ||||
CNetMsgMaker(INIT_PROTO_VERSION) | CNetMsgMaker(INIT_PROTO_VERSION) | ||||
.Make(NetMsgType::REJECT, strCommand, REJECT_NONSTANDARD, | .Make(NetMsgType::REJECT, strCommand, | ||||
REJECT_NONSTANDARD, | |||||
strprintf("Expected to offer services %08x", | strprintf("Expected to offer services %08x", | ||||
GetDesirableServiceFlags(nServices)))); | GetDesirableServiceFlags(nServices)))); | ||||
} | |||||
pfrom->fDisconnect = true; | pfrom->fDisconnect = true; | ||||
return false; | return false; | ||||
} | } | ||||
if (nVersion < MIN_PEER_PROTO_VERSION) { | if (nVersion < MIN_PEER_PROTO_VERSION) { | ||||
// disconnect from peers older than this proto version | // disconnect from peers older than this proto version | ||||
LogPrint(BCLog::NET, | LogPrint(BCLog::NET, | ||||
"peer=%d using obsolete version %i; disconnecting\n", | "peer=%d using obsolete version %i; disconnecting\n", | ||||
pfrom->GetId(), nVersion); | pfrom->GetId(), nVersion); | ||||
if (g_enable_bip61) { | |||||
connman->PushMessage( | connman->PushMessage( | ||||
pfrom, | pfrom, | ||||
CNetMsgMaker(INIT_PROTO_VERSION) | CNetMsgMaker(INIT_PROTO_VERSION) | ||||
.Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE, | .Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE, | ||||
strprintf("Version must be %d or greater", | strprintf("Version must be %d or greater", | ||||
MIN_PEER_PROTO_VERSION))); | MIN_PEER_PROTO_VERSION))); | ||||
} | |||||
pfrom->fDisconnect = true; | pfrom->fDisconnect = true; | ||||
return false; | return false; | ||||
} | } | ||||
if (!vRecv.empty()) { | if (!vRecv.empty()) { | ||||
vRecv >> addrFrom >> nNonce; | vRecv >> addrFrom >> nNonce; | ||||
} | } | ||||
if (!vRecv.empty()) { | if (!vRecv.empty()) { | ||||
▲ Show 20 Lines • Show All 748 Lines • ▼ Show 20 Lines | else if (strCommand == NetMsgType::TX) { | ||||
int nDoS = 0; | int nDoS = 0; | ||||
if (state.IsInvalid(nDoS)) { | if (state.IsInvalid(nDoS)) { | ||||
LogPrint(BCLog::MEMPOOLREJ, | LogPrint(BCLog::MEMPOOLREJ, | ||||
"%s from peer=%d was not accepted: %s\n", | "%s from peer=%d was not accepted: %s\n", | ||||
tx.GetHash().ToString(), pfrom->GetId(), | tx.GetHash().ToString(), pfrom->GetId(), | ||||
FormatStateMessage(state)); | FormatStateMessage(state)); | ||||
// Never send AcceptToMemoryPool's internal codes over P2P. | // Never send AcceptToMemoryPool's internal codes over P2P. | ||||
if (state.GetRejectCode() > 0 && | if (g_enable_bip61 && state.GetRejectCode() > 0 && | ||||
state.GetRejectCode() < REJECT_INTERNAL) { | state.GetRejectCode() < REJECT_INTERNAL) { | ||||
connman->PushMessage( | connman->PushMessage( | ||||
pfrom, msgMaker.Make(NetMsgType::REJECT, strCommand, | pfrom, msgMaker.Make(NetMsgType::REJECT, strCommand, | ||||
uint8_t(state.GetRejectCode()), | uint8_t(state.GetRejectCode()), | ||||
state.GetRejectReason().substr( | state.GetRejectReason().substr( | ||||
0, MAX_REJECT_MESSAGE_LENGTH), | 0, MAX_REJECT_MESSAGE_LENGTH), | ||||
inv.hash)); | inv.hash)); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 640 Lines • ▼ Show 20 Lines | |||||
return true; | return true; | ||||
} | } | ||||
static bool SendRejectsAndCheckIfBanned(CNode *pnode, CConnman *connman) { | static bool SendRejectsAndCheckIfBanned(CNode *pnode, CConnman *connman) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
CNodeState &state = *State(pnode->GetId()); | CNodeState &state = *State(pnode->GetId()); | ||||
if (g_enable_bip61) { | |||||
for (const CBlockReject &reject : state.rejects) { | for (const CBlockReject &reject : state.rejects) { | ||||
connman->PushMessage( | connman->PushMessage( | ||||
pnode, CNetMsgMaker(INIT_PROTO_VERSION) | pnode, | ||||
CNetMsgMaker(INIT_PROTO_VERSION) | |||||
.Make(NetMsgType::REJECT, std::string(NetMsgType::BLOCK), | .Make(NetMsgType::REJECT, std::string(NetMsgType::BLOCK), | ||||
reject.chRejectCode, reject.strRejectReason, | reject.chRejectCode, reject.strRejectReason, | ||||
reject.hashBlock)); | reject.hashBlock)); | ||||
} | } | ||||
} | |||||
state.rejects.clear(); | state.rejects.clear(); | ||||
if (state.fShouldBan) { | if (state.fShouldBan) { | ||||
state.fShouldBan = false; | state.fShouldBan = false; | ||||
if (pnode->fWhitelisted) { | if (pnode->fWhitelisted) { | ||||
LogPrintf("Warning: not punishing whitelisted peer %s!\n", | LogPrintf("Warning: not punishing whitelisted peer %s!\n", | ||||
pnode->addr.ToString()); | pnode->addr.ToString()); | ||||
} else if (pnode->m_manual_connection) { | } else if (pnode->m_manual_connection) { | ||||
▲ Show 20 Lines • Show All 115 Lines • ▼ Show 20 Lines | try { | ||||
connman, interruptMsgProc); | connman, interruptMsgProc); | ||||
if (interruptMsgProc) { | if (interruptMsgProc) { | ||||
return false; | return false; | ||||
} | } | ||||
if (!pfrom->vRecvGetData.empty()) { | if (!pfrom->vRecvGetData.empty()) { | ||||
fMoreWork = true; | fMoreWork = true; | ||||
} | } | ||||
} catch (const std::ios_base::failure &e) { | } catch (const std::ios_base::failure &e) { | ||||
if (g_enable_bip61) { | |||||
connman->PushMessage( | connman->PushMessage( | ||||
pfrom, CNetMsgMaker(INIT_PROTO_VERSION) | pfrom, | ||||
CNetMsgMaker(INIT_PROTO_VERSION) | |||||
.Make(NetMsgType::REJECT, strCommand, REJECT_MALFORMED, | .Make(NetMsgType::REJECT, strCommand, REJECT_MALFORMED, | ||||
std::string("error parsing message"))); | std::string("error parsing message"))); | ||||
} | |||||
if (strstr(e.what(), "end of data")) { | if (strstr(e.what(), "end of data")) { | ||||
// Allow exceptions from under-length message on vRecv | // Allow exceptions from under-length message on vRecv | ||||
LogPrint( | LogPrint(BCLog::NET, | ||||
BCLog::NET, | "%s(%s, %u bytes): Exception '%s' caught, normally caused " | ||||
"%s(%s, %u bytes): Exception '%s' caught, normally caused by a " | "by a message being shorter than its stated length\n", | ||||
"message being shorter than its stated length\n", | __func__, SanitizeString(strCommand), nMessageSize, | ||||
__func__, SanitizeString(strCommand), nMessageSize, e.what()); | e.what()); | ||||
} else if (strstr(e.what(), "size too large")) { | } else if (strstr(e.what(), "size too large")) { | ||||
// Allow exceptions from over-long size | // Allow exceptions from over-long size | ||||
LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' caught\n", | LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' caught\n", | ||||
__func__, SanitizeString(strCommand), nMessageSize, | __func__, SanitizeString(strCommand), nMessageSize, | ||||
e.what()); | e.what()); | ||||
} else if (strstr(e.what(), "non-canonical ReadCompactSize()")) { | } else if (strstr(e.what(), "non-canonical ReadCompactSize()")) { | ||||
// Allow exceptions from non-canonical encoding | // Allow exceptions from non-canonical encoding | ||||
LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' caught\n", | LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' caught\n", | ||||
▲ Show 20 Lines • Show All 885 Lines • Show Last 20 Lines |