Changeset View
Changeset View
Standalone View
Standalone View
src/net_processing.cpp
// Copyright (c) 2009-2010 Satoshi Nakamoto | // Copyright (c) 2009-2010 Satoshi Nakamoto | ||||
// Copyright (c) 2009-2016 The Bitcoin Core developers | // Copyright (c) 2009-2016 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include <net_processing.h> | #include <net_processing.h> | ||||
#include <addrman.h> | #include <addrman.h> | ||||
#include <avalanche/processor.h> | #include <avalanche/processor.h> | ||||
#include <avalanche/proof.h> | #include <avalanche/proof.h> | ||||
#include <avalanche/proofid.h> | |||||
#include <avalanche/validation.h> | #include <avalanche/validation.h> | ||||
#include <banman.h> | #include <banman.h> | ||||
#include <blockdb.h> | #include <blockdb.h> | ||||
#include <blockencodings.h> | #include <blockencodings.h> | ||||
#include <blockfilter.h> | #include <blockfilter.h> | ||||
#include <blockvalidity.h> | #include <blockvalidity.h> | ||||
#include <chain.h> | #include <chain.h> | ||||
#include <chainparams.h> | #include <chainparams.h> | ||||
▲ Show 20 Lines • Show All 2,039 Lines • ▼ Show 20 Lines | while (it != pfrom.vRecvGetData.end() && it->type == MSG_TX) { | ||||
connman.PushMessage(&pfrom, | connman.PushMessage(&pfrom, | ||||
msgMaker.Make(nSendFlags, NetMsgType::TX, *tx)); | msgMaker.Make(nSendFlags, NetMsgType::TX, *tx)); | ||||
mempool.RemoveUnbroadcastTx(TxId(inv.hash)); | mempool.RemoveUnbroadcastTx(TxId(inv.hash)); | ||||
} else { | } else { | ||||
vNotFound.push_back(inv); | vNotFound.push_back(inv); | ||||
} | } | ||||
} | } | ||||
// Process an avalanche proof item. For now, we assume that peers always | |||||
// request a single avalanche proof, and it must be the one this node | |||||
// advertised in the avahello message. | |||||
if (it != pfrom.vRecvGetData.end() && it->type == MSG_AVALANCHE_PROOF) { | |||||
const CInv &inv = *it++; | |||||
if (!g_avalanche || | |||||
!gArgs.GetBoolArg("-enableavalanche", AVALANCHE_DEFAULT_ENABLED) || | |||||
!gArgs.IsArgSet("-avaproof")) { | |||||
vNotFound.push_back(inv); | |||||
} else { | |||||
const avalanche::ProofId proofid{inv.hash}; | |||||
const avalanche::Proof proof = g_avalanche->getProof(); | |||||
if (proofid == proof.getId()) { | |||||
connman.PushMessage(&pfrom, | |||||
msgMaker.Make(NetMsgType::AVAPROOF, proof)); | |||||
} else { | |||||
// The requested proof is not ours. | |||||
vNotFound.push_back(inv); | |||||
} | |||||
} | |||||
} | |||||
// Only process one BLOCK item per call, since they're uncommon and can be | // Only process one BLOCK item per call, since they're uncommon and can be | ||||
// expensive to process. | // expensive to process. | ||||
if (it != pfrom.vRecvGetData.end() && !pfrom.fPauseSend) { | if (it != pfrom.vRecvGetData.end() && !pfrom.fPauseSend) { | ||||
const CInv &inv = *it++; | const CInv &inv = *it++; | ||||
if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || | if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || | ||||
inv.type == MSG_CMPCT_BLOCK) { | inv.type == MSG_CMPCT_BLOCK) { | ||||
ProcessGetBlockData(config, pfrom, inv, connman, interruptMsgProc); | ProcessGetBlockData(config, pfrom, inv, connman, interruptMsgProc); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,875 Lines • ▼ Show 20 Lines | if (msg_type == NetMsgType::AVAHELLO && g_avalanche) { | ||||
if (!gArgs.GetBoolArg("-enableavalanche", AVALANCHE_DEFAULT_ENABLED)) { | if (!gArgs.GetBoolArg("-enableavalanche", AVALANCHE_DEFAULT_ENABLED)) { | ||||
Misbehaving(pfrom, 20, "unsolicited-avahello"); | Misbehaving(pfrom, 20, "unsolicited-avahello"); | ||||
return; | return; | ||||
} | } | ||||
if (!pfrom.m_avalanche_state) { | if (!pfrom.m_avalanche_state) { | ||||
pfrom.m_avalanche_state = std::make_unique<CNode::AvalancheState>(); | pfrom.m_avalanche_state = std::make_unique<CNode::AvalancheState>(); | ||||
} | } | ||||
// Store the delegation and signature for later verification. | |||||
CHashVerifier<CDataStream> verifier(&vRecv); | CHashVerifier<CDataStream> verifier(&vRecv); | ||||
avalanche::Delegation &delegation = pfrom.m_avalanche_state->delegation; | verifier >> pfrom.m_avalanche_state->delegation; | ||||
verifier >> delegation; | |||||
SchnorrSig &sig = pfrom.m_avalanche_state->sig; | |||||
verifier >> sig; | |||||
// Ask for the proof. | |||||
std::vector<CInv> vGetData; | |||||
vGetData.emplace_back( | |||||
CInv(MSG_AVALANCHE_PROOF, | |||||
pfrom.m_avalanche_state->delegation.getProofId())); | |||||
m_connman.PushMessage(&pfrom, | |||||
msgMaker.Make(NetMsgType::GETDATA, vGetData)); | |||||
} | |||||
if (msg_type == NetMsgType::AVAPROOF && g_avalanche) { | |||||
if (!pfrom.m_avalanche_state) { | |||||
Misbehaving(pfrom, 20, "avaproof-before-avahello"); | |||||
return; | |||||
} | |||||
// Read the proof. | |||||
avalanche::Proof proof; | avalanche::Proof proof; | ||||
// TODO: read proof from message | vRecv >> proof; | ||||
if (proof.getStakes().size() > AVALANCHE_MAX_PROOF_STAKES) { | if (proof.getStakes().size() > AVALANCHE_MAX_PROOF_STAKES) { | ||||
Misbehaving(pfrom, 100, "too-large-avalanche-proof"); | Misbehaving(pfrom, 100, "too-large-avalanche-proof"); | ||||
return; | return; | ||||
} | } | ||||
// Verify the delegation is internally consistent. | |||||
const avalanche::Delegation &delegation = | |||||
pfrom.m_avalanche_state->delegation; | |||||
avalanche::DelegationState state; | avalanche::DelegationState state; | ||||
CPubKey pubkey; | CPubKey pubkey; | ||||
if (!delegation.verify(state, proof, pubkey)) { | if (!delegation.verify(state, proof, pubkey)) { | ||||
Misbehaving(pfrom, 100, "invalid-delegation"); | Misbehaving(pfrom, 100, "invalid-delegation"); | ||||
return; | return; | ||||
} | } | ||||
SchnorrSig sig; | // Use the delegated pubkey to verify the signature received | ||||
verifier >> sig; | // in the avahello message. | ||||
const uint256 hash = g_avalanche->buildRemoteSighash(&pfrom); | |||||
if (!pubkey.VerifySchnorr(hash, pfrom.m_avalanche_state->sig)) { | |||||
Misbehaving(pfrom, 100, "invalid-avalanche-handshake"); | |||||
return; | |||||
} | |||||
if (::ChainstateActive().IsInitialBlockDownload()) { | |||||
// We add the nodes to a queue that is processed when receiving the | |||||
// first block after IBD. | |||||
if (g_avalanche->queueNode(pfrom.GetId(), proof, delegation)) { | |||||
LogPrint(BCLog::NET, | |||||
"queued avalanche node for proof verification=%d\n", | |||||
pfrom.GetId()); | |||||
} else { | |||||
// We already have a proof queued from this node | |||||
g_avalanche->removeNodeFromQueue(pfrom.GetId()); | |||||
Misbehaving(pfrom, 100, "duplicate-avalanche-proof"); | |||||
} | |||||
} else { | |||||
// Add the node to the avalanche peers. | |||||
if (g_avalanche->addNode(pfrom.GetId(), proof, delegation)) { | |||||
LogPrint(BCLog::NET, "added avalanche node=%d\n", | |||||
pfrom.GetId()); | |||||
} else { | |||||
Misbehaving(pfrom, 100, "failed-avalanche-addnode"); | |||||
} | |||||
} | |||||
} | } | ||||
// Ignore avalanche requests while importing | // Ignore avalanche requests while importing | ||||
if (msg_type == NetMsgType::AVAPOLL && !fImporting && !fReindex && | if (msg_type == NetMsgType::AVAPOLL && !fImporting && !fReindex && | ||||
g_avalanche) { | g_avalanche) { | ||||
if (!gArgs.GetBoolArg("-enableavalanche", AVALANCHE_DEFAULT_ENABLED)) { | if (!gArgs.GetBoolArg("-enableavalanche", AVALANCHE_DEFAULT_ENABLED)) { | ||||
Misbehaving(pfrom, 20, "unsolicited-avapoll"); | Misbehaving(pfrom, 20, "unsolicited-avapoll"); | ||||
return; | return; | ||||
▲ Show 20 Lines • Show All 1,598 Lines • Show Last 20 Lines |