From a39638568b5096c29afd922913e43b70026b2a93 Mon Sep 17 00:00:00 2001 From: Ed Hennis Date: Fri, 14 Feb 2025 18:47:52 -0500 Subject: [PATCH] [WIP] Checkpoint --- src/test/consensus/Consensus_test.cpp | 65 ++++++++++++++++++++++++++- src/test/csf/Tx.h | 2 +- src/xrpld/consensus/Consensus.h | 2 +- 3 files changed, 65 insertions(+), 4 deletions(-) diff --git a/src/test/consensus/Consensus_test.cpp b/src/test/consensus/Consensus_test.cpp index 36b3ca8508f..59bdf446f66 100644 --- a/src/test/consensus/Consensus_test.cpp +++ b/src/test/consensus/Consensus_test.cpp @@ -1119,13 +1119,13 @@ class Consensus_test : public beast::unit_test::suite } void - testDisputes() + testDisjointNetwork() { // WIP: Try to create conditions where messaging is unreliable and all // peers have different initial proposals using namespace csf; using namespace std::chrono; - testcase("disputes"); + testcase("disjoint network"); std::uint32_t const numPeers = 35; @@ -1210,6 +1210,66 @@ class Consensus_test : public beast::unit_test::suite } } + void + testDisputes() + { + testcase("disputes"); + + using namespace csf; + + // Test dispute objects directly + using Dispute = DisputedTx; + + Tx const tx{99}; + int const numPeers = 100; + ConsensusParms p; + std::size_t peersUnchanged = 0; + + // Three cases: + // 1 proposing, initial vote yes + // 2 proposing, initial vote no + // 3 not proposing, initial vote doesn't matter after the first update, use yes + { + bool const proposing = true; + bool const myVote = true; + + Dispute d{tx.id(), myVote, numPeers, journal_}; + BEAST_EXPECT(d.ID() == 99); + + // Create an even split in the peer votes + for (int i = 0; i < numPeers; ++i) + { + BEAST_EXPECT(d.setVote(PeerID(i), i < 50)); + } + // Switch the middle vote to match mine + BEAST_EXPECT(d.setVote(myVote ? PeerID(50) : PeerID(49), myVote)); + + // no changes yet + BEAST_EXPECT(d.getOurVote() == myVote); + BEAST_EXPECT(!d.stalled(p, proposing, peersUnchanged)); + + // I'm in the majority, my vote should not change + BEAST_EXPECT(d.updateVote(5, proposing, p) != proposing); + BEAST_EXPECT(d.updateVote(10, proposing, p) != proposing); + + // Right now, the vote is 51%. The requirement is about to jump to 65% + bool changed = d.updateVote(55, proposing, p); + BEAST_EXPECT(changed == !proposing || myVote); + BEAST_EXPECT(!changed || d.getOurVote() != myVote); + // 16 validators change their vote to match my original vote + for (int i = 0; i < 16; ++i) + { + // If I was voting yes, change no's from the end + auto p =myVote ? PeerID(numPeers - i - 1) : PeerID(i); + BEAST_EXPECT(d.setVote(p, myVote)); + } + // The vote should now be 66% + changed = d.updateVote(60, proposing, p); + BEAST_EXPECT(changed == proposing); + BEAST_EXPECT(!changed || d.getOurVote() == myVote); + } + } + void run() override { @@ -1226,6 +1286,7 @@ class Consensus_test : public beast::unit_test::suite testHubNetwork(); testPreferredByBranch(); testPauseForLaggards(); + testDisjointNetwork(); testDisputes(); } }; diff --git a/src/test/csf/Tx.h b/src/test/csf/Tx.h index f87f382167d..7037c55aa92 100644 --- a/src/test/csf/Tx.h +++ b/src/test/csf/Tx.h @@ -48,7 +48,7 @@ class Tx { } - ID + ID const& id() const { return id_; diff --git a/src/xrpld/consensus/Consensus.h b/src/xrpld/consensus/Consensus.h index c72dd449702..74de1f90a43 100644 --- a/src/xrpld/consensus/Consensus.h +++ b/src/xrpld/consensus/Consensus.h @@ -1595,7 +1595,7 @@ Consensus::haveConsensus() << ", disagree=" << disagree; ConsensusParms const& parms = adaptor_.parms(); - // Stallling is BAD + // Stalling is BAD bool stalled = haveCloseTimeConsensus_ && std::all_of(result_->disputes.begin(), result_->disputes.end(),