Changeset View
Changeset View
Standalone View
Standalone View
src/net_processing.cpp
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
Show First 20 Lines • Show All 931 Lines • ▼ Show 20 Lines | private: | ||||
/** | /** | ||||
* Checks if address relay is permitted with peer. If needed, initializes | * Checks if address relay is permitted with peer. If needed, initializes | ||||
* the m_addr_known bloom filter and sets m_addr_relay_enabled to true. | * the m_addr_known bloom filter and sets m_addr_relay_enabled to true. | ||||
* | * | ||||
* @return True if address relay is enabled with peer | * @return True if address relay is enabled with peer | ||||
* False if address relay is disallowed | * False if address relay is disallowed | ||||
*/ | */ | ||||
bool SetupAddressRelay(CNode &node, Peer &peer); | bool SetupAddressRelay(CNode &node, Peer &peer); | ||||
/** | |||||
* Manage reception of an avalanche proof. | |||||
* | |||||
* @return False if the peer is misbehaving, true otherwise | |||||
*/ | |||||
bool ReceivedAvalancheProof(CNode &peer, const avalanche::ProofRef &proof); | |||||
}; | }; | ||||
} // namespace | } // namespace | ||||
namespace { | namespace { | ||||
/** | /** | ||||
* Filter for proofs that were recently rejected but not orphaned. | * Filter for proofs that were recently rejected but not orphaned. | ||||
* These are not rerequested until they are rolled out of the filter. | * These are not rerequested until they are rolled out of the filter. | ||||
* | * | ||||
▲ Show 20 Lines • Show All 4,166 Lines • ▼ Show 20 Lines | if (msg_type == NetMsgType::AVARESPONSE) { | ||||
} | } | ||||
return; | return; | ||||
} | } | ||||
if (msg_type == NetMsgType::AVAPROOF) { | if (msg_type == NetMsgType::AVAPROOF) { | ||||
auto proof = RCUPtr<avalanche::Proof>::make(); | auto proof = RCUPtr<avalanche::Proof>::make(); | ||||
vRecv >> *proof; | vRecv >> *proof; | ||||
const avalanche::ProofId &proofid = proof->getId(); | |||||
pfrom.AddKnownProof(proofid); | |||||
const NodeId nodeid = pfrom.GetId(); | |||||
{ | |||||
LOCK(cs_proofrequest); | |||||
m_proofrequest.ReceivedResponse(nodeid, proofid); | |||||
if (AlreadyHaveProof(proofid)) { | |||||
m_proofrequest.ForgetInvId(proofid); | |||||
return; | |||||
} | |||||
} | |||||
// registerProof should not be called while cs_proofrequest because it | |||||
// holds cs_main and that creates a potential deadlock during shutdown | |||||
avalanche::ProofRegistrationState state; | |||||
if (g_avalanche->withPeerManager([&](avalanche::PeerManager &pm) { | |||||
return pm.registerProof(proof, state); | |||||
})) { | |||||
WITH_LOCK(cs_proofrequest, m_proofrequest.ForgetInvId(proofid)); | |||||
RelayProof(proofid, m_connman); | |||||
pfrom.m_last_proof_time = GetTime<std::chrono::seconds>(); | ReceivedAvalancheProof(pfrom, proof); | ||||
LogPrint(BCLog::NET, "New avalanche proof: peer=%d, proofid %s\n", | |||||
nodeid, proofid.ToString()); | |||||
} | |||||
if (state.GetResult() == avalanche::ProofRegistrationResult::INVALID) { | |||||
WITH_LOCK(cs_rejectedProofs, rejectedProofs->insert(proofid)); | |||||
Misbehaving(nodeid, 100, state.GetRejectReason()); | |||||
return; | |||||
} | |||||
if (!gArgs.GetBoolArg("-enableavalancheproofreplacement", | |||||
AVALANCHE_DEFAULT_PROOF_REPLACEMENT_ENABLED)) { | |||||
// If proof replacement is not enabled there is no point dealing | |||||
// with proof polling, so we're done. | |||||
return; | |||||
} | |||||
if (state.IsValid() || | |||||
state.GetResult() == | |||||
avalanche::ProofRegistrationResult::CONFLICTING) { | |||||
g_avalanche->addProofToReconcile(proof); | |||||
return; | |||||
} | |||||
LogPrint(BCLog::AVALANCHE, | |||||
"Not polling the avalanche proof (%s): peer=%d, proofid %s\n", | |||||
state.GetRejectReason(), nodeid, proofid.ToString()); | |||||
return; | return; | ||||
} | } | ||||
if (msg_type == NetMsgType::GETADDR) { | if (msg_type == NetMsgType::GETADDR) { | ||||
// This asymmetric behavior for inbound and outbound connections was | // This asymmetric behavior for inbound and outbound connections was | ||||
// introduced to prevent a fingerprinting attack: an attacker can send | // introduced to prevent a fingerprinting attack: an attacker can send | ||||
// specific fake addresses to users' AddrMan and later request them by | // specific fake addresses to users' AddrMan and later request them by | ||||
// sending getaddr messages. Making nodes which are behind NAT and can | // sending getaddr messages. Making nodes which are behind NAT and can | ||||
▲ Show 20 Lines • Show All 1,672 Lines • ▼ Show 20 Lines | // | ||||
pto->m_tx_relay->m_next_send_feefilter = | pto->m_tx_relay->m_next_send_feefilter = | ||||
current_time + GetRandomDuration<std::chrono::microseconds>( | current_time + GetRandomDuration<std::chrono::microseconds>( | ||||
MAX_FEEFILTER_CHANGE_DELAY); | MAX_FEEFILTER_CHANGE_DELAY); | ||||
} | } | ||||
} | } | ||||
} // release cs_main | } // release cs_main | ||||
return true; | return true; | ||||
} | } | ||||
bool PeerManagerImpl::ReceivedAvalancheProof(CNode &peer, | |||||
const avalanche::ProofRef &proof) { | |||||
assert(proof != nullptr); | |||||
const avalanche::ProofId &proofid = proof->getId(); | |||||
peer.AddKnownProof(proofid); | |||||
const NodeId nodeid = peer.GetId(); | |||||
{ | |||||
LOCK(cs_proofrequest); | |||||
m_proofrequest.ReceivedResponse(nodeid, proofid); | |||||
if (AlreadyHaveProof(proofid)) { | |||||
m_proofrequest.ForgetInvId(proofid); | |||||
return true; | |||||
} | |||||
} | |||||
// registerProof should not be called while cs_proofrequest because it | |||||
// holds cs_main and that creates a potential deadlock during shutdown | |||||
avalanche::ProofRegistrationState state; | |||||
if (g_avalanche->withPeerManager([&](avalanche::PeerManager &pm) { | |||||
return pm.registerProof(proof, state); | |||||
})) { | |||||
WITH_LOCK(cs_proofrequest, m_proofrequest.ForgetInvId(proofid)); | |||||
RelayProof(proofid, m_connman); | |||||
peer.m_last_proof_time = GetTime<std::chrono::seconds>(); | |||||
LogPrint(BCLog::NET, "New avalanche proof: peer=%d, proofid %s\n", | |||||
nodeid, proofid.ToString()); | |||||
} | |||||
if (state.GetResult() == avalanche::ProofRegistrationResult::INVALID) { | |||||
WITH_LOCK(cs_rejectedProofs, rejectedProofs->insert(proofid)); | |||||
Misbehaving(nodeid, 100, state.GetRejectReason()); | |||||
return false; | |||||
} | |||||
if (!gArgs.GetBoolArg("-enableavalancheproofreplacement", | |||||
AVALANCHE_DEFAULT_PROOF_REPLACEMENT_ENABLED)) { | |||||
// If proof replacement is not enabled there is no point dealing | |||||
// with proof polling, so we're done. | |||||
return true; | |||||
} | |||||
if (state.IsValid() || | |||||
state.GetResult() == avalanche::ProofRegistrationResult::CONFLICTING) { | |||||
g_avalanche->addProofToReconcile(proof); | |||||
return true; | |||||
} | |||||
LogPrint(BCLog::AVALANCHE, | |||||
"Not polling the avalanche proof (%s): peer=%d, proofid %s\n", | |||||
state.GetRejectReason(), nodeid, proofid.ToString()); | |||||
return true; | |||||
} |