diff --git a/src/avalanche/processor.h b/src/avalanche/processor.h --- a/src/avalanche/processor.h +++ b/src/avalanche/processor.h @@ -253,8 +253,8 @@ int getConfidence(const CBlockIndex *pindex) const; // TDOD: Refactor the API to remove the dependency on avalanche/protocol.h - void sendResponse(CNode *pfrom, AvalancheResponse response) const; - bool registerVotes(NodeId nodeid, const AvalancheResponse &response, + void sendResponse(CNode *pfrom, Response response) const; + bool registerVotes(NodeId nodeid, const Response &response, std::vector &updates); bool addPeer(NodeId nodeid, int64_t score, CPubKey pubkey); diff --git a/src/avalanche/processor.cpp b/src/avalanche/processor.cpp --- a/src/avalanche/processor.cpp +++ b/src/avalanche/processor.cpp @@ -186,12 +186,12 @@ * When using TCP, we need to sign all messages as the transport layer is * not secure. */ - class TCPAvalancheResponse { - AvalancheResponse response; + class TCPResponse { + Response response; std::array sig; public: - TCPAvalancheResponse(AvalancheResponse responseIn, const CKey &key) + TCPResponse(Response responseIn, const CKey &key) : response(std::move(responseIn)) { CHashWriter hasher(SER_GETHASH, 0); hasher << response; @@ -219,15 +219,14 @@ }; } // namespace -void Processor::sendResponse(CNode *pfrom, AvalancheResponse response) const { +void Processor::sendResponse(CNode *pfrom, Response response) const { connman->PushMessage( - pfrom, - CNetMsgMaker(pfrom->GetSendVersion()) - .Make(NetMsgType::AVARESPONSE, - TCPAvalancheResponse(std::move(response), sessionKey))); + pfrom, CNetMsgMaker(pfrom->GetSendVersion()) + .Make(NetMsgType::AVARESPONSE, + TCPResponse(std::move(response), sessionKey))); } -bool Processor::registerVotes(NodeId nodeid, const AvalancheResponse &response, +bool Processor::registerVotes(NodeId nodeid, const Response &response, std::vector &updates) { { // Save the time at which we can query again. @@ -257,7 +256,7 @@ } // Verify that the request and the vote are consistent. - const std::vector &votes = response.GetVotes(); + const std::vector &votes = response.GetVotes(); size_t size = invs.size(); if (votes.size() != size) { // TODO: increase banscore for inconsistent response. @@ -273,7 +272,7 @@ } } - std::map responseIndex; + std::map responseIndex; { LOCK(cs_main); @@ -299,7 +298,7 @@ auto w = vote_records.getWriteView(); for (const auto &p : responseIndex) { CBlockIndex *pindex = p.first; - const AvalancheVote &v = p.second; + const Vote &v = p.second; auto it = w->find(pindex); if (it == w.end()) { @@ -492,10 +491,9 @@ // Send the query to the node. connman->PushMessage( - pnode, - CNetMsgMaker(pnode->GetSendVersion()) - .Make(NetMsgType::AVAPOLL, - AvalanchePoll(current_round, std::move(invs)))); + pnode, CNetMsgMaker(pnode->GetSendVersion()) + .Make(NetMsgType::AVAPOLL, + Poll(current_round, std::move(invs)))); return true; }); diff --git a/src/avalanche/protocol.h b/src/avalanche/protocol.h --- a/src/avalanche/protocol.h +++ b/src/avalanche/protocol.h @@ -12,14 +12,15 @@ #include #include -class AvalancheVote { +namespace avalanche { + +class Vote { uint32_t error; uint256 hash; public: - AvalancheVote() : error(-1), hash() {} - AvalancheVote(uint32_t errorIn, uint256 hashIn) - : error(errorIn), hash(hashIn) {} + Vote() : error(-1), hash() {} + Vote(uint32_t errorIn, uint256 hashIn) : error(errorIn), hash(hashIn) {} const uint256 &GetHash() const { return hash; } uint32_t GetError() const { return error; } @@ -34,20 +35,19 @@ } }; -class AvalancheResponse { +class Response { uint64_t round; uint32_t cooldown; - std::vector votes; + std::vector votes; public: - AvalancheResponse() : round(-1), cooldown(-1) {} - AvalancheResponse(uint64_t roundIn, uint32_t cooldownIn, - std::vector votesIn) + Response() : round(-1), cooldown(-1) {} + Response(uint64_t roundIn, uint32_t cooldownIn, std::vector votesIn) : round(roundIn), cooldown(cooldownIn), votes(votesIn) {} uint64_t getRound() const { return round; } uint32_t getCooldown() const { return cooldown; } - const std::vector &GetVotes() const { return votes; } + const std::vector &GetVotes() const { return votes; } // serialization support ADD_SERIALIZE_METHODS; @@ -60,12 +60,12 @@ } }; -class AvalanchePoll { +class Poll { uint64_t round; std::vector invs; public: - AvalanchePoll(uint64_t roundIn, std::vector invsIn) + Poll(uint64_t roundIn, std::vector invsIn) : round(roundIn), invs(invsIn) {} const std::vector &GetInvs() const { return invs; } @@ -80,4 +80,6 @@ } }; +} // namespace avalanche + #endif // BITCOIN_AVALANCHE_PROTOCOL_H diff --git a/src/avalanche/test/processor_tests.cpp b/src/avalanche/test/processor_tests.cpp --- a/src/avalanche/test/processor_tests.cpp +++ b/src/avalanche/test/processor_tests.cpp @@ -219,7 +219,7 @@ return nodes; } -static AvalancheResponse next(AvalancheResponse &r) { +static Response next(Response &r) { auto copy = r; r = {r.getRound() + 1, r.getCooldown(), r.GetVotes()}; return copy; @@ -261,14 +261,14 @@ BOOST_CHECK(p.isAccepted(pindex)); int nextNodeIndex = 0; - auto registerNewVote = [&](const AvalancheResponse &resp) { + auto registerNewVote = [&](const Response &resp) { AvalancheTest::runEventLoop(p); auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId(); BOOST_CHECK(p.registerVotes(nodeid, resp, updates)); }; // Let's vote for this block a few times. - AvalancheResponse resp{0, 0, {AvalancheVote(0, blockHash)}}; + Response resp{0, 0, {Vote(0, blockHash)}}; for (int i = 0; i < 6; i++) { registerNewVote(next(resp)); BOOST_CHECK(p.isAccepted(pindex)); @@ -277,13 +277,13 @@ } // A single neutral vote do not change anything. - resp = {AvalancheTest::getRound(p), 0, {AvalancheVote(-1, blockHash)}}; + resp = {AvalancheTest::getRound(p), 0, {Vote(-1, blockHash)}}; registerNewVote(next(resp)); BOOST_CHECK(p.isAccepted(pindex)); BOOST_CHECK_EQUAL(p.getConfidence(pindex), 0); BOOST_CHECK_EQUAL(updates.size(), 0); - resp = {AvalancheTest::getRound(p), 0, {AvalancheVote(0, blockHash)}}; + resp = {AvalancheTest::getRound(p), 0, {Vote(0, blockHash)}}; for (int i = 1; i < 7; i++) { registerNewVote(next(resp)); BOOST_CHECK(p.isAccepted(pindex)); @@ -292,7 +292,7 @@ } // Two neutral votes will stall progress. - resp = {AvalancheTest::getRound(p), 0, {AvalancheVote(-1, blockHash)}}; + resp = {AvalancheTest::getRound(p), 0, {Vote(-1, blockHash)}}; registerNewVote(next(resp)); BOOST_CHECK(p.isAccepted(pindex)); BOOST_CHECK_EQUAL(p.getConfidence(pindex), 6); @@ -302,7 +302,7 @@ BOOST_CHECK_EQUAL(p.getConfidence(pindex), 6); BOOST_CHECK_EQUAL(updates.size(), 0); - resp = {AvalancheTest::getRound(p), 0, {AvalancheVote(0, blockHash)}}; + resp = {AvalancheTest::getRound(p), 0, {Vote(0, blockHash)}}; for (int i = 2; i < 8; i++) { registerNewVote(next(resp)); BOOST_CHECK(p.isAccepted(pindex)); @@ -342,7 +342,7 @@ BOOST_CHECK_EQUAL(invs[0].type, MSG_BLOCK); BOOST_CHECK(invs[0].hash == blockHash); - resp = {AvalancheTest::getRound(p), 0, {AvalancheVote(1, blockHash)}}; + resp = {AvalancheTest::getRound(p), 0, {Vote(1, blockHash)}}; for (int i = 0; i < 6; i++) { registerNewVote(next(resp)); BOOST_CHECK(p.isAccepted(pindex)); @@ -434,15 +434,11 @@ uint64_t round = AvalancheTest::getRound(p); AvalancheTest::runEventLoop(p); BOOST_CHECK(p.registerVotes(avanodes[0]->GetId(), - {round, 0, {AvalancheVote(0, blockHashA)}}, - updates)); + {round, 0, {Vote(0, blockHashA)}}, updates)); BOOST_CHECK_EQUAL(updates.size(), 0); // Start voting on block B after one vote. - AvalancheResponse resp{ - round + 1, - 0, - {AvalancheVote(0, blockHashB), AvalancheVote(0, blockHashA)}}; + Response resp{round + 1, 0, {Vote(0, blockHashB), Vote(0, blockHashA)}}; BOOST_CHECK(p.addBlockToReconcile(pindexB)); invs = AvalancheTest::getInvsForNextPoll(p); BOOST_CHECK_EQUAL(invs.size(), 2); @@ -552,7 +548,7 @@ BOOST_CHECK_EQUAL(AvalancheTest::getSuitableNodeToQuery(p), NO_NODE); // Respond to the request. - AvalancheResponse resp = {round, 0, {AvalancheVote(0, blockHash)}}; + Response resp = {round, 0, {Vote(0, blockHash)}}; BOOST_CHECK(p.registerVotes(avanodeid, resp, updates)); BOOST_CHECK_EQUAL(updates.size(), 0); @@ -571,8 +567,7 @@ // Sending responses that do not match the request also fails. // 1. Too many results. - resp = { - round, 0, {AvalancheVote(0, blockHash), AvalancheVote(0, blockHash)}}; + resp = {round, 0, {Vote(0, blockHash), Vote(0, blockHash)}}; AvalancheTest::runEventLoop(p); BOOST_CHECK(!p.registerVotes(avanodeid, resp, updates)); BOOST_CHECK_EQUAL(updates.size(), 0); @@ -586,7 +581,7 @@ BOOST_CHECK_EQUAL(AvalancheTest::getSuitableNodeToQuery(p), avanodeid); // 3. Do not match the poll. - resp = {AvalancheTest::getRound(p), 0, {AvalancheVote()}}; + resp = {AvalancheTest::getRound(p), 0, {Vote()}}; AvalancheTest::runEventLoop(p); BOOST_CHECK(!p.registerVotes(avanodeid, resp, updates)); BOOST_CHECK_EQUAL(updates.size(), 0); @@ -596,22 +591,22 @@ uint64_t queryRound = AvalancheTest::getRound(p); AvalancheTest::runEventLoop(p); - resp = {queryRound + 1, 0, {AvalancheVote()}}; + resp = {queryRound + 1, 0, {Vote()}}; BOOST_CHECK(!p.registerVotes(avanodeid, resp, updates)); BOOST_CHECK_EQUAL(updates.size(), 0); - resp = {queryRound - 1, 0, {AvalancheVote()}}; + resp = {queryRound - 1, 0, {Vote()}}; BOOST_CHECK(!p.registerVotes(avanodeid, resp, updates)); BOOST_CHECK_EQUAL(updates.size(), 0); // 5. Making request for invalid nodes do not work. Request is not // discarded. - resp = {queryRound, 0, {AvalancheVote(0, blockHash)}}; + resp = {queryRound, 0, {Vote(0, blockHash)}}; BOOST_CHECK(!p.registerVotes(avanodeid + 1234, resp, updates)); BOOST_CHECK_EQUAL(updates.size(), 0); // Proper response gets processed and avanode is available again. - resp = {queryRound, 0, {AvalancheVote(0, blockHash)}}; + resp = {queryRound, 0, {Vote(0, blockHash)}}; BOOST_CHECK(p.registerVotes(avanodeid, resp, updates)); BOOST_CHECK_EQUAL(updates.size(), 0); BOOST_CHECK_EQUAL(AvalancheTest::getSuitableNodeToQuery(p), avanodeid); @@ -628,7 +623,7 @@ resp = {AvalancheTest::getRound(p), 0, - {AvalancheVote(0, blockHash), AvalancheVote(0, blockHash2)}}; + {Vote(0, blockHash), Vote(0, blockHash2)}}; AvalancheTest::runEventLoop(p); BOOST_CHECK(!p.registerVotes(avanodeid, resp, updates)); BOOST_CHECK_EQUAL(updates.size(), 0); @@ -637,7 +632,7 @@ // But they are accepted in order. resp = {AvalancheTest::getRound(p), 0, - {AvalancheVote(0, blockHash2), AvalancheVote(0, blockHash)}}; + {Vote(0, blockHash2), Vote(0, blockHash)}}; AvalancheTest::runEventLoop(p); BOOST_CHECK(p.registerVotes(avanodeid, resp, updates)); BOOST_CHECK_EQUAL(updates.size(), 0); @@ -645,7 +640,7 @@ // When a block is marked invalid, stop polling. pindex2->nStatus = pindex2->nStatus.withFailed(); - resp = {AvalancheTest::getRound(p), 0, {AvalancheVote(0, blockHash)}}; + resp = {AvalancheTest::getRound(p), 0, {Vote(0, blockHash)}}; AvalancheTest::runEventLoop(p); BOOST_CHECK(p.registerVotes(avanodeid, resp, updates)); BOOST_CHECK_EQUAL(updates.size(), 0); @@ -686,8 +681,7 @@ auto queryTimeDuration = std::chrono::milliseconds(10); p.setQueryTimeoutDuration(queryTimeDuration); for (int i = 0; i < 10; i++) { - AvalancheResponse resp = { - AvalancheTest::getRound(p), 0, {AvalancheVote(0, blockHash)}}; + Response resp = {AvalancheTest::getRound(p), 0, {Vote(0, blockHash)}}; auto start = std::chrono::steady_clock::now(); AvalancheTest::runEventLoop(p); @@ -772,7 +766,7 @@ // Send one response, now we can poll again. auto it = node_round_map.begin(); - AvalancheResponse resp = {it->second, 0, {AvalancheVote(0, blockHash)}}; + Response resp = {it->second, 0, {Vote(0, blockHash)}}; BOOST_CHECK(p.registerVotes(it->first, resp, updates)); node_round_map.erase(it); @@ -814,7 +808,7 @@ // Do one valid round of voting. uint64_t round = AvalancheTest::getRound(p); - AvalancheResponse resp{round, 0, {AvalancheVote(0, blockHash)}}; + Response resp{round, 0, {Vote(0, blockHash)}}; // Check that all nodes can vote. for (size_t i = 0; i < avanodes.size(); i++) { @@ -848,13 +842,13 @@ continue; } - BOOST_CHECK(p.registerVotes( - nodeid, {r, 0, {AvalancheVote(0, blockHash)}}, updates)); + BOOST_CHECK( + p.registerVotes(nodeid, {r, 0, {Vote(0, blockHash)}}, updates)); BOOST_CHECK_EQUAL(p.getConfidence(pindex), confidence); } - BOOST_CHECK(p.registerVotes( - firstNodeId, {round, 0, {AvalancheVote(0, blockHash)}}, updates)); + BOOST_CHECK(p.registerVotes(firstNodeId, {round, 0, {Vote(0, blockHash)}}, + updates)); BOOST_CHECK_EQUAL(p.getConfidence(pindex), confidence + 1); connman->ClearNodes(); @@ -922,8 +916,7 @@ std::chrono::steady_clock::now() + std::chrono::milliseconds(100); std::vector updates; - p.registerVotes(nodeid, {queryRound, 100, {AvalancheVote(0, blockHash)}}, - updates); + p.registerVotes(nodeid, {queryRound, 100, {Vote(0, blockHash)}}, updates); for (int i = 0; i < 10000; i++) { // We make sure that we do not get a request before queryTime. UninterruptibleSleep(std::chrono::milliseconds(1)); diff --git a/src/net_processing.cpp b/src/net_processing.cpp --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -3587,7 +3587,7 @@ return error("poll message size = %u", nCount); } - std::vector votes; + std::vector votes; votes.reserve(nCount); LogPrint(BCLog::NET, "received avalanche poll from peer=%d\n", @@ -3615,7 +3615,7 @@ // Send the query to the node. g_avalanche->sendResponse( - pfrom, AvalancheResponse(round, cooldown, std::move(votes))); + pfrom, avalanche::Response(round, cooldown, std::move(votes))); return true; } @@ -3627,7 +3627,7 @@ // verify response's signatures in order to avoid any manipulation of // messages at the transport level. CHashVerifier verifier(&vRecv); - AvalancheResponse response; + avalanche::Response response; verifier >> response; if (!g_avalanche->forNode( diff --git a/src/protocol.h b/src/protocol.h --- a/src/protocol.h +++ b/src/protocol.h @@ -259,12 +259,12 @@ */ extern const char *BLOCKTXN; /** - * Contains an AvalanchePoll. + * Contains an avalanche::Poll. * Peer should respond with "avaresponse" message. */ extern const char *AVAPOLL; /** - * Contains an AvalancheResponse. + * Contains an avalanche::Response. * Sent in response to a "avapoll" message. */ extern const char *AVARESPONSE;