rippled
Loading...
Searching...
No Matches
ledgers.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012-2017 Ripple Labs Inc
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <test/csf/ledgers.h>
21
22#include <algorithm>
23
24namespace ripple {
25namespace test {
26namespace csf {
27
28Ledger::Instance const Ledger::genesis;
29
32{
34 res["id"] = static_cast<ID::value_type>(id());
35 res["seq"] = static_cast<Seq::value_type>(seq());
36 return res;
37}
38
39bool
40Ledger::isAncestor(Ledger const& ancestor) const
41{
42 if (ancestor.seq() < seq())
43 return operator[](ancestor.seq()) == ancestor.id();
44 return false;
45}
46
49{
50 if (s > seq())
51 return {};
52 if (s == seq())
53 return id();
54 return instance_->ancestors[static_cast<Seq::value_type>(s)];
55}
56
58mismatch(Ledger const& a, Ledger const& b)
59{
60 using Seq = Ledger::Seq;
61
62 // end is 1 past end of range
63 Seq start{0};
64 Seq end = std::min(a.seq() + Seq{1}, b.seq() + Seq{1});
65
66 // Find mismatch in [start,end)
67 // Binary search
68 Seq count = end - start;
69 while (count > Seq{0})
70 {
71 Seq step = count / Seq{2};
72 Seq curr = start + step;
73 if (a[curr] == b[curr])
74 {
75 // go to second half
76 start = ++curr;
77 count -= step + Seq{1};
78 }
79 else
80 count = step;
81 }
82 return start;
83}
84
89
92{
93 return Ledger::ID{static_cast<Ledger::ID::value_type>(instances_.size())};
94}
95
98 Ledger const& parent,
99 TxSetType const& txs,
100 NetClock::duration closeTimeResolution,
101 NetClock::time_point const& consensusCloseTime)
102{
103 using namespace std::chrono_literals;
104 Ledger::Instance next(*parent.instance_);
105 next.txs.insert(txs.begin(), txs.end());
106 next.seq = parent.seq() + Ledger::Seq{1};
107 next.closeTimeResolution = closeTimeResolution;
108 next.closeTimeAgree = consensusCloseTime != NetClock::time_point{};
109 if (next.closeTimeAgree)
110 next.closeTime = effCloseTime(
111 consensusCloseTime, closeTimeResolution, parent.closeTime());
112 else
113 next.closeTime = parent.closeTime() + 1s;
114
115 next.parentCloseTime = parent.closeTime();
116 next.parentID = parent.id();
117 next.ancestors.push_back(parent.id());
118
119 auto it = instances_.left.find(next);
120 if (it == instances_.left.end())
121 {
122 using Entry = InstanceMap::left_value_type;
123 it = instances_.left.insert(Entry{next, nextID()}).first;
124 }
125 return Ledger(it->second, &(it->first));
126}
127
130{
131 auto const it = instances_.right.find(id);
132 if (it != instances_.right.end())
133 {
134 return Ledger(it->first, &(it->second));
135 }
136 return std::nullopt;
137}
138
141{
142 // Tips always maintains the Ledgers with largest sequence number
143 // along all known chains.
145 tips.reserve(ledgers.size());
146
147 for (Ledger const& ledger : ledgers)
148 {
149 // Three options,
150 // 1. ledger is on a new branch
151 // 2. ledger is on a branch that we have seen tip for
152 // 3. ledger is the new tip for a branch
153 bool found = false;
154 for (auto idx = 0; idx < tips.size() && !found; ++idx)
155 {
156 bool const idxEarlier = tips[idx].seq() < ledger.seq();
157 Ledger const& earlier = idxEarlier ? tips[idx] : ledger;
158 Ledger const& later = idxEarlier ? ledger : tips[idx];
159 if (later.isAncestor(earlier))
160 {
161 tips[idx] = later;
162 found = true;
163 }
164 }
165
166 if (!found)
167 tips.push_back(ledger);
168 }
169 // The size of tips is the number of branches
170 return tips.size();
171}
172} // namespace csf
173} // namespace test
174} // namespace ripple
Represents a JSON value.
Definition json_value.h:149
InstanceMap::value_type InstanceEntry
Definition ledgers.h:254
Ledger::ID nextID() const
Definition ledgers.cpp:91
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:97
std::optional< Ledger > lookup(Ledger::ID const &id) const
Find the ledger with the given ID.
Definition ledgers.cpp:129
std::size_t branches(std::set< Ledger > const &ledgers) const
Determine the number of distinct branches for the set of ledgers.
Definition ledgers.cpp:140
A ledger is a set of observed transactions and a sequence number identifying the ledger.
Definition ledgers.h:64
static Instance const genesis
Definition ledgers.h:154
NetClock::time_point closeTime() const
Definition ledgers.h:196
Instance const * instance_
Definition ledgers.h:244
Json::Value getJson() const
Definition ledgers.cpp:31
bool isAncestor(Ledger const &ancestor) const
Determine whether ancestor is really an ancestor of this ledger.
Definition ledgers.cpp:40
ID operator[](Seq seq) const
Return the id of the ancestor with the given seq (if exists/known)
Definition ledgers.cpp:48
tagged_integer< std::uint32_t, SeqTag > Seq
Definition ledgers.h:69
T is_same_v
T min(T... args)
@ objectValue
object value (collection of name/value pairs).
Definition json_value.h:45
boost::container::flat_set< Tx > TxSetType
Definition Tx.h:79
Ledger::Seq mismatch(Ledger const &a, Ledger const &b)
Definition ledgers.cpp:58
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
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)
std::vector< Ledger::ID > ancestors
IDs of this ledgers ancestors.
Definition ledgers.h:111
Set the sequence number on a JTx.
Definition seq.h:34