diff --git a/src/ripple/consensus/LedgerTrie.h b/src/ripple/consensus/LedgerTrie.h index e914aa989..7efa59906 100644 --- a/src/ripple/consensus/LedgerTrie.h +++ b/src/ripple/consensus/LedgerTrie.h @@ -29,7 +29,7 @@ namespace ripple { /** The tip of a span of ledger ancestry -*/ + */ template class SpanTip { @@ -461,7 +461,7 @@ public: newNode->branchSupport = loc->branchSupport; newNode->children = std::move(loc->children); assert(loc->children.empty()); - for(std::unique_ptr & child : newNode->children) + for (std::unique_ptr& child : newNode->children) child->parent = newNode.get(); // Loc truncates to prefix and newNode is its child @@ -512,8 +512,7 @@ public: Seq diffSeq; std::tie(loc, diffSeq) = find(ledger); - // Cannot erase root - if (loc && loc != root.get()) + if (loc) { // Must be exact match with tip support if (diffSeq == loc->span.end() && diffSeq > ledger.seq() && @@ -525,7 +524,7 @@ public: auto const it = seqSupport.find(ledger.seq()); assert(it != seqSupport.end() && it->second >= count); it->second -= count; - if(it->second == 0) + if (it->second == 0) seqSupport.erase(it->first); Node* decNode = loc; @@ -584,7 +583,8 @@ public: /** Return the count of branch support for the specific ledger @param ledger The ledger to lookup - @return The number of entries in the trie for this ledger or a descendant + @return The number of entries in the trie for this ledger or a + descendant */ std::uint32_t branchSupport(Ledger const& ledger) const @@ -595,8 +595,7 @@ public: // Check that ledger is is an exact match or proper // prefix of loc - if (loc && diffSeq > ledger.seq() && - ledger.seq() < loc->span.end()) + if (loc && diffSeq > ledger.seq() && ledger.seq() < loc->span.end()) { return loc->branchSupport; } @@ -659,11 +658,15 @@ public: @param largestIssued The sequence number of the largest validation issued by this node. - @return Pair with the sequence number and ID of the preferred ledger + @return Pair with the sequence number and ID of the preferred ledger or + boost::none if no preferred ledger exists */ - SpanTip + boost::optional> getPreferred(Seq const largestIssued) const { + if (empty()) + return boost::none; + Node* curr = root.get(); bool done = false; @@ -699,7 +702,7 @@ public: uncommitted += uncommittedIt->second; uncommittedIt++; } - else // otherwise we jump to the end of the span + else // otherwise we jump to the end of the span nextSeq = curr->span.end(); } // We did not consume the entire span, so we have found the @@ -727,8 +730,10 @@ public: curr->children.end(), [](std::unique_ptr const& a, std::unique_ptr const& b) { - return std::make_tuple(a->branchSupport, a->span.startID()) > - std::make_tuple(b->branchSupport, b->span.startID()); + return std::make_tuple( + a->branchSupport, a->span.startID()) > + std::make_tuple( + b->branchSupport, b->span.startID()); }); best = curr->children[0].get(); @@ -752,6 +757,14 @@ public: return curr->span.tip(); } + /** Return whether the trie is tracking any ledgers + */ + bool + empty() const + { + return !root || root->branchSupport == 0; + } + /** Dump an ascii representation of the trie to the stream */ void @@ -761,7 +774,7 @@ public: } /** Dump JSON representation of trie state - */ + */ Json::Value getJson() const { @@ -798,7 +811,7 @@ public: for (auto const& child : curr->children) { - if(child->parent != curr) + if (child->parent != curr) return false; support += child->branchSupport; diff --git a/src/ripple/consensus/Validations.h b/src/ripple/consensus/Validations.h index 9e46460c7..0a499f19e 100644 --- a/src/ripple/consensus/Validations.h +++ b/src/ripple/consensus/Validations.h @@ -87,6 +87,7 @@ class SeqEnforcer using time_point = std::chrono::steady_clock::time_point; Seq seq_{0}; time_point when_; + public: /** Try advancing the largest observed validation ledger sequence @@ -101,11 +102,11 @@ public: @return Whether the validation satisfies the invariant */ bool - operator()(time_point now, Seq s, ValidationParms const & p) + operator()(time_point now, Seq s, ValidationParms const& p) { - if(now > (when_ + p.validationSET_EXPIRES)) + if (now > (when_ + p.validationSET_EXPIRES)) seq_ = Seq{0}; - if(s <= seq_) + if (s <= seq_) return false; seq_ = s; when_ = now; @@ -147,7 +148,6 @@ isCurrent( (seenTime < (now + p.validationCURRENT_LOCAL))); } - /** Status of newly received validation */ enum class ValStatus { @@ -233,8 +233,8 @@ to_string(ValStatus m) // Whether this is a full or partial validation bool full() const; - // Identifier for this node that remains fixed even when rotating signing - // keys + // Identifier for this node that remains fixed even when rotating + // signing keys NodeID nodeID() const; implementation_specific_t @@ -312,7 +312,7 @@ class Validations hash_map lastLedger_; // Set of ledgers being acquired from the network - hash_map, hash_set> acquiring_; + hash_map, hash_set> acquiring_; // Parameters to determine validation staleness ValidationParms const parms_; @@ -327,7 +327,8 @@ private: removeTrie(ScopedLock const&, NodeID const& nodeID, Validation const& val) { { - auto it = acquiring_.find(std::make_pair(val.seq(), val.ledgerID())); + auto it = + acquiring_.find(std::make_pair(val.seq(), val.ledgerID())); if (it != acquiring_.end()) { it->second.erase(nodeID); @@ -387,7 +388,8 @@ private: @param lock Existing lock of mutex_ @param nodeID The node identifier of the validating node @param val The trusted validation issued by the node - @param prior If not none, the last current validated ledger Seq,ID of key + @param prior If not none, the last current validated ledger Seq,ID of + key */ void updateTrie( @@ -445,7 +447,7 @@ private: withTrie(ScopedLock const& lock, F&& f) { // Call current to flush any stale validations - current(lock, [](auto){}, [](auto, auto){}); + current(lock, [](auto) {}, [](auto, auto) {}); checkAcquired(lock); return f(trie_); } @@ -537,8 +539,8 @@ public: } /** Return the adaptor instance - */ - Adaptor const & + */ + Adaptor const& adaptor() const { return adaptor_; @@ -552,8 +554,8 @@ public: return parms_; } - /** Return whether the local node can issue a validation for the given sequence - number + /** Return whether the local node can issue a validation for the given + sequence number @param s The sequence number of the ledger the node wants to validate @return Whether the validation satisfies the invariant, updating the @@ -602,7 +604,7 @@ public: Validation& oldVal = ins.first->second; if (val.signTime() > oldVal.signTime()) { - std::pair old(oldVal.seq(),oldVal.ledgerID()); + std::pair old(oldVal.seq(), oldVal.ledgerID()); adaptor_.onStale(std::move(oldVal)); ins.first->second = val; if (val.trusted()) @@ -691,20 +693,19 @@ public: @param curr The local node's current working ledger @return The sequence and id of the preferred working ledger, - or Seq{0},ID{0} if no trusted validations are available to + or boost::none if no trusted validations are available to determine the preferred ledger. */ - std::pair + boost::optional> getPreferred(Ledger const& curr) { ScopedLock lock{mutex_}; - SpanTip preferred = + boost::optional> preferred = withTrie(lock, [this](LedgerTrie& trie) { return trie.getPreferred(localSeqEnforcer_.largest()); }); - // No trusted validations to determine branch - if (preferred.seq == Seq{0}) + if (!preferred) { // fall back to majority over acquiring ledgers auto it = std::max_element( @@ -722,26 +723,26 @@ public: return std::tie(aSize, aKey.second) < std::tie(bSize, bKey.second); }); - if(it != acquiring_.end()) + if (it != acquiring_.end()) return it->first; - return std::make_pair(preferred.seq, preferred.id); + return boost::none; } // If we are the parent of the preferred ledger, stick with our // current ledger since we might be about to generate it - if (preferred.seq == curr.seq() + Seq{1} && - preferred.ancestor(curr.seq()) == curr.id()) + if (preferred->seq == curr.seq() + Seq{1} && + preferred->ancestor(curr.seq()) == curr.id()) return std::make_pair(curr.seq(), curr.id()); // A ledger ahead of us is preferred regardless of whether it is // a descendant of our working ledger or it is on a different chain - if (preferred.seq > curr.seq()) - return std::make_pair(preferred.seq, preferred.id); + if (preferred->seq > curr.seq()) + return std::make_pair(preferred->seq, preferred->id); // Only switch to earlier or same sequence number // if it is a different chain. - if (curr[preferred.seq] != preferred.id) - return std::make_pair(preferred.seq, preferred.id); + if (curr[preferred->seq] != preferred->id) + return std::make_pair(preferred->seq, preferred->id); // Stick with current ledger return std::make_pair(curr.seq(), curr.id()); @@ -759,22 +760,21 @@ public: ID getPreferred(Ledger const& curr, Seq minValidSeq) { - std::pair preferred = getPreferred(curr); - if(preferred.first >= minValidSeq && preferred.second != ID{0}) - return preferred.second; + boost::optional> preferred = getPreferred(curr); + if (preferred && preferred->first >= minValidSeq) + return preferred->second; return curr.id(); - } - /** Determine the preferred last closed ledger for the next consensus round. - Called before starting the next round of ledger consensus to determine the - preferred working ledger. Uses the dominant peerCount ledger if no + Called before starting the next round of ledger consensus to determine + the preferred working ledger. Uses the dominant peerCount ledger if no trusted validations are available. @param lcl Last closed ledger by this node - @param minSeq Minimum allowed sequence number of the trusted preferred ledger + @param minSeq Minimum allowed sequence number of the trusted preferred + ledger @param peerCounts Map from ledger ids to count of peers with that as the last closed ledger @return The preferred last closed ledger ID @@ -784,15 +784,16 @@ public: */ ID getPreferredLCL( - Ledger const & lcl, + Ledger const& lcl, Seq minSeq, hash_map const& peerCounts) { - std::pair preferred = getPreferred(lcl); + boost::optional> preferred = getPreferred(lcl); - // Trusted validations exist - if (preferred.second != ID{0} && preferred.first > Seq{0}) - return (preferred.first >= minSeq) ? preferred.second : lcl.id(); + // Trusted validations exist, but stick with local preferred ledger if + // preferred is in the past + if (preferred) + return (preferred->first >= minSeq) ? preferred->second : lcl.id(); // Otherwise, rely on peer ledgers auto it = std::max_element( diff --git a/src/test/consensus/LedgerTrie_test.cpp b/src/test/consensus/LedgerTrie_test.cpp index 05abf579e..bfd231b38 100644 --- a/src/test/consensus/LedgerTrie_test.cpp +++ b/src/test/consensus/LedgerTrie_test.cpp @@ -18,9 +18,9 @@ //============================================================================== #include #include +#include #include #include -#include namespace ripple { namespace test { @@ -29,7 +29,6 @@ class LedgerTrie_test : public beast::unit_test::suite { beast::Journal j; - void testInsert() { @@ -141,20 +140,19 @@ class LedgerTrie_test : public beast::unit_test::suite { LedgerTrie 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); - } } @@ -191,7 +189,7 @@ class LedgerTrie_test : public beast::unit_test::suite { LedgerTrie 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"])); @@ -209,7 +207,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 { @@ -288,17 +285,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 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 t; LedgerHistoryHelper h; BEAST_EXPECT(t.tipSupport(h["a"]) == 0); @@ -339,7 +354,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 @@ -348,18 +362,28 @@ class LedgerTrie_test : public beast::unit_test::suite using namespace csf; using Seq = Ledger::Seq; // Empty + { + LedgerTrie t; + BEAST_EXPECT(t.getPreferred(Seq{0}) == boost::none); + BEAST_EXPECT(t.getPreferred(Seq{2}) == boost::none); + } + // Genesis support is NOT empty { LedgerTrie 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 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 { @@ -367,17 +391,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 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 { @@ -386,40 +410,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 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 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 @@ -428,17 +452,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 @@ -446,11 +470,11 @@ class LedgerTrie_test : public beast::unit_test::suite LedgerTrie 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 @@ -458,25 +482,25 @@ class LedgerTrie_test : public beast::unit_test::suite LedgerTrie 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 @@ -497,15 +521,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 @@ -521,11 +545,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 @@ -540,11 +564,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 @@ -559,15 +583,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 @@ -613,22 +634,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; @@ -636,11 +657,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; } } @@ -650,6 +671,7 @@ class LedgerTrie_test : public beast::unit_test::suite { testInsert(); testRemove(); + testEmpty(); testSupport(); testGetPreferred(); testRootRelated(); diff --git a/src/test/consensus/Validations_test.cpp b/src/test/consensus/Validations_test.cpp index 33c6488cf..b49b647bd 100644 --- a/src/test/consensus/Validations_test.cpp +++ b/src/test/consensus/Validations_test.cpp @@ -58,9 +58,7 @@ class Validations_test : public beast::unit_test::suite boost::optional 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; std::vector 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 const expectedKeys = {a.nodeID(), - b.nodeID()}; + hash_set 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 const expectedKeys = {a.nodeID(), - b.nodeID()}; + hash_set 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); }