1#include <test/csf/Validation.h>
2#include <test/csf/ledgers.h>
3#include <test/unit_test/SuiteJournal.h>
5#include <xrpld/consensus/Validations.h>
7#include <xrpl/basics/UnorderedContainers.h>
8#include <xrpl/basics/chrono.h>
9#include <xrpl/basics/tagged_integer.h>
10#include <xrpl/beast/clock/abstract_clock.h>
11#include <xrpl/beast/clock/manual_clock.h>
12#include <xrpl/beast/unit_test/suite.h>
128 return validate(ledger.
id(), ledger.
seq(), signOffset, seenOffset,
true);
240 using namespace std::chrono_literals;
244 Ledger const ledgerA = h[
"a"];
245 Ledger ledgerAB = h[
"ab"];
246 Ledger ledgerAZ = h[
"az"];
247 Ledger ledgerABC = h[
"abc"];
248 Ledger const ledgerABCD = h[
"abcd"];
249 Ledger const ledgerABCDE = h[
"abcde"];
264 harness.
clock().advance(1s);
277 harness.
clock().advance(1s);
285 harness.
clock().advance(1s);
292 harness.
clock().advance(2s);
293 auto const valABCDE = n.
validate(ledgerABCDE);
295 harness.
clock().advance(4s);
296 auto const valABCD = n.
validate(ledgerABCD);
341 for (
bool doFull : {
true,
false})
346 auto process = [&](
Ledger& lgr) {
353 harness.
clock().advance(1s);
354 BEAST_EXPECT(ledgerAB.
seq() < ledgerABC.
seq());
375 Ledger const ledgerAB = h[
"ab"];
384 for (Trigger
const& trigger : triggers)
390 trigger(harness.
vals());
398 trigger(harness.
vals());
412 using namespace std::chrono_literals;
416 Ledger const ledgerA = h[
"a"];
417 Ledger const ledgerAB = h[
"ab"];
418 Ledger const ledgerABC = h[
"abc"];
419 Ledger const ledgerAD = h[
"ad"];
435 for (
Ledger const& ledger : {ledgerA, ledgerAB, ledgerABC, ledgerAD})
438 harness.
clock().advance(5s);
458 using namespace std::chrono_literals;
459 testcase(
"Current trusted validations");
462 Ledger const ledgerA = h[
"a"];
463 Ledger const ledgerB = h[
"b"];
464 Ledger const ledgerAC = h[
"ac"];
479 harness.
clock().advance(3s);
481 for (
auto const& node : {a, b})
497 using namespace std::chrono_literals;
501 Ledger const ledgerA = h[
"a"];
502 Ledger const ledgerAC = h[
"ac"];
508 for (
auto const& node : {a, b})
516 harness.
clock().advance(3s);
522 for (
auto const& node : {a, b})
539 using namespace std::chrono_literals;
565 auto sorted = [](
auto vec) {
569 auto compare = [&]() {
570 for (
auto& it : trustedValidations)
572 auto const&
id = it.first.first;
573 auto const& seq = it.first.second;
574 auto const& expectedValidations = it.second;
579 sorted(expectedValidations));
583 expectedFees.
reserve(expectedValidations.size());
584 for (
auto const& val : expectedValidations)
586 expectedFees.
push_back(val.loadFee().value_or(baseFee));
589 BEAST_EXPECT(sorted(harness.
vals().
fees(
id, baseFee)) == sorted(expectedFees));
594 Ledger const ledgerA = h[
"a"];
595 Ledger const ledgerB = h[
"b"];
596 Ledger const ledgerAC = h[
"ac"];
602 for (
auto const& node : {a, b, c})
604 auto const val = node.validate(ledgerA);
607 trustedValidations[{val.ledgerID(), val.seq()}].emplace_back(val);
611 auto const val = d.validate(ledgerB);
613 trustedValidations[{val.ledgerID(), val.seq()}].emplace_back(val);
620 harness.
clock().advance(5s);
622 for (
auto const& node : {a, b, c})
624 auto const val = node.validate(ledgerAC);
627 trustedValidations[{val.ledgerID(), val.seq()}].emplace_back(val);
655 Ledger const ledgerA = h[
"a"];
665 Ledger const ledgerB = h[
"ab"];
677 for (
int i = 0; i < loops; ++i)
685 Ledger const ledgerC = h[
"abc"];
698 using namespace std::chrono_literals;
708 Ledger const ledgerA = h[
"a"];
709 Ledger const ledgerAB = h[
"ab"];
712 for (
auto const& node : {trustedNode1, trustedNode2, notTrustedNode})
714 auto const val = node.validate(ledgerA);
716 expected.
emplace(node.nodeID(), val);
721 harness.
clock().advance(1s);
722 auto newVal = trustedNode1.
validate(ledgerAB);
724 expected.
find(trustedNode1.
nodeID())->second = newVal;
730 using namespace std::chrono_literals;
742 Ledger const ledgerA = h[
"a"];
743 Ledger const ledgerB = h[
"b"];
744 Ledger const ledgerAC = h[
"ac"];
745 Ledger const ledgerACD = h[
"acd"];
766 BEAST_EXPECT(ledgerB.
id() > ledgerA.
id());
775 harness.
clock().advance(5s);
778 for (
auto const& node : {trustedNode1, trustedNode2, notTrustedNode, trustedNode3})
788 harness.
clock().advance(5s);
789 for (
auto const& node : {trustedNode1, trustedNode2, notTrustedNode, trustedNode3})
791 for (
auto const& ledger : {ledgerA, ledgerB, ledgerACD})
798 using namespace std::chrono_literals;
805 Ledger const ledgerA = h[
"a"];
806 Ledger const ledgerB = h[
"b"];
807 Ledger const ledgerC = h[
"c"];
817 ++peerCounts[ledgerB.
id()];
822 ++peerCounts[ledgerC.
id()];
824 BEAST_EXPECT(ledgerC.
id() > ledgerB.
id());
828 peerCounts[ledgerC.
id()] += 1000;
844 using namespace std::chrono_literals;
845 testcase(
"Acquire validated ledger");
873 Ledger const ledgerAB = h[
"ab"];
878 harness.
clock().advance(5s);
895 harness.
clock().advance(5s);
896 Ledger const ledgerABCDE = h[
"abcde"];
912 Ledger const ledgerA = h[
"a"];
933 BEAST_EXPECT(enforcer(
clock.now(),
Seq{1}, p));
934 BEAST_EXPECT(enforcer(
clock.now(),
Seq{10}, p));
935 BEAST_EXPECT(!enforcer(
clock.now(),
Seq{5}, p));
936 BEAST_EXPECT(!enforcer(
clock.now(),
Seq{9}, p));
938 BEAST_EXPECT(!enforcer(
clock.now(),
Seq{1}, p));
940 BEAST_EXPECT(enforcer(
clock.now(),
Seq{1}, p));
949 auto checker = [
this](
954 trustedVals.empty() ? this->genesisLedger_.
id() : trustedVals[0].ledgerID();
956 trustedVals.empty() ? this->genesisLedger_.
seq() : trustedVals[0].seq();
962 if (trustedVals.empty())
964 BEAST_EXPECT(vals.
getPreferred(this->genesisLedger_) == std::nullopt);
968 BEAST_EXPECT(vals.
getPreferred(this->genesisLedger_)->second == testID);
979 Ledger const ledgerAB = h[
"ab"];
985 checker(harness.
vals(), listed, trustedVals);
989 checker(harness.
vals(), listed, trustedVals);
998 Ledger const ledgerAB = h[
"ab"];
1004 checker(harness.
vals(), listed, trustedVals);
1006 trustedVals.push_back(v);
1008 checker(harness.
vals(), listed, trustedVals);
1021 auto& vals = harness.
vals();
1022 BEAST_EXPECT(vals.currentTrusted() == trustedVals);
1028 trustedVals.clear();
1032 BEAST_EXPECT(vals.currentTrusted() == trustedVals);
Abstract interface to a clock.
virtual time_point now() const =0
Returns the current time.
Manual clock implementation.
TestcaseT testcase
Memberspace for declaring test cases.
std::chrono::time_point< NetClock > time_point
std::chrono::duration< rep, period > duration
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.
void expire(beast::Journal const &j)
Expire old validation sets.
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.
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.
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.
A ledger is a set of observed transactions and a sequence number identifying the ledger.
TaggedInteger< std::uint32_t, IdTag > ID
TaggedInteger< std::uint32_t, SeqTag > Seq
Validation of a specific ledger by a specific Peer.
PeerID const & nodeID() const
Ledger::ID ledgerID() const
csf::Validation Validation
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)
beast::ManualClock< std::chrono::steady_clock > clock_
ValidationParms parms() const
TestHarness(LedgerOracle &o)
void testGetCurrentPublicKeys()
static NetClock::time_point toNetClock(clock_type const &c)
void testAcquireValidatedLedger()
void testGetPreferredLedger()
beast::AbstractClock< std::chrono::steady_clock > const clock_type
void testGetPreferredLCL()
Ledger const genesisLedger_
void testCurrentTrusted()
void run() override
Runs the suite.
Validations< Adaptor > TestValidations
void testTrustedByLedgerFunctions()
void testNumTrustedForLedger()
T duration_cast(T... args)
BEAST_DEFINE_TESTSUITE(Validations, consensus, xrpl)
TaggedInteger< std::uint32_t, PeerIDTag > PeerID
std::pair< PeerID, std::uint32_t > PeerKey
The current key of a peer.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::unordered_set< Value, Hash, Pred, Allocator > hash_set
ValStatus
Status of validation we received.
@ Current
This was a new validation and was added.
@ BadSeq
A validation violates the increasing seq requirement.
@ Conflicting
Multiple validations by a validator for different ledgers.
@ Stale
Not current or was older than current from this node.
std::unordered_map< Key, Value, Hash, Pred, Allocator > hash_map
Timing parameters to control validation staleness and expiration.
std::chrono::seconds validationCurrentEarly
Duration pre-close in which validations are acceptable.
std::chrono::seconds validationCurrentLocal
Duration a validation remains current after first observed.
std::chrono::seconds validationSetExpires
Duration a set of validations for a given ledger hash remain valid.
std::chrono::seconds validationFRESHNESS
How long we consider a validation fresh.
std::chrono::seconds validationCurrentWall
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.