rippled
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 #include <algorithm>
20 #include <test/csf/ledgers.h>
21 
22 #include <sstream>
23 
24 namespace ripple {
25 namespace test {
26 namespace csf {
27 
28 Ledger::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 
39 bool
40 Ledger::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 
58 mismatch(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 
86 {
88 }
89 
92 {
93  return Ledger::ID{static_cast<Ledger::ID::value_type>(instances_.size())};
94 }
95 
96 Ledger
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.
144  std::vector<Ledger> tips;
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
ripple::test::csf::Ledger::getJson
Json::Value getJson() const
Definition: ledgers.cpp:31
sstream
ripple::test::csf::LedgerOracle::InstanceEntry
InstanceMap::value_type InstanceEntry
Definition: ledgers.h:249
ripple::test::csf::TxSetType
boost::container::flat_set< Tx > TxSetType
Definition: Tx.h:73
ripple::test::csf::LedgerOracle::nextID
Ledger::ID nextID() const
Definition: ledgers.cpp:91
std::vector::reserve
T reserve(T... args)
ripple::test::csf::mismatch
Ledger::Seq mismatch(Ledger const &a, Ledger const &b)
Definition: ledgers.cpp:58
ripple::test::csf::LedgerOracle::accept
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::vector
STL class.
std::set::size
T size(T... args)
ripple::test::csf::Ledger::Instance
Definition: ledgers.h:76
std::chrono::duration
ripple::test::csf::Ledger::Instance::ancestors
std::vector< Ledger::ID > ancestors
IDs of this ledgers ancestors.
Definition: ledgers.h:106
ripple::test::csf::Ledger
A ledger is a set of observed transactions and a sequence number identifying the ledger.
Definition: ledgers.h:58
ripple::test::csf::Ledger::seq
Seq seq() const
Definition: ledgers.h:173
ripple::test::csf::LedgerOracle::LedgerOracle
LedgerOracle()
Definition: ledgers.cpp:85
ripple::test::csf::LedgerOracle::instances_
InstanceMap instances_
Definition: ledgers.h:252
algorithm
std::vector::push_back
T push_back(T... args)
ripple::test::csf::LedgerOracle::lookup
std::optional< Ledger > lookup(Ledger::ID const &id) const
Find the ledger with the given ID.
Definition: ledgers.cpp:129
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:43
ripple::test::csf::Ledger::operator[]
ID operator[](Seq seq) const
Return the id of the ancestor with the given seq (if exists/known)
Definition: ledgers.cpp:48
std::chrono::time_point
std::uint32_t
std::min
T min(T... args)
ripple::test::csf::Ledger::closeTime
NetClock::time_point closeTime() const
Definition: ledgers.h:191
ripple::test::jtx::seq
Set the sequence number on a JTx.
Definition: seq.h:33
ripple::test::csf::Ledger::id
ID id() const
Definition: ledgers.h:167
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::test::csf::Ledger::genesis
static const Instance genesis
Definition: ledgers.h:149
ripple::test::csf::LedgerOracle::branches
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
ripple::test::csf::Ledger::isAncestor
bool isAncestor(Ledger const &ancestor) const
Determine whether ancestor is really an ancestor of this ledger.
Definition: ledgers.cpp:40
ripple::test::csf::Ledger::Seq
tagged_integer< std::uint32_t, SeqTag > Seq
Definition: ledgers.h:64
std::optional
std::size_t
ripple::test::csf::Ledger::instance_
Instance const * instance_
Definition: ledgers.h:239
ripple::tagged_integer
A type-safe wrap around standard integral types.
Definition: tagged_integer.h:44
std::set
STL class.
ripple::effCloseTime
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.
Definition: LedgerTiming.h:152
Json::Value
Represents a JSON value.
Definition: json_value.h:145