xrpld
Loading...
Searching...
No Matches
ledgers.cpp
1#include <test/csf/ledgers.h>
2
3#include <test/csf/Tx.h>
4
5#include <xrpl/basics/chrono.h>
6#include <xrpl/json/json_value.h>
7#include <xrpl/ledger/LedgerTiming.h>
8
9#include <algorithm>
10#include <chrono>
11#include <cstddef>
12#include <optional>
13#include <set>
14#include <vector>
15
16namespace xrpl::test::csf {
17
19
20json::Value
22{
24 res["id"] = static_cast<ID::value_type>(id());
25 res["seq"] = static_cast<Seq::value_type>(seq());
26 return res;
27}
28
29bool
30Ledger::isAncestor(Ledger const& ancestor) const
31{
32 if (ancestor.seq() < seq())
33 return operator[](ancestor.seq()) == ancestor.id();
34 return false;
35}
36
39{
40 if (s > seq())
41 return {};
42 if (s == seq())
43 return id();
44 return instance_->ancestors[static_cast<Seq::value_type>(s)];
45}
46
48mismatch(Ledger const& a, Ledger const& b)
49{
50 using Seq = Ledger::Seq;
51
52 // end is 1 past end of range
53 Seq start{0};
54 Seq const end = std::min(a.seq() + Seq{1}, b.seq() + Seq{1});
55
56 // Find mismatch in [start,end)
57 // Binary search
58 Seq count = end - start;
59 while (count > Seq{0})
60 {
61 Seq const step = count / Seq{2};
62 Seq curr = start + step;
63 if (a[curr] == b[curr])
64 {
65 // go to second half
66 start = ++curr;
67 count -= step + Seq{1};
68 }
69 else
70 {
71 count = step;
72 }
73 }
74 return start;
75}
76
81
84{
85 return Ledger::ID{static_cast<Ledger::ID::value_type>(instances_.size())};
86}
87
90 Ledger const& parent,
91 TxSetType const& txs,
92 NetClock::duration closeTimeResolution,
93 NetClock::time_point const& consensusCloseTime)
94{
95 using namespace std::chrono_literals;
96 Ledger::Instance next(*parent.instance_);
97 next.txs.insert(txs.begin(), txs.end());
98 next.seq = parent.seq() + Ledger::Seq{1};
99 next.closeTimeResolution = closeTimeResolution;
100 next.closeTimeAgree = consensusCloseTime != NetClock::time_point{};
101 if (next.closeTimeAgree)
102 {
103 next.closeTime = effCloseTime(consensusCloseTime, closeTimeResolution, parent.closeTime());
104 }
105 else
106 {
107 next.closeTime = parent.closeTime() + 1s;
108 }
109
110 next.parentCloseTime = parent.closeTime();
111 next.parentID = parent.id();
112 next.ancestors.push_back(parent.id());
113
114 auto it = instances_.left.find(next);
115 if (it == instances_.left.end())
116 {
117 using Entry = InstanceMap::left_value_type;
118 it = instances_.left.insert(Entry{next, nextID()}).first;
119 }
120 return Ledger(it->second, &(it->first));
121}
122
125{
126 auto const it = instances_.right.find(id);
127 if (it != instances_.right.end())
128 {
129 return Ledger(it->first, &(it->second));
130 }
131 return std::nullopt;
132}
133
136{
137 // Tips always maintains the Ledgers with largest sequence number
138 // along all known chains.
140 tips.reserve(ledgers.size());
141
142 for (Ledger const& ledger : ledgers)
143 {
144 // Three options,
145 // 1. ledger is on a new branch
146 // 2. ledger is on a branch that we have seen tip for
147 // 3. ledger is the new tip for a branch
148 bool found = false;
149 for (auto idx = 0; idx < tips.size() && !found; ++idx)
150 {
151 bool const idxEarlier = tips[idx].seq() < ledger.seq();
152 Ledger const& earlier = idxEarlier ? tips[idx] : ledger;
153 Ledger const& later = idxEarlier ? ledger : tips[idx];
154 if (later.isAncestor(earlier))
155 {
156 tips[idx] = later;
157 found = true;
158 }
159 }
160
161 if (!found)
162 tips.push_back(ledger);
163 }
164 // The size of tips is the number of branches
165 return tips.size();
166}
167} // namespace xrpl::test::csf
Represents a JSON value.
Definition json_value.h:130
std::chrono::time_point< NetClock > time_point
Definition chrono.h:46
std::chrono::duration< rep, period > duration
Definition chrono.h:45
Ledger::ID nextID() const
Definition ledgers.cpp:83
InstanceMap::value_type InstanceEntry
Definition ledgers.h:231
Ledger accept(Ledger const &curr, TxSetType const &txs, NetClock::duration closeTimeResolution, NetClock::time_point const &consensusCloseTime)
Accept the given txs and generate a new ledger.
Definition ledgers.cpp:89
std::optional< Ledger > lookup(Ledger::ID const &id) const
Find the ledger with the given ID.
Definition ledgers.cpp:124
static std::size_t branches(std::set< Ledger > const &ledgers)
Determine the number of distinct branches for the set of ledgers.
Definition ledgers.cpp:135
A ledger is a set of observed transactions and a sequence number identifying the ledger.
Definition ledgers.h:41
Instance const * instance_
Definition ledgers.h:221
TaggedInteger< std::uint32_t, IdTag > ID
Definition ledgers.h:49
TaggedInteger< std::uint32_t, SeqTag > Seq
Definition ledgers.h:46
bool isAncestor(Ledger const &ancestor) const
Determine whether ancestor is really an ancestor of this ledger.
Definition ledgers.cpp:30
static Instance const kGenesis
Definition ledgers.h:131
ID operator[](Seq seq) const
Return the id of the ancestor with the given seq (if exists/known).
Definition ledgers.cpp:38
Ledger(ID id, Instance const *i)
Definition ledgers.h:133
NetClock::time_point closeTime() const
Definition ledgers.h:173
json::Value getJson() const
Definition ledgers.cpp:21
T min(T... args)
@ Object
object value (collection of name/value pairs).
Definition json_value.h:26
boost::container::flat_set< Tx > TxSetType
Definition Tx.h:58
Ledger::Seq mismatch(Ledger const &a, Ledger const &b)
Definition ledgers.cpp:48
std::chrono::time_point< Clock, Duration > effCloseTime(std::chrono::time_point< Clock, Duration > closeTime, std::chrono::duration< Rep, Period > resolution, std::chrono::time_point< Clock, Duration > priorCloseTime)
Calculate the effective ledger close time.
T push_back(T... args)
T reserve(T... args)
T size(T... args)