1#include <test/csf/Validation.h>
2#include <test/unit_test/SuiteJournal.h>
4#include <xrpld/consensus/Validations.h>
6#include <xrpl/basics/tagged_integer.h>
7#include <xrpl/beast/clock/manual_clock.h>
8#include <xrpl/beast/unit_test.h>
29 duration_cast<NetClock::duration>(c.now().time_since_epoch() + 86400s));
120 return validate(ledger.
id(), ledger.
seq(), signOffset, seenOffset,
true);
232 using namespace std::chrono_literals;
236 Ledger const ledgerA = h[
"a"];
237 Ledger ledgerAB = h[
"ab"];
238 Ledger ledgerAZ = h[
"az"];
239 Ledger ledgerABC = h[
"abc"];
240 Ledger const ledgerABCD = h[
"abcd"];
241 Ledger const ledgerABCDE = h[
"abcde"];
256 harness.
clock().advance(1s);
269 harness.
clock().advance(1s);
277 harness.
clock().advance(1s);
284 harness.
clock().advance(2s);
285 auto const valABCDE = n.
validate(ledgerABCDE);
287 harness.
clock().advance(4s);
288 auto const valABCD = n.
validate(ledgerABCD);
333 for (
bool doFull : {
true,
false})
338 auto process = [&](
Ledger& lgr) {
345 harness.
clock().advance(1s);
346 BEAST_EXPECT(ledgerAB.
seq() < ledgerABC.
seq());
367 Ledger const ledgerAB = h[
"ab"];
376 for (Trigger
const& trigger : triggers)
382 trigger(harness.
vals());
390 trigger(harness.
vals());
404 using namespace std::chrono_literals;
408 Ledger const ledgerA = h[
"a"];
409 Ledger const ledgerAB = h[
"ab"];
410 Ledger const ledgerABC = h[
"abc"];
411 Ledger const ledgerAD = h[
"ad"];
427 for (
Ledger const& ledger : {ledgerA, ledgerAB, ledgerABC, ledgerAD})
430 harness.
clock().advance(5s);
450 using namespace std::chrono_literals;
451 testcase(
"Current trusted validations");
454 Ledger const ledgerA = h[
"a"];
455 Ledger const ledgerB = h[
"b"];
456 Ledger const ledgerAC = h[
"ac"];
471 harness.
clock().advance(3s);
473 for (
auto const& node : {a, b})
489 using namespace std::chrono_literals;
493 Ledger const ledgerA = h[
"a"];
494 Ledger const ledgerAC = h[
"ac"];
500 for (
auto const& node : {a, b})
508 harness.
clock().advance(3s);
514 for (
auto const& node : {a, b})
531 using namespace std::chrono_literals;
557 auto sorted = [](
auto vec) {
561 auto compare = [&]() {
562 for (
auto& it : trustedValidations)
564 auto const&
id = it.first.first;
565 auto const&
seq = it.first.second;
566 auto const& expectedValidations = it.second;
571 sorted(expectedValidations));
575 expectedFees.
reserve(expectedValidations.size());
576 for (
auto const& val : expectedValidations)
578 expectedFees.
push_back(val.loadFee().value_or(baseFee));
581 BEAST_EXPECT(sorted(harness.
vals().
fees(
id, baseFee)) == sorted(expectedFees));
586 Ledger const ledgerA = h[
"a"];
587 Ledger const ledgerB = h[
"b"];
588 Ledger const ledgerAC = h[
"ac"];
594 for (
auto const& node : {a, b, c})
596 auto const val = node.validate(ledgerA);
599 trustedValidations[{val.ledgerID(), val.seq()}].emplace_back(val);
603 auto const val = d.validate(ledgerB);
605 trustedValidations[{val.ledgerID(), val.seq()}].emplace_back(val);
612 harness.
clock().advance(5s);
614 for (
auto const& node : {a, b, c})
616 auto const val = node.validate(ledgerAC);
619 trustedValidations[{val.ledgerID(), val.seq()}].emplace_back(val);
647 Ledger const ledgerA = h[
"a"];
657 Ledger const ledgerB = h[
"ab"];
669 for (
int i = 0; i < loops; ++i)
677 Ledger const ledgerC = h[
"abc"];
690 using namespace std::chrono_literals;
700 Ledger const ledgerA = h[
"a"];
701 Ledger const ledgerAB = h[
"ab"];
704 for (
auto const& node : {trustedNode1, trustedNode2, notTrustedNode})
706 auto const val = node.validate(ledgerA);
708 expected.
emplace(node.nodeID(), val);
713 harness.
clock().advance(1s);
714 auto newVal = trustedNode1.
validate(ledgerAB);
716 expected.
find(trustedNode1.
nodeID())->second = newVal;
722 using namespace std::chrono_literals;
734 Ledger const ledgerA = h[
"a"];
735 Ledger const ledgerB = h[
"b"];
736 Ledger const ledgerAC = h[
"ac"];
737 Ledger const ledgerACD = h[
"acd"];
758 BEAST_EXPECT(ledgerB.
id() > ledgerA.
id());
767 harness.
clock().advance(5s);
770 for (
auto const& node : {trustedNode1, trustedNode2, notTrustedNode, trustedNode3})
780 harness.
clock().advance(5s);
781 for (
auto const& node : {trustedNode1, trustedNode2, notTrustedNode, trustedNode3})
783 for (
auto const& ledger : {ledgerA, ledgerB, ledgerACD})
790 using namespace std::chrono_literals;
797 Ledger const ledgerA = h[
"a"];
798 Ledger const ledgerB = h[
"b"];
799 Ledger const ledgerC = h[
"c"];
809 ++peerCounts[ledgerB.
id()];
814 ++peerCounts[ledgerC.
id()];
816 BEAST_EXPECT(ledgerC.
id() > ledgerB.
id());
820 peerCounts[ledgerC.
id()] += 1000;
836 using namespace std::chrono_literals;
837 testcase(
"Acquire validated ledger");
865 Ledger const ledgerAB = h[
"ab"];
870 harness.
clock().advance(5s);
887 harness.
clock().advance(5s);
888 Ledger const ledgerABCDE = h[
"abcde"];
904 Ledger const ledgerA = h[
"a"];
925 BEAST_EXPECT(enforcer(clock.now(), Seq{1}, p));
926 BEAST_EXPECT(enforcer(clock.now(), Seq{10}, p));
927 BEAST_EXPECT(!enforcer(clock.now(), Seq{5}, p));
928 BEAST_EXPECT(!enforcer(clock.now(), Seq{9}, p));
930 BEAST_EXPECT(!enforcer(clock.now(), Seq{1}, p));
932 BEAST_EXPECT(enforcer(clock.now(), Seq{1}, p));
941 auto checker = [
this](
946 trustedVals.empty() ? this->
genesisLedger.
id() : trustedVals[0].ledgerID();
953 if (trustedVals.empty())
959 BEAST_EXPECT(vals.
getPreferred(this->genesisLedger)->second == testID);
970 Ledger const ledgerAB = h[
"ab"];
976 checker(harness.
vals(), listed, trustedVals);
980 checker(harness.
vals(), listed, trustedVals);
989 Ledger const ledgerAB = h[
"ab"];
995 checker(harness.
vals(), listed, trustedVals);
997 trustedVals.push_back(v);
999 checker(harness.
vals(), listed, trustedVals);
1012 auto& vals = harness.
vals();
1013 BEAST_EXPECT(vals.currentTrusted() == trustedVals);
1019 trustedVals.clear();
1023 BEAST_EXPECT(vals.currentTrusted() == trustedVals);
Abstract interface to a clock.
Manual clock implementation.
testcase_t testcase
Memberspace for declaring test cases.
std::chrono::time_point< NetClock > time_point
Enforce validation increasing sequence requirement.
Maintains current and recent ledger validations.
ID getPreferredLCL(Ledger const &lcl, Seq minSeq, hash_map< ID, std::uint32_t > const &peerCounts)
Determine the preferred last closed ledger for the next consensus round.
std::size_t getNodesAfter(Ledger const &ledger, ID const &ledgerID)
Count the number of current trusted validators working on a ledger after the specified one.
auto getCurrentNodeIDs() -> hash_set< NodeID >
Get the set of node ids associated with current validations.
std::size_t numTrustedForLedger(ID const &ledgerID)
Count the number of trusted full validations for the given ledger.
std::vector< WrappedValidationType > getTrustedForLedger(ID const &ledgerID, Seq const &seq)
Get trusted full validations for a specific ledger.
ValStatus add(NodeID const &nodeID, Validation const &val)
Add a new validation.
void trustChanged(hash_set< NodeID > const &added, hash_set< NodeID > const &removed)
Update trust status of validations.
std::optional< std::pair< Seq, ID > > getPreferred(Ledger const &curr)
Return the sequence number and ID of the preferred working ledger.
std::vector< WrappedValidationType > currentTrusted()
Get the currently trusted full validations.
void setSeqToKeep(Seq const &low, Seq const &high)
Set the range [low, high) of validations to keep from expire.
void expire(beast::Journal &j)
Expire old validation sets.
std::vector< std::uint32_t > fees(ID const &ledgerID, std::uint32_t baseFee)
Returns fees reported by trusted full validators in the given ledger.
Oracle maintaining unique ledgers for a simulation.
std::optional< Ledger > lookup(Ledger::ID const &id) const
Find the ledger with the given ID.
A ledger is a set of observed transactions and a sequence number identifying the ledger.
tagged_integer< std::uint32_t, IdTag > ID
tagged_integer< std::uint32_t, SeqTag > Seq
Validation of a specific ledger by a specific Peer.
PeerID const & nodeID() const
Ledger::ID ledgerID() const
NetClock::time_point now() const
Adaptor(clock_type &c, LedgerOracle &o)
std::optional< Ledger > acquire(Ledger::ID const &id)
std::optional< std::uint32_t > loadFee_
NetClock::time_point now() const
Validation validate(Ledger::ID id, Ledger::Seq seq, NetClock::duration signOffset, NetClock::duration seenOffset, bool full) const
PeerKey masterKey() const
Node(PeerID nodeID, clock_type const &c)
Validation validate(Ledger ledger) const
void setLoadFee(std::uint32_t fee)
Validation partial(Ledger ledger) const
Validation validate(Ledger ledger, NetClock::duration signOffset, NetClock::duration seenOffset) const
ValStatus add(Validation const &v)
ValidationParms parms() const
beast::manual_clock< std::chrono::steady_clock > clock_
TestHarness(LedgerOracle &o)
void testGetCurrentPublicKeys()
static NetClock::time_point toNetClock(clock_type const &c)
void testAcquireValidatedLedger()
beast::abstract_clock< std::chrono::steady_clock > const clock_type
void testGetPreferredLedger()
void testGetPreferredLCL()
Ledger const genesisLedger
void testCurrentTrusted()
void run() override
Runs the suite.
void testTrustedByLedgerFunctions()
void testNumTrustedForLedger()
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
ValStatus
Status of validation we received.
@ badSeq
A validation violates the increasing seq requirement.
@ stale
Not current or was older than current from this node.
@ current
This was a new validation and was added.
@ conflicting
Multiple validations by a validator for different ledgers.
Timing parameters to control validation staleness and expiration.
std::chrono::seconds validationFRESHNESS
How long we consider a validation fresh.
std::chrono::seconds validationSET_EXPIRES
Duration a set of validations for a given ledger hash remain valid.
std::chrono::seconds validationCURRENT_EARLY
Duration pre-close in which validations are acceptable.
std::chrono::seconds validationCURRENT_LOCAL
Duration a validation remains current after first observed.
std::chrono::seconds validationCURRENT_WALL
The number of seconds a validation remains current after its ledger's close time.
Helper for writing unit tests with controlled ledger histories.
Set the sequence number on a JTx.