Changeset View
Changeset View
Standalone View
Standalone View
src/avalanche/processor.cpp
// Copyright (c) 2018-2019 The Bitcoin developers | // Copyright (c) 2018-2019 The Bitcoin 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 <avalanche/processor.h> | #include <avalanche/processor.h> | ||||
#include <avalanche/delegationbuilder.h> | #include <avalanche/delegationbuilder.h> | ||||
#include <avalanche/peermanager.h> | #include <avalanche/peermanager.h> | ||||
#include <avalanche/validation.h> | #include <avalanche/validation.h> | ||||
#include <chain.h> | #include <chain.h> | ||||
#include <key_io.h> // For DecodeSecret | #include <key_io.h> // For DecodeSecret | ||||
#include <net_processing.h> // For ::PeerManager | #include <net_processing.h> // For ::PeerManager | ||||
#include <netmessagemaker.h> | #include <netmessagemaker.h> | ||||
#include <reverse_iterator.h> | #include <reverse_iterator.h> | ||||
#include <scheduler.h> | #include <scheduler.h> | ||||
#include <util/bitmanip.h> | #include <util/bitmanip.h> | ||||
#include <util/translation.h> | |||||
#include <validation.h> | #include <validation.h> | ||||
#include <chrono> | #include <chrono> | ||||
#include <tuple> | #include <tuple> | ||||
/** | /** | ||||
* Run the avalanche event loop every 10ms. | * Run the avalanche event loop every 10ms. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 132 Lines • ▼ Show 20 Lines | void updatedBlockTip() override { | ||||
m_processor->mustRegisterProof = false; | m_processor->mustRegisterProof = false; | ||||
} | } | ||||
m_processor->peerManager->updatedBlockTip(); | m_processor->peerManager->updatedBlockTip(); | ||||
} | } | ||||
}; | }; | ||||
Processor::Processor(interfaces::Chain &chain, CConnman *connmanIn, | Processor::Processor(interfaces::Chain &chain, CConnman *connmanIn, | ||||
NodePeerManager *nodePeerManagerIn) | NodePeerManager *nodePeerManagerIn, | ||||
std::unique_ptr<PeerData> peerDataIn, CKey sessionKeyIn) | |||||
: connman(connmanIn), nodePeerManager(nodePeerManagerIn), | : connman(connmanIn), nodePeerManager(nodePeerManagerIn), | ||||
queryTimeoutDuration(AVALANCHE_DEFAULT_QUERY_TIMEOUT), round(0), | queryTimeoutDuration(AVALANCHE_DEFAULT_QUERY_TIMEOUT), round(0), | ||||
peerManager(std::make_unique<PeerManager>()) { | peerManager(std::make_unique<PeerManager>()), | ||||
if (gArgs.IsArgSet("-avasessionkey")) { | peerData(std::move(peerDataIn)), sessionKey(std::move(sessionKeyIn)), | ||||
sessionKey = DecodeSecret(gArgs.GetArg("-avasessionkey", "")); | // Schedule proof registration at the first new block after IBD. | ||||
// FIXME: get rid of this flag | |||||
mustRegisterProof(!!peerData) { | |||||
// Make sure we get notified of chain state changes. | |||||
chainNotificationsHandler = | |||||
chain.handleNotifications(std::make_shared<NotificationsHandler>(this)); | |||||
} | |||||
Processor::~Processor() { | |||||
chainNotificationsHandler.reset(); | |||||
stopEventLoop(); | |||||
} | |||||
std::unique_ptr<Processor> | |||||
Processor::MakeProcessor(const ArgsManager &argsman, interfaces::Chain &chain, | |||||
CConnman *connman, NodePeerManager *nodePeerManager, | |||||
bilingual_str &error) { | |||||
std::unique_ptr<PeerData> peerData; | |||||
CKey masterKey; | |||||
CKey sessionKey; | |||||
if (argsman.IsArgSet("-avasessionkey")) { | |||||
sessionKey = DecodeSecret(argsman.GetArg("-avasessionkey", "")); | |||||
if (!sessionKey.IsValid()) { | |||||
error = _("the avalanche session key is invalid"); | |||||
return nullptr; | |||||
} | |||||
} else { | } else { | ||||
// Pick a random key for the session. | // Pick a random key for the session. | ||||
sessionKey.MakeNewKey(true); | sessionKey.MakeNewKey(true); | ||||
} | } | ||||
if (gArgs.IsArgSet("-avaproof")) { | if (argsman.IsArgSet("-avaproof")) { | ||||
peerData = std::make_unique<PeerData>(); | if (!argsman.IsArgSet("-avamasterkey")) { | ||||
error = _( | |||||
"the avalanche master key is missing for the avalanche proof"); | |||||
return nullptr; | |||||
} | |||||
masterKey = DecodeSecret(argsman.GetArg("-avamasterkey", "")); | |||||
if (!masterKey.IsValid()) { | |||||
error = _("the avalanche master key is invalid"); | |||||
return nullptr; | |||||
} | |||||
peerData = std::make_unique<PeerData>(); | |||||
{ | { | ||||
// The proof. | // The proof. | ||||
CDataStream stream(ParseHex(gArgs.GetArg("-avaproof", "")), | CDataStream stream(ParseHex(argsman.GetArg("-avaproof", "")), | ||||
SER_NETWORK, 0); | SER_NETWORK, 0); | ||||
stream >> peerData->proof; | stream >> peerData->proof; | ||||
} | |||||
// Schedule proof registration at the first new block after IBD. | ProofValidationState proof_state; | ||||
mustRegisterProof = true; | if (!peerData->proof.verify(proof_state)) { | ||||
switch (proof_state.GetResult()) { | |||||
case ProofValidationResult::NO_STAKE: | |||||
error = _("the avalanche proof has no stake"); | |||||
return nullptr; | |||||
case ProofValidationResult::DUST_THRESOLD: | |||||
error = _("the avalanche proof stake is too low"); | |||||
return nullptr; | |||||
case ProofValidationResult::DUPLICATE_STAKE: | |||||
error = _("the avalanche proof has duplicated stake"); | |||||
return nullptr; | |||||
case ProofValidationResult::INVALID_SIGNATURE: | |||||
error = | |||||
_("the avalanche proof has invalid stake signatures"); | |||||
return nullptr; | |||||
case ProofValidationResult::TOO_MANY_UTXOS: | |||||
error = strprintf( | |||||
_("the avalanche proof has too many utxos (max: %u)"), | |||||
AVALANCHE_MAX_PROOF_STAKES); | |||||
return nullptr; | |||||
default: | |||||
error = _("the avalanche proof is invalid"); | |||||
return nullptr; | |||||
} | |||||
} | } | ||||
// Generate the delegation to the session key. | // Generate the delegation to the session key. | ||||
DelegationBuilder dgb(peerData->proof); | DelegationBuilder dgb(peerData->proof); | ||||
if (sessionKey.GetPubKey() != peerData->proof.getMaster()) { | if (sessionKey.GetPubKey() != peerData->proof.getMaster()) { | ||||
dgb.addLevel(DecodeSecret(gArgs.GetArg("-avamasterkey", "")), | dgb.addLevel(masterKey, sessionKey.GetPubKey()); | ||||
sessionKey.GetPubKey()); | |||||
} | } | ||||
peerData->delegation = dgb.build(); | peerData->delegation = dgb.build(); | ||||
} | } | ||||
// Make sure we get notified of chain state changes. | // We can't use std::make_unique with a private constructor | ||||
chainNotificationsHandler = | return std::unique_ptr<Processor>( | ||||
chain.handleNotifications(std::make_shared<NotificationsHandler>(this)); | new Processor(chain, connman, nodePeerManager, std::move(peerData), | ||||
} | std::move(sessionKey))); | ||||
Processor::~Processor() { | |||||
chainNotificationsHandler.reset(); | |||||
stopEventLoop(); | |||||
} | } | ||||
bool Processor::addBlockToReconcile(const CBlockIndex *pindex) { | bool Processor::addBlockToReconcile(const CBlockIndex *pindex) { | ||||
bool isAccepted; | bool isAccepted; | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
if (!IsWorthPolling(pindex)) { | if (!IsWorthPolling(pindex)) { | ||||
▲ Show 20 Lines • Show All 416 Lines • Show Last 20 Lines |