Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13115670
D2042.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
8 KB
Subscribers
None
D2042.diff
View Options
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -181,6 +181,7 @@
add_library(server
addrman.cpp
addrdb.cpp
+ avalanche.cpp
bloom.cpp
blockencodings.cpp
chain.cpp
diff --git a/src/Makefile.am b/src/Makefile.am
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -102,7 +102,7 @@
BITCOIN_CORE_H = \
addrdb.h \
addrman.h \
- avalanche_impl.h \
+ avalanche.h \
base58.h \
bloom.h \
blockencodings.h \
@@ -227,6 +227,7 @@
libbitcoin_server_a_SOURCES = \
addrman.cpp \
addrdb.cpp \
+ avalanche.cpp \
bloom.cpp \
blockencodings.cpp \
chain.cpp \
diff --git a/src/avalanche_impl.h b/src/avalanche.h
rename from src/avalanche_impl.h
rename to src/avalanche.h
--- a/src/avalanche_impl.h
+++ b/src/avalanche.h
@@ -2,16 +2,28 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_AVALANCHE_IMPL_H
-#define BITCOIN_AVALANCHE_IMPL_H
+#ifndef BITCOIN_AVALANCHE_H
+#define BITCOIN_AVALANCHE_H
+
+#include "net.h" // for NodeId
+#include "protocol.h" // for CInv
+#include "rwcollection.h"
+#include "serialize.h"
+#include "uint256.h"
#include <cstdint>
+#include <vector>
+
+class Config;
+class CBlockIndex;
+class CScheduler;
namespace {
/**
* Finalization score.
*/
static int AVALANCHE_FINALIZATION_SCORE = 128;
+}
/**
* Vote history.
@@ -77,6 +89,64 @@
return true;
}
};
-}
-#endif // BITCOIN_AVALANCHE_IMPL_H
+class AvalancheVote {
+ uint32_t error;
+ uint256 hash;
+
+public:
+ AvalancheVote() : error(-1), hash() {}
+ AvalancheVote(uint32_t errorIn, uint256 hashIn)
+ : error(errorIn), hash(hashIn) {}
+
+ const uint256 &GetHash() const { return hash; }
+ bool IsValid() const { return error == 0; }
+
+ // serialization support
+ ADD_SERIALIZE_METHODS;
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream &s, Operation ser_action) {
+ READWRITE(error);
+ READWRITE(hash);
+ }
+};
+
+class AvalancheResponse {
+ uint32_t cooldown;
+ std::vector<AvalancheVote> votes;
+
+public:
+ AvalancheResponse(uint32_t cooldownIn, std::vector<AvalancheVote> votesIn)
+ : cooldown(cooldownIn), votes(votesIn) {}
+
+ const std::vector<AvalancheVote> &GetVotes() const { return votes; }
+
+ // serialization support
+ ADD_SERIALIZE_METHODS;
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream &s, Operation ser_action) {
+ READWRITE(cooldown);
+ READWRITE(votes);
+ }
+};
+
+class AvalancheProcessor {
+private:
+ /**
+ * Blocks to run avalanche on.
+ */
+ RWCollection<std::map<const CBlockIndex *, VoteRecord>> vote_records;
+
+public:
+ AvalancheProcessor() {}
+
+ bool addBlockToReconcile(const CBlockIndex *pindex);
+ bool isAccepted(const CBlockIndex *pindex) const;
+ bool hasFinalized(const CBlockIndex *pindex) const;
+
+ bool registerVotes(const AvalancheResponse &response);
+};
+
+#endif // BITCOIN_AVALANCHE_H
diff --git a/src/avalanche.cpp b/src/avalanche.cpp
new file mode 100644
--- /dev/null
+++ b/src/avalanche.cpp
@@ -0,0 +1,76 @@
+// Copyright (c) 2018 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "avalanche.h"
+
+#include "chain.h"
+#include "netmessagemaker.h"
+#include "scheduler.h"
+#include "validation.h"
+
+bool AvalancheProcessor::addBlockToReconcile(const CBlockIndex *pindex) {
+ return vote_records.getWriteView()
+ ->insert(std::make_pair(pindex, VoteRecord()))
+ .second;
+}
+
+static const VoteRecord *GetRecord(
+ const RWCollection<std::map<const CBlockIndex *, VoteRecord>> &vote_records,
+ const CBlockIndex *pindex) {
+ auto r = vote_records.getReadView();
+ auto it = r->find(pindex);
+ if (it == r.end()) {
+ return nullptr;
+ }
+
+ return &it->second;
+}
+
+bool AvalancheProcessor::isAccepted(const CBlockIndex *pindex) const {
+ if (auto vr = GetRecord(vote_records, pindex)) {
+ return vr->isValid();
+ }
+
+ return false;
+}
+
+bool AvalancheProcessor::hasFinalized(const CBlockIndex *pindex) const {
+ if (auto vr = GetRecord(vote_records, pindex)) {
+ return vr->hasFinalized();
+ }
+
+ return false;
+}
+
+bool AvalancheProcessor::registerVotes(const AvalancheResponse &response) {
+ const std::vector<AvalancheVote> &votes = response.GetVotes();
+
+ std::map<const CBlockIndex *, AvalancheVote> responseIndex;
+
+ {
+ LOCK(cs_main);
+ for (auto &v : votes) {
+ BlockMap::iterator mi = mapBlockIndex.find(v.GetHash());
+ if (mi == mapBlockIndex.end()) {
+ // This should not happen, but just in case...
+ continue;
+ }
+
+ responseIndex.insert(std::make_pair(mi->second, v));
+ }
+ }
+
+ {
+ // Register votes.
+ auto w = vote_records.getWriteView();
+ for (auto &p : responseIndex) {
+ const CBlockIndex *pindex = p.first;
+ const AvalancheVote &v = p.second;
+
+ w[pindex].registerVote(v.IsValid());
+ }
+ }
+
+ return true;
+}
diff --git a/src/test/avalanche_tests.cpp b/src/test/avalanche_tests.cpp
--- a/src/test/avalanche_tests.cpp
+++ b/src/test/avalanche_tests.cpp
@@ -2,13 +2,13 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "avalanche_impl.h"
+#include "avalanche.h"
#include "test/test_bitcoin.h"
#include <boost/test/unit_test.hpp>
-BOOST_FIXTURE_TEST_SUITE(avalanche_tests, BasicTestingSetup)
+BOOST_FIXTURE_TEST_SUITE(avalanche_tests, TestChain100Setup)
#define REGISTER_VOTE_AND_CHECK(vr, vote, state, finalized, confidence) \
vr.registerVote(vote); \
@@ -66,4 +66,66 @@
AVALANCHE_FINALIZATION_SCORE);
}
+BOOST_AUTO_TEST_CASE(block_register) {
+ AvalancheProcessor p;
+
+ CBlock block = CreateAndProcessBlock({}, CScript());
+ const uint256 hash = block.GetHash();
+ const CBlockIndex *pindex = mapBlockIndex[hash];
+
+ // Querying for random block returns false.
+ BOOST_CHECK(!p.isAccepted(pindex));
+ BOOST_CHECK(!p.hasFinalized(pindex));
+
+ // Newly added blocks are also considered rejected.
+ BOOST_CHECK(p.addBlockToReconcile(pindex));
+ BOOST_CHECK(!p.isAccepted(pindex));
+ BOOST_CHECK(!p.hasFinalized(pindex));
+
+ // Let's vote for this block a few times.
+ AvalancheResponse resp{0, {AvalancheVote(0, hash)}};
+ for (int i = 0; i < 5; i++) {
+ p.registerVotes(resp);
+ BOOST_CHECK(!p.isAccepted(pindex));
+ BOOST_CHECK(!p.hasFinalized(pindex));
+ }
+
+ // Now it is accepted, but we can vote for it numerous times.
+ for (int i = 0; i < AVALANCHE_FINALIZATION_SCORE; i++) {
+ p.registerVotes(resp);
+ BOOST_CHECK(p.isAccepted(pindex));
+ BOOST_CHECK(!p.hasFinalized(pindex));
+ }
+
+ // Now finalize the decision.
+ resp = {0, {AvalancheVote(1, hash)}};
+ p.registerVotes(resp);
+ BOOST_CHECK(p.isAccepted(pindex));
+ BOOST_CHECK(p.hasFinalized(pindex));
+
+ // Now let's undo this and finalize rejection.
+ for (int i = 0; i < 5; i++) {
+ p.registerVotes(resp);
+ BOOST_CHECK(p.isAccepted(pindex));
+ BOOST_CHECK(p.hasFinalized(pindex));
+ }
+
+ // Now it is rejected, but we can vote for it numerous times.
+ for (int i = 0; i < AVALANCHE_FINALIZATION_SCORE; i++) {
+ p.registerVotes(resp);
+ BOOST_CHECK(!p.isAccepted(pindex));
+ BOOST_CHECK(!p.hasFinalized(pindex));
+ }
+
+ // Now finalize the decision.
+ p.registerVotes(resp);
+ BOOST_CHECK(!p.isAccepted(pindex));
+ BOOST_CHECK(p.hasFinalized(pindex));
+
+ // Adding the block twice does nothing.
+ BOOST_CHECK(!p.addBlockToReconcile(pindex));
+ BOOST_CHECK(!p.isAccepted(pindex));
+ BOOST_CHECK(p.hasFinalized(pindex));
+}
+
BOOST_AUTO_TEST_SUITE_END()
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Mar 1, 11:42 (6 h, 37 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5187669
Default Alt Text
D2042.diff (8 KB)
Attached To
D2042: [avalanche] Add a block registry and facility to register votes on these blocks.
Event Timeline
Log In to Comment