Merge master (1.1.2) into develop (1.2.0-b8)

This commit is contained in:
Nik Bougalis
2018-12-11 12:48:32 -08:00
6 changed files with 237 additions and 170 deletions

View File

@@ -18,9 +18,9 @@
//==============================================================================
#include <ripple/beast/unit_test.h>
#include <ripple/consensus/LedgerTrie.h>
#include <random>
#include <test/csf/ledgers.h>
#include <unordered_map>
#include <random>
namespace ripple {
namespace test {
@@ -138,20 +138,19 @@ class LedgerTrie_test : public beast::unit_test::suite
{
LedgerTrie<Ledger> t;
LedgerHistoryHelper h;
t.insert(h["ab"],4);
t.insert(h["ab"], 4);
BEAST_EXPECT(t.tipSupport(h["ab"]) == 4);
BEAST_EXPECT(t.branchSupport(h["ab"]) == 4);
BEAST_EXPECT(t.tipSupport(h["a"]) == 0);
BEAST_EXPECT(t.branchSupport(h["a"]) == 4);
t.insert(h["abc"],2);
t.insert(h["abc"], 2);
BEAST_EXPECT(t.tipSupport(h["abc"]) == 2);
BEAST_EXPECT(t.branchSupport(h["abc"]) == 2);
BEAST_EXPECT(t.tipSupport(h["ab"]) == 4);
BEAST_EXPECT(t.branchSupport(h["ab"]) == 6);
BEAST_EXPECT(t.tipSupport(h["a"]) == 0);
BEAST_EXPECT(t.branchSupport(h["a"]) == 6);
}
}
@@ -188,7 +187,7 @@ class LedgerTrie_test : public beast::unit_test::suite
{
LedgerTrie<Ledger> t;
LedgerHistoryHelper h;
t.insert(h["abc"],2);
t.insert(h["abc"], 2);
BEAST_EXPECT(t.tipSupport(h["abc"]) == 2);
BEAST_EXPECT(t.remove(h["abc"]));
@@ -206,7 +205,6 @@ class LedgerTrie_test : public beast::unit_test::suite
BEAST_EXPECT(t.remove(h["abc"], 300));
BEAST_EXPECT(t.checkInvariants());
BEAST_EXPECT(t.tipSupport(h["abc"]) == 0);
}
// In trie with = 1 tip support, no children
{
@@ -285,17 +283,35 @@ class LedgerTrie_test : public beast::unit_test::suite
BEAST_EXPECT(t.tipSupport(h["abc"]) == 1);
BEAST_EXPECT(t.branchSupport(h["ab"]) == 1);
}
}
void
testEmpty()
{
using namespace csf;
LedgerTrie<Ledger> t;
LedgerHistoryHelper h;
BEAST_EXPECT(t.empty());
Ledger genesis = h[""];
t.insert(genesis);
BEAST_EXPECT(!t.empty());
t.remove(genesis);
BEAST_EXPECT(t.empty());
t.insert(h["abc"]);
BEAST_EXPECT(!t.empty());
t.remove(h["abc"]);
BEAST_EXPECT(t.empty());
}
void
testSupport()
{
using namespace csf;
using Seq = Ledger::Seq;
LedgerTrie<Ledger> t;
LedgerHistoryHelper h;
BEAST_EXPECT(t.tipSupport(h["a"]) == 0);
@@ -336,7 +352,6 @@ class LedgerTrie_test : public beast::unit_test::suite
BEAST_EXPECT(t.branchSupport(h["ab"]) == 1);
BEAST_EXPECT(t.branchSupport(h["abc"]) == 0);
BEAST_EXPECT(t.branchSupport(h["abe"]) == 1);
}
void
@@ -345,18 +360,28 @@ class LedgerTrie_test : public beast::unit_test::suite
using namespace csf;
using Seq = Ledger::Seq;
// Empty
{
LedgerTrie<Ledger> t;
BEAST_EXPECT(t.getPreferred(Seq{0}) == boost::none);
BEAST_EXPECT(t.getPreferred(Seq{2}) == boost::none);
}
// Genesis support is NOT empty
{
LedgerTrie<Ledger> t;
LedgerHistoryHelper h;
BEAST_EXPECT(t.getPreferred(Seq{0}).id == h[""].id());
BEAST_EXPECT(t.getPreferred(Seq{2}).id == h[""].id());
Ledger genesis = h[""];
t.insert(genesis);
BEAST_EXPECT(t.getPreferred(Seq{0})->id == genesis.id());
BEAST_EXPECT(t.remove(genesis));
BEAST_EXPECT(t.getPreferred(Seq{0}) == boost::none);
BEAST_EXPECT(!t.remove(genesis));
}
// Single node no children
{
LedgerTrie<Ledger> t;
LedgerHistoryHelper h;
t.insert(h["abc"]);
BEAST_EXPECT(t.getPreferred(Seq{3}).id == h["abc"].id());
BEAST_EXPECT(t.getPreferred(Seq{3})->id == h["abc"].id());
}
// Single node smaller child support
{
@@ -364,17 +389,17 @@ class LedgerTrie_test : public beast::unit_test::suite
LedgerHistoryHelper h;
t.insert(h["abc"]);
t.insert(h["abcd"]);
BEAST_EXPECT(t.getPreferred(Seq{3}).id == h["abc"].id());
BEAST_EXPECT(t.getPreferred(Seq{4}).id == h["abc"].id());
BEAST_EXPECT(t.getPreferred(Seq{3})->id == h["abc"].id());
BEAST_EXPECT(t.getPreferred(Seq{4})->id == h["abc"].id());
}
// Single node larger child
{
LedgerTrie<Ledger> t;
LedgerHistoryHelper h;
t.insert(h["abc"]);
t.insert(h["abcd"],2);
BEAST_EXPECT(t.getPreferred(Seq{3}).id == h["abcd"].id());
BEAST_EXPECT(t.getPreferred(Seq{4}).id == h["abcd"].id());
t.insert(h["abcd"], 2);
BEAST_EXPECT(t.getPreferred(Seq{3})->id == h["abcd"].id());
BEAST_EXPECT(t.getPreferred(Seq{4})->id == h["abcd"].id());
}
// Single node smaller children support
{
@@ -383,40 +408,40 @@ class LedgerTrie_test : public beast::unit_test::suite
t.insert(h["abc"]);
t.insert(h["abcd"]);
t.insert(h["abce"]);
BEAST_EXPECT(t.getPreferred(Seq{3}).id == h["abc"].id());
BEAST_EXPECT(t.getPreferred(Seq{4}).id == h["abc"].id());
BEAST_EXPECT(t.getPreferred(Seq{3})->id == h["abc"].id());
BEAST_EXPECT(t.getPreferred(Seq{4})->id == h["abc"].id());
t.insert(h["abc"]);
BEAST_EXPECT(t.getPreferred(Seq{3}).id == h["abc"].id());
BEAST_EXPECT(t.getPreferred(Seq{4}).id == h["abc"].id());
BEAST_EXPECT(t.getPreferred(Seq{3})->id == h["abc"].id());
BEAST_EXPECT(t.getPreferred(Seq{4})->id == h["abc"].id());
}
// Single node larger children
{
LedgerTrie<Ledger> t;
LedgerHistoryHelper h;
t.insert(h["abc"]);
t.insert(h["abcd"],2);
t.insert(h["abcd"], 2);
t.insert(h["abce"]);
BEAST_EXPECT(t.getPreferred(Seq{3}).id == h["abc"].id());
BEAST_EXPECT(t.getPreferred(Seq{4}).id == h["abc"].id());
BEAST_EXPECT(t.getPreferred(Seq{3})->id == h["abc"].id());
BEAST_EXPECT(t.getPreferred(Seq{4})->id == h["abc"].id());
t.insert(h["abcd"]);
BEAST_EXPECT(t.getPreferred(Seq{3}).id == h["abcd"].id());
BEAST_EXPECT(t.getPreferred(Seq{4}).id == h["abcd"].id());
BEAST_EXPECT(t.getPreferred(Seq{3})->id == h["abcd"].id());
BEAST_EXPECT(t.getPreferred(Seq{4})->id == h["abcd"].id());
}
// Tie-breaker by id
{
LedgerTrie<Ledger> t;
LedgerHistoryHelper h;
t.insert(h["abcd"],2);
t.insert(h["abce"],2);
t.insert(h["abcd"], 2);
t.insert(h["abce"], 2);
BEAST_EXPECT(h["abce"].id() > h["abcd"].id());
BEAST_EXPECT(t.getPreferred(Seq{4}).id == h["abce"].id());
BEAST_EXPECT(t.getPreferred(Seq{4})->id == h["abce"].id());
t.insert(h["abcd"]);
BEAST_EXPECT(h["abce"].id() > h["abcd"].id());
BEAST_EXPECT(t.getPreferred(Seq{4}).id == h["abcd"].id());
BEAST_EXPECT(t.getPreferred(Seq{4})->id == h["abcd"].id());
}
// Tie-breaker not needed
@@ -425,17 +450,17 @@ class LedgerTrie_test : public beast::unit_test::suite
LedgerHistoryHelper h;
t.insert(h["abc"]);
t.insert(h["abcd"]);
t.insert(h["abce"],2);
t.insert(h["abce"], 2);
// abce only has a margin of 1, but it owns the tie-breaker
BEAST_EXPECT(h["abce"].id() > h["abcd"].id());
BEAST_EXPECT(t.getPreferred(Seq{3}).id == h["abce"].id());
BEAST_EXPECT(t.getPreferred(Seq{4}).id == h["abce"].id());
BEAST_EXPECT(t.getPreferred(Seq{3})->id == h["abce"].id());
BEAST_EXPECT(t.getPreferred(Seq{4})->id == h["abce"].id());
// Switch support from abce to abcd, tie-breaker now needed
t.remove(h["abce"]);
t.insert(h["abcd"]);
BEAST_EXPECT(t.getPreferred(Seq{3}).id == h["abc"].id());
BEAST_EXPECT(t.getPreferred(Seq{4}).id == h["abc"].id());
BEAST_EXPECT(t.getPreferred(Seq{3})->id == h["abc"].id());
BEAST_EXPECT(t.getPreferred(Seq{4})->id == h["abc"].id());
}
// Single node larger grand child
@@ -443,11 +468,11 @@ class LedgerTrie_test : public beast::unit_test::suite
LedgerTrie<Ledger> t;
LedgerHistoryHelper h;
t.insert(h["abc"]);
t.insert(h["abcd"],2);
t.insert(h["abcde"],4);
BEAST_EXPECT(t.getPreferred(Seq{3}).id == h["abcde"].id());
BEAST_EXPECT(t.getPreferred(Seq{4}).id == h["abcde"].id());
BEAST_EXPECT(t.getPreferred(Seq{5}).id == h["abcde"].id());
t.insert(h["abcd"], 2);
t.insert(h["abcde"], 4);
BEAST_EXPECT(t.getPreferred(Seq{3})->id == h["abcde"].id());
BEAST_EXPECT(t.getPreferred(Seq{4})->id == h["abcde"].id());
BEAST_EXPECT(t.getPreferred(Seq{5})->id == h["abcde"].id());
}
// Too much uncommitted support from competing branches
@@ -455,25 +480,25 @@ class LedgerTrie_test : public beast::unit_test::suite
LedgerTrie<Ledger> t;
LedgerHistoryHelper h;
t.insert(h["abc"]);
t.insert(h["abcde"],2);
t.insert(h["abcfg"],2);
t.insert(h["abcde"], 2);
t.insert(h["abcfg"], 2);
// 'de' and 'fg' are tied without 'abc' vote
BEAST_EXPECT(t.getPreferred(Seq{3}).id == h["abc"].id());
BEAST_EXPECT(t.getPreferred(Seq{4}).id == h["abc"].id());
BEAST_EXPECT(t.getPreferred(Seq{5}).id == h["abc"].id());
BEAST_EXPECT(t.getPreferred(Seq{3})->id == h["abc"].id());
BEAST_EXPECT(t.getPreferred(Seq{4})->id == h["abc"].id());
BEAST_EXPECT(t.getPreferred(Seq{5})->id == h["abc"].id());
t.remove(h["abc"]);
t.insert(h["abcd"]);
// 'de' branch has 3 votes to 2, so earlier sequences see it as
// preferred
BEAST_EXPECT(t.getPreferred(Seq{3}).id == h["abcde"].id());
BEAST_EXPECT(t.getPreferred(Seq{4}).id == h["abcde"].id());
BEAST_EXPECT(t.getPreferred(Seq{3})->id == h["abcde"].id());
BEAST_EXPECT(t.getPreferred(Seq{4})->id == h["abcde"].id());
// However, if you validated a ledger with Seq 5, potentially on
// a different branch, you do not yet know if they chose abcd
// or abcf because of you, so abc remains preferred
BEAST_EXPECT(t.getPreferred(Seq{5}).id == h["abc"].id());
BEAST_EXPECT(t.getPreferred(Seq{5})->id == h["abc"].id());
}
// Changing largestSeq perspective changes preferred branch
@@ -494,15 +519,15 @@ class LedgerTrie_test : public beast::unit_test::suite
t.insert(h["ab"]);
t.insert(h["ac"]);
t.insert(h["acf"]);
t.insert(h["abde"],2);
t.insert(h["abde"], 2);
// B has more branch support
BEAST_EXPECT(t.getPreferred(Seq{1}).id == h["ab"].id());
BEAST_EXPECT(t.getPreferred(Seq{2}).id == h["ab"].id());
BEAST_EXPECT(t.getPreferred(Seq{1})->id == h["ab"].id());
BEAST_EXPECT(t.getPreferred(Seq{2})->id == h["ab"].id());
// But if you last validated D,F or E, you do not yet know
// if someone used that validation to commit to B or C
BEAST_EXPECT(t.getPreferred(Seq{3}).id == h["a"].id());
BEAST_EXPECT(t.getPreferred(Seq{4}).id == h["a"].id());
BEAST_EXPECT(t.getPreferred(Seq{3})->id == h["a"].id());
BEAST_EXPECT(t.getPreferred(Seq{4})->id == h["a"].id());
/** One of E advancing to G doesn't change anything
A
@@ -518,11 +543,11 @@ class LedgerTrie_test : public beast::unit_test::suite
t.remove(h["abde"]);
t.insert(h["abdeg"]);
BEAST_EXPECT(t.getPreferred(Seq{1}).id == h["ab"].id());
BEAST_EXPECT(t.getPreferred(Seq{2}).id == h["ab"].id());
BEAST_EXPECT(t.getPreferred(Seq{3}).id == h["a"].id());
BEAST_EXPECT(t.getPreferred(Seq{4}).id == h["a"].id());
BEAST_EXPECT(t.getPreferred(Seq{5}).id == h["a"].id());
BEAST_EXPECT(t.getPreferred(Seq{1})->id == h["ab"].id());
BEAST_EXPECT(t.getPreferred(Seq{2})->id == h["ab"].id());
BEAST_EXPECT(t.getPreferred(Seq{3})->id == h["a"].id());
BEAST_EXPECT(t.getPreferred(Seq{4})->id == h["a"].id());
BEAST_EXPECT(t.getPreferred(Seq{5})->id == h["a"].id());
/** C advancing to H does advance the seq 3 preferred ledger
A
@@ -537,11 +562,11 @@ class LedgerTrie_test : public beast::unit_test::suite
*/
t.remove(h["ac"]);
t.insert(h["abh"]);
BEAST_EXPECT(t.getPreferred(Seq{1}).id == h["ab"].id());
BEAST_EXPECT(t.getPreferred(Seq{2}).id == h["ab"].id());
BEAST_EXPECT(t.getPreferred(Seq{3}).id == h["ab"].id());
BEAST_EXPECT(t.getPreferred(Seq{4}).id == h["a"].id());
BEAST_EXPECT(t.getPreferred(Seq{5}).id == h["a"].id());
BEAST_EXPECT(t.getPreferred(Seq{1})->id == h["ab"].id());
BEAST_EXPECT(t.getPreferred(Seq{2})->id == h["ab"].id());
BEAST_EXPECT(t.getPreferred(Seq{3})->id == h["ab"].id());
BEAST_EXPECT(t.getPreferred(Seq{4})->id == h["a"].id());
BEAST_EXPECT(t.getPreferred(Seq{5})->id == h["a"].id());
/** F advancing to E also moves the preferred ledger forward
A
@@ -556,15 +581,12 @@ class LedgerTrie_test : public beast::unit_test::suite
*/
t.remove(h["acf"]);
t.insert(h["abde"]);
BEAST_EXPECT(t.getPreferred(Seq{1}).id == h["abde"].id());
BEAST_EXPECT(t.getPreferred(Seq{2}).id == h["abde"].id());
BEAST_EXPECT(t.getPreferred(Seq{3}).id == h["abde"].id());
BEAST_EXPECT(t.getPreferred(Seq{4}).id == h["ab"].id());
BEAST_EXPECT(t.getPreferred(Seq{5}).id == h["ab"].id());
BEAST_EXPECT(t.getPreferred(Seq{1})->id == h["abde"].id());
BEAST_EXPECT(t.getPreferred(Seq{2})->id == h["abde"].id());
BEAST_EXPECT(t.getPreferred(Seq{3})->id == h["abde"].id());
BEAST_EXPECT(t.getPreferred(Seq{4})->id == h["ab"].id());
BEAST_EXPECT(t.getPreferred(Seq{5})->id == h["ab"].id());
}
}
void
@@ -610,22 +632,22 @@ class LedgerTrie_test : public beast::unit_test::suite
// Ledgers have sequence 1,2,3,4
std::uint32_t const depth = 4;
// Each ledger has 4 possible children
std::uint32_t const width = 4;
std::uint32_t const width = 4;
std::uint32_t const iterations = 10000;
// Use explicit seed to have same results for CI
std::mt19937 gen{ 42 };
std::uniform_int_distribution<> depthDist(0, depth-1);
std::uniform_int_distribution<> widthDist(0, width-1);
std::mt19937 gen{42};
std::uniform_int_distribution<> depthDist(0, depth - 1);
std::uniform_int_distribution<> widthDist(0, width - 1);
std::uniform_int_distribution<> flip(0, 1);
for(std::uint32_t i = 0; i < iterations; ++i)
for (std::uint32_t i = 0; i < iterations; ++i)
{
// pick a random ledger history
std::string curr = "";
char depth = depthDist(gen);
char offset = 0;
for(char d = 0; d < depth; ++d)
for (char d = 0; d < depth; ++d)
{
char a = offset + widthDist(gen);
curr += a;
@@ -633,11 +655,11 @@ class LedgerTrie_test : public beast::unit_test::suite
}
// 50-50 to add remove
if(flip(gen) == 0)
if (flip(gen) == 0)
t.insert(h[curr]);
else
t.remove(h[curr]);
if(!BEAST_EXPECT(t.checkInvariants()))
if (!BEAST_EXPECT(t.checkInvariants()))
return;
}
}
@@ -647,6 +669,7 @@ class LedgerTrie_test : public beast::unit_test::suite
{
testInsert();
testRemove();
testEmpty();
testSupport();
testGetPreferred();
testRootRelated();

View File

@@ -58,9 +58,7 @@ class Validations_test : public beast::unit_test::suite
boost::optional<std::uint32_t> loadFee_;
public:
Node(PeerID nodeID, clock_type const& c)
: c_(c)
, nodeID_(nodeID)
Node(PeerID nodeID, clock_type const& c) : c_(c), nodeID_(nodeID)
{
}
@@ -292,7 +290,7 @@ class Validations_test : public beast::unit_test::suite
}
};
Ledger const genesisLedger{Ledger::MakeGenesis{}};
Ledger const genesisLedger{Ledger::MakeGenesis{}};
void
testAddValidation()
@@ -349,8 +347,7 @@ class Validations_test : public beast::unit_test::suite
BEAST_EXPECT(
ValStatus::badSeq == harness.add(n.validate(ledgerAB)));
// Cannot send the same partial validation sequence
BEAST_EXPECT(
ValStatus::badSeq == harness.add(n.partial(ledgerAB)));
BEAST_EXPECT(ValStatus::badSeq == harness.add(n.partial(ledgerAB)));
// Now trusts the newest ledger too
harness.clock().advance(1s);
@@ -425,9 +422,8 @@ class Validations_test : public beast::unit_test::suite
TestHarness harness(h.oracle);
Node n = harness.makeNode();
auto process = [&](Ledger & lgr)
{
if(doFull)
auto process = [&](Ledger& lgr) {
if (doFull)
return harness.add(n.validate(lgr));
return harness.add(n.partial(lgr));
};
@@ -458,7 +454,6 @@ class Validations_test : public beast::unit_test::suite
Ledger ledgerA = h["a"];
Ledger ledgerAB = h["ab"];
using Trigger = std::function<void(TestValidations&)>;
std::vector<Trigger> triggers = {
@@ -492,8 +487,7 @@ class Validations_test : public beast::unit_test::suite
BEAST_EXPECT(
harness.vals().getNodesAfter(ledgerA, ledgerA.id()) == 0);
BEAST_EXPECT(
harness.vals().getPreferred(genesisLedger) ==
std::make_pair(Ledger::Seq{0}, Ledger::ID{0}));
harness.vals().getPreferred(genesisLedger) == boost::none);
}
}
@@ -611,8 +605,7 @@ class Validations_test : public beast::unit_test::suite
ValStatus::current == harness.add(node.validate(ledgerA)));
{
hash_set<PeerID> const expectedKeys = {a.nodeID(),
b.nodeID()};
hash_set<PeerID> const expectedKeys = {a.nodeID(), b.nodeID()};
BEAST_EXPECT(harness.vals().getCurrentNodeIDs() == expectedKeys);
}
@@ -627,8 +620,7 @@ class Validations_test : public beast::unit_test::suite
ValStatus::current == harness.add(node.partial(ledgerAC)));
{
hash_set<PeerID> const expectedKeys = {a.nodeID(),
b.nodeID()};
hash_set<PeerID> const expectedKeys = {a.nodeID(), b.nodeID()};
BEAST_EXPECT(harness.vals().getCurrentNodeIDs() == expectedKeys);
}
@@ -695,7 +687,6 @@ class Validations_test : public beast::unit_test::suite
BEAST_EXPECT(
sorted(harness.vals().fees(id, baseFee)) ==
sorted(expectedFees));
}
};
@@ -836,8 +827,7 @@ class Validations_test : public beast::unit_test::suite
};
// Empty (no ledgers)
BEAST_EXPECT(
harness.vals().getPreferred(ledgerA) == pref(genesisLedger));
BEAST_EXPECT(harness.vals().getPreferred(ledgerA) == boost::none);
// Single ledger
BEAST_EXPECT(ValStatus::current == harness.add(a.validate(ledgerB)));
@@ -1069,8 +1059,12 @@ class Validations_test : public beast::unit_test::suite
BEAST_EXPECT(
vals.getNodesAfter(this->genesisLedger, genesisLedger.id()) ==
trustedVals.size());
BEAST_EXPECT(
vals.getPreferred(this->genesisLedger).second == testID);
if (trustedVals.empty())
BEAST_EXPECT(
vals.getPreferred(this->genesisLedger) == boost::none);
else
BEAST_EXPECT(
vals.getPreferred(this->genesisLedger)->second == testID);
BEAST_EXPECT(vals.getTrustedForLedger(testID) == trustedVals);
BEAST_EXPECT(
vals.numTrustedForLedger(testID) == trustedVals.size());
@@ -1127,7 +1121,7 @@ class Validations_test : public beast::unit_test::suite
auto& vals = harness.vals();
BEAST_EXPECT(vals.currentTrusted() == trustedVals);
BEAST_EXPECT(
vals.getPreferred(genesisLedger).second == v.ledgerID());
vals.getPreferred(genesisLedger)->second == v.ledgerID());
BEAST_EXPECT(
vals.getNodesAfter(genesisLedger, genesisLedger.id()) == 0);
@@ -1136,8 +1130,7 @@ class Validations_test : public beast::unit_test::suite
// make acquiring ledger available
h["ab"];
BEAST_EXPECT(vals.currentTrusted() == trustedVals);
BEAST_EXPECT(
vals.getPreferred(genesisLedger).second == genesisLedger.id());
BEAST_EXPECT(vals.getPreferred(genesisLedger) == boost::none);
BEAST_EXPECT(
vals.getNodesAfter(genesisLedger, genesisLedger.id()) == 0);
}