rippled
AmendmentTable.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 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 <ripple/app/main/Application.h>
21 #include <ripple/app/misc/AmendmentTable.h>
22 #include <ripple/app/rdb/Wallet.h>
23 #include <ripple/core/ConfigSections.h>
24 #include <ripple/protocol/Feature.h>
25 #include <ripple/protocol/STValidation.h>
26 #include <ripple/protocol/TxFlags.h>
27 #include <ripple/protocol/jss.h>
28 #include <boost/format.hpp>
29 #include <boost/regex.hpp>
30 #include <algorithm>
31 #include <mutex>
32 
33 namespace ripple {
34 
36 parseSection(Section const& section)
37 {
38  static boost::regex const re1(
39  "^" // start of line
40  "(?:\\s*)" // whitespace (optional)
41  "([abcdefABCDEF0-9]{64})" // <hexadecimal amendment ID>
42  "(?:\\s+)" // whitespace
43  "(\\S+)" // <description>
44  ,
45  boost::regex_constants::optimize);
46 
48 
49  for (auto const& line : section.lines())
50  {
51  boost::smatch match;
52 
53  if (!boost::regex_match(line, match, re1))
54  Throw<std::runtime_error>(
55  "Invalid entry '" + line + "' in [" + section.name() + "]");
56 
57  uint256 id;
58 
59  if (!id.parseHex(match[1]))
60  Throw<std::runtime_error>(
61  "Invalid amendment ID '" + match[1] + "' in [" +
62  section.name() + "]");
63 
64  names.push_back(std::make_pair(id, match[2]));
65  }
66 
67  return names;
68 }
69 
75 {
78 
84  bool enabled = false;
85 
87  bool supported = false;
88 
91 
92  explicit AmendmentState() = default;
93 };
94 
97 {
98 private:
99  // How many yes votes each amendment received
101  Rules const& rules_;
102  // number of trusted validations
104  // number of votes needed
105  int threshold_ = 0;
106 
107 public:
109  Rules const& rules,
111  : rules_(rules)
112  {
113  // process validations for ledger before flag ledger
114  for (auto const& val : valSet)
115  {
116  if (val->isTrusted())
117  {
118  if (val->isFieldPresent(sfAmendments))
119  {
120  auto const choices = val->getFieldV256(sfAmendments);
122  choices.begin(),
123  choices.end(),
124  [&](auto const& amendment) { ++votes_[amendment]; });
125  }
126 
128  }
129  }
130 
132  ? std::max(
133  1L,
134  static_cast<long>(
138  : std::max(
139  1L,
140  static_cast<long>(
144  }
145 
146  bool
147  passes(uint256 const& amendment) const
148  {
149  auto const& it = votes_.find(amendment);
150 
151  if (it == votes_.end())
152  return false;
153 
154  // Before this fix, it was possible for an amendment to activate with a
155  // percentage slightly less than 80% because we compared for "greater
156  // than or equal to" instead of strictly "greater than".
157  // One validator is an exception, otherwise it is not possible
158  // to gain majority.
160  trustedValidations_ == 1)
161  return it->second >= threshold_;
162 
163  return it->second > threshold_;
164  }
165 
166  int
167  votes(uint256 const& amendment) const
168  {
169  auto const& it = votes_.find(amendment);
170 
171  if (it == votes_.end())
172  return 0;
173 
174  return it->second;
175  }
176 
177  int
179  {
180  return trustedValidations_;
181  }
182 
183  int
184  threshold() const
185  {
186  return threshold_;
187  }
188 };
189 
190 //------------------------------------------------------------------------------
191 
198 class AmendmentTableImpl final : public AmendmentTable
199 {
200 private:
202 
205 
206  // Time that an amendment must hold a majority for
208 
209  // The results of the last voting round - may be empty if
210  // we haven't participated in one yet.
212 
213  // True if an unsupported amendment is enabled
215 
216  // Unset if no unsupported amendments reach majority,
217  // else set to the earliest time an unsupported amendment
218  // will be enabled.
220 
222 
223  // Database which persists veto/unveto vote
225 
226  // Finds or creates state. Must be called with mutex_ locked.
228  add(uint256 const& amendment, std::lock_guard<std::mutex> const& lock);
229 
230  // Finds existing state. Must be called with mutex_ locked.
232  get(uint256 const& amendment, std::lock_guard<std::mutex> const& lock);
233 
234  AmendmentState const*
235  get(uint256 const& amendment,
236  std::lock_guard<std::mutex> const& lock) const;
237 
238  // Injects amendment json into v. Must be called with mutex_ locked.
239  void
240  injectJson(
241  Json::Value& v,
242  uint256 const& amendment,
243  AmendmentState const& state,
244  std::lock_guard<std::mutex> const& lock) const;
245 
246  void
247  persistVote(
248  uint256 const& amendment,
249  std::string const& name,
250  AmendmentVote vote) const;
251 
252 public:
254  Application& app,
255  std::chrono::seconds majorityTime,
256  std::vector<FeatureInfo> const& supported,
257  Section const& enabled,
258  Section const& vetoed,
259  beast::Journal journal);
260 
261  uint256
262  find(std::string const& name) const override;
263 
264  bool
265  veto(uint256 const& amendment) override;
266  bool
267  unVeto(uint256 const& amendment) override;
268 
269  bool
270  enable(uint256 const& amendment) override;
271 
272  bool
273  isEnabled(uint256 const& amendment) const override;
274  bool
275  isSupported(uint256 const& amendment) const override;
276 
277  bool
278  hasUnsupportedEnabled() const override;
279 
281  firstUnsupportedExpected() const override;
282 
284  getJson() const override;
286  getJson(uint256 const&) const override;
287 
288  bool
289  needValidatedLedger(LedgerIndex seq) const override;
290 
291  void
293  LedgerIndex seq,
294  std::set<uint256> const& enabled,
295  majorityAmendments_t const& majority) override;
296 
298  doValidation(std::set<uint256> const& enabledAmendments) const override;
299 
301  getDesired() const override;
302 
304  doVoting(
305  Rules const& rules,
306  NetClock::time_point closeTime,
307  std::set<uint256> const& enabledAmendments,
308  majorityAmendments_t const& majorityAmendments,
309  std::vector<std::shared_ptr<STValidation>> const& validations) override;
310 };
311 
312 //------------------------------------------------------------------------------
313 
315  Application& app,
316  std::chrono::seconds majorityTime,
317  std::vector<FeatureInfo> const& supported,
318  Section const& enabled,
319  Section const& vetoed,
320  beast::Journal journal)
321  : lastUpdateSeq_(0)
322  , majorityTime_(majorityTime)
323  , unsupportedEnabled_(false)
324  , j_(journal)
325  , db_(app.getWalletDB())
326 {
327  std::lock_guard lock(mutex_);
328 
329  // Find out if the FeatureVotes table exists in WalletDB
330  bool const featureVotesExist = [this]() {
331  auto db = db_.checkoutDb();
332  return createFeatureVotes(*db);
333  }();
334 
335  // Parse supported amendments
336  for (auto const& [name, amendment, votebehavior] : supported)
337  {
338  AmendmentState& s = add(amendment, lock);
339 
340  s.name = name;
341  s.supported = true;
342  switch (votebehavior)
343  {
346  break;
347 
350  break;
351 
354  break;
355  }
356 
357  JLOG(j_.debug()) << "Amendment " << amendment << " (" << s.name
358  << ") is supported and will be "
359  << (s.vote == AmendmentVote::up ? "up" : "down")
360  << " voted by default if not enabled on the ledger.";
361  }
362 
363  hash_set<uint256> detect_conflict;
364  // Parse enabled amendments from config
365  for (std::pair<uint256, std::string> const& a : parseSection(enabled))
366  {
367  if (featureVotesExist)
368  { // If the table existed, warn about duplicate config info
369  JLOG(j_.warn()) << "[amendments] section in config file ignored"
370  " in favor of data in db/wallet.db.";
371  break;
372  }
373  else
374  { // Otherwise transfer config data into the table
375  detect_conflict.insert(a.first);
376  persistVote(a.first, a.second, AmendmentVote::up);
377  }
378  }
379 
380  // Parse vetoed amendments from config
381  for (auto const& a : parseSection(vetoed))
382  {
383  if (featureVotesExist)
384  { // If the table existed, warn about duplicate config info
385  JLOG(j_.warn())
386  << "[veto_amendments] section in config file ignored"
387  " in favor of data in db/wallet.db.";
388  break;
389  }
390  else
391  { // Otherwise transfer config data into the table
392  if (detect_conflict.count(a.first) == 0)
393  {
394  persistVote(a.first, a.second, AmendmentVote::down);
395  }
396  else
397  {
398  JLOG(j_.warn())
399  << "[veto_amendments] section in config has amendment "
400  << '(' << a.first << ", " << a.second
401  << ") both [veto_amendments] and [amendments].";
402  }
403  }
404  }
405 
406  // Read amendment votes from wallet.db
407  auto db = db_.checkoutDb();
409  *db,
410  [&](boost::optional<std::string> amendment_hash,
411  boost::optional<std::string> amendment_name,
412  boost::optional<AmendmentVote> vote) {
413  uint256 amend_hash;
414  if (!amendment_hash || !amendment_name || !vote)
415  {
416  // These fields should never have nulls, but check
417  Throw<std::runtime_error>(
418  "Invalid FeatureVotes row in wallet.db");
419  }
420  if (!amend_hash.parseHex(*amendment_hash))
421  {
422  Throw<std::runtime_error>(
423  "Invalid amendment ID '" + *amendment_hash +
424  " in wallet.db");
425  }
426  if (*vote == AmendmentVote::down)
427  {
428  // Unknown amendments are effectively vetoed already
429  if (auto s = get(amend_hash, lock))
430  {
431  JLOG(j_.info()) << "Amendment {" << *amendment_name << ", "
432  << amend_hash << "} is downvoted.";
433  if (!amendment_name->empty())
434  s->name = *amendment_name;
435  // An obsolete amendment's vote can never be changed
436  if (s->vote != AmendmentVote::obsolete)
437  s->vote = *vote;
438  }
439  }
440  else // up-vote
441  {
442  AmendmentState& s = add(amend_hash, lock);
443 
444  JLOG(j_.debug()) << "Amendment {" << *amendment_name << ", "
445  << amend_hash << "} is upvoted.";
446  if (!amendment_name->empty())
447  s.name = *amendment_name;
448  // An obsolete amendment's vote can never be changed
449  if (s.vote != AmendmentVote::obsolete)
450  s.vote = *vote;
451  }
452  });
453 }
454 
457  uint256 const& amendmentHash,
459 {
460  // call with the mutex held
461  return amendmentMap_[amendmentHash];
462 }
463 
466  uint256 const& amendmentHash,
467  std::lock_guard<std::mutex> const& lock)
468 {
469  // Forward to the const version of get.
470  return const_cast<AmendmentState*>(
471  std::as_const(*this).get(amendmentHash, lock));
472 }
473 
474 AmendmentState const*
476  uint256 const& amendmentHash,
477  std::lock_guard<std::mutex> const&) const
478 {
479  // call with the mutex held
480  auto ret = amendmentMap_.find(amendmentHash);
481 
482  if (ret == amendmentMap_.end())
483  return nullptr;
484 
485  return &ret->second;
486 }
487 
488 uint256
490 {
491  std::lock_guard lock(mutex_);
492 
493  for (auto const& e : amendmentMap_)
494  {
495  if (name == e.second.name)
496  return e.first;
497  }
498 
499  return {};
500 }
501 
502 void
504  uint256 const& amendment,
505  std::string const& name,
506  AmendmentVote vote) const
507 {
508  assert(vote != AmendmentVote::obsolete);
509  auto db = db_.checkoutDb();
510  voteAmendment(*db, amendment, name, vote);
511 }
512 
513 bool
515 {
516  std::lock_guard lock(mutex_);
517  AmendmentState& s = add(amendment, lock);
518 
519  if (s.vote != AmendmentVote::up)
520  return false;
522  persistVote(amendment, s.name, s.vote);
523  return true;
524 }
525 
526 bool
528 {
529  std::lock_guard lock(mutex_);
530  AmendmentState* const s = get(amendment, lock);
531 
532  if (!s || s->vote != AmendmentVote::down)
533  return false;
534  s->vote = AmendmentVote::up;
535  persistVote(amendment, s->name, s->vote);
536  return true;
537 }
538 
539 bool
541 {
542  std::lock_guard lock(mutex_);
543  AmendmentState& s = add(amendment, lock);
544 
545  if (s.enabled)
546  return false;
547 
548  s.enabled = true;
549 
550  if (!s.supported)
551  {
552  JLOG(j_.error()) << "Unsupported amendment " << amendment
553  << " activated.";
554  unsupportedEnabled_ = true;
555  }
556 
557  return true;
558 }
559 
560 bool
561 AmendmentTableImpl::isEnabled(uint256 const& amendment) const
562 {
563  std::lock_guard lock(mutex_);
564  AmendmentState const* s = get(amendment, lock);
565  return s && s->enabled;
566 }
567 
568 bool
570 {
571  std::lock_guard lock(mutex_);
572  AmendmentState const* s = get(amendment, lock);
573  return s && s->supported;
574 }
575 
576 bool
578 {
579  std::lock_guard lock(mutex_);
580  return unsupportedEnabled_;
581 }
582 
585 {
586  std::lock_guard lock(mutex_);
588 }
589 
592 {
593  // Get the list of amendments we support and do not
594  // veto, but that are not already enabled
595  std::vector<uint256> amendments;
596 
597  {
598  std::lock_guard lock(mutex_);
599  amendments.reserve(amendmentMap_.size());
600  for (auto const& e : amendmentMap_)
601  {
602  if (e.second.supported && e.second.vote == AmendmentVote::up &&
603  (enabled.count(e.first) == 0))
604  {
605  amendments.push_back(e.first);
606  JLOG(j_.info()) << "Voting for amendment " << e.second.name;
607  }
608  }
609  }
610 
611  if (!amendments.empty())
612  std::sort(amendments.begin(), amendments.end());
613 
614  return amendments;
615 }
616 
619 {
620  // Get the list of amendments we support and do not veto
621  return doValidation({});
622 }
623 
626  Rules const& rules,
627  NetClock::time_point closeTime,
628  std::set<uint256> const& enabledAmendments,
629  majorityAmendments_t const& majorityAmendments,
631 {
632  JLOG(j_.trace()) << "voting at " << closeTime.time_since_epoch().count()
633  << ": " << enabledAmendments.size() << ", "
634  << majorityAmendments.size() << ", " << valSet.size();
635 
636  auto vote = std::make_unique<AmendmentSet>(rules, valSet);
637 
638  JLOG(j_.debug()) << "Received " << vote->trustedValidations()
639  << " trusted validations, threshold is: "
640  << vote->threshold();
641 
642  // Map of amendments to the action to be taken for each one. The action is
643  // the value of the flags in the pseudo-transaction
645 
646  std::lock_guard lock(mutex_);
647 
648  // process all amendments we know of
649  for (auto const& entry : amendmentMap_)
650  {
651  NetClock::time_point majorityTime = {};
652 
653  bool const hasValMajority = vote->passes(entry.first);
654 
655  {
656  auto const it = majorityAmendments.find(entry.first);
657  if (it != majorityAmendments.end())
658  majorityTime = it->second;
659  }
660 
661  if (enabledAmendments.count(entry.first) != 0)
662  {
663  JLOG(j_.debug()) << entry.first << ": amendment already enabled";
664  }
665  else if (
666  hasValMajority && (majorityTime == NetClock::time_point{}) &&
667  entry.second.vote == AmendmentVote::up)
668  {
669  // Ledger says no majority, validators say yes
670  JLOG(j_.debug()) << entry.first << ": amendment got majority";
671  actions[entry.first] = tfGotMajority;
672  }
673  else if (!hasValMajority && (majorityTime != NetClock::time_point{}))
674  {
675  // Ledger says majority, validators say no
676  JLOG(j_.debug()) << entry.first << ": amendment lost majority";
677  actions[entry.first] = tfLostMajority;
678  }
679  else if (
680  (majorityTime != NetClock::time_point{}) &&
681  ((majorityTime + majorityTime_) <= closeTime) &&
682  entry.second.vote == AmendmentVote::up)
683  {
684  // Ledger says majority held
685  JLOG(j_.debug()) << entry.first << ": amendment majority held";
686  actions[entry.first] = 0;
687  }
688  }
689 
690  // Stash for reporting
691  lastVote_ = std::move(vote);
692  return actions;
693 }
694 
695 bool
697 {
698  std::lock_guard lock(mutex_);
699 
700  // Is there a ledger in which an amendment could have been enabled
701  // between these two ledger sequences?
702 
703  return ((ledgerSeq - 1) / 256) != ((lastUpdateSeq_ - 1) / 256);
704 }
705 
706 void
708  LedgerIndex ledgerSeq,
709  std::set<uint256> const& enabled,
710  majorityAmendments_t const& majority)
711 {
712  for (auto& e : enabled)
713  enable(e);
714 
715  std::lock_guard lock(mutex_);
716 
717  // Remember the ledger sequence of this update.
718  lastUpdateSeq_ = ledgerSeq;
719 
720  // Since we have the whole list in `majority`, reset the time flag, even
721  // if it's currently set. If it's not set when the loop is done, then any
722  // prior unknown amendments have lost majority.
724  for (auto const& [hash, time] : majority)
725  {
726  AmendmentState& s = add(hash, lock);
727 
728  if (s.enabled)
729  continue;
730 
731  if (!s.supported)
732  {
733  JLOG(j_.info()) << "Unsupported amendment " << hash
734  << " reached majority at " << to_string(time);
737  }
738  }
741 }
742 
743 void
745  Json::Value& v,
746  const uint256& id,
747  const AmendmentState& fs,
748  std::lock_guard<std::mutex> const&) const
749 {
750  if (!fs.name.empty())
751  v[jss::name] = fs.name;
752 
753  v[jss::supported] = fs.supported;
754  if (!fs.enabled)
755  {
756  if (fs.vote == AmendmentVote::obsolete)
757  v[jss::vetoed] = "Obsolete";
758  else
759  v[jss::vetoed] = fs.vote == AmendmentVote::down;
760  }
761  v[jss::enabled] = fs.enabled;
762 
763  if (!fs.enabled && lastVote_)
764  {
765  auto const votesTotal = lastVote_->trustedValidations();
766  auto const votesNeeded = lastVote_->threshold();
767  auto const votesFor = lastVote_->votes(id);
768 
769  v[jss::count] = votesFor;
770  v[jss::validations] = votesTotal;
771 
772  if (votesNeeded)
773  v[jss::threshold] = votesNeeded;
774  }
775 }
776 
779 {
781  {
782  std::lock_guard lock(mutex_);
783  for (auto const& e : amendmentMap_)
784  {
785  injectJson(
786  ret[to_string(e.first)] = Json::objectValue,
787  e.first,
788  e.second,
789  lock);
790  }
791  }
792  return ret;
793 }
794 
796 AmendmentTableImpl::getJson(uint256 const& amendmentID) const
797 {
799  Json::Value& jAmendment = (ret[to_string(amendmentID)] = Json::objectValue);
800 
801  {
802  std::lock_guard lock(mutex_);
803  AmendmentState const* a = get(amendmentID, lock);
804  if (a)
805  injectJson(jAmendment, amendmentID, *a, lock);
806  }
807 
808  return ret;
809 }
810 
813  Application& app,
814  std::chrono::seconds majorityTime,
816  Section const& enabled,
817  Section const& vetoed,
818  beast::Journal journal)
819 {
820  return std::make_unique<AmendmentTableImpl>(
821  app, majorityTime, supported, enabled, vetoed, journal);
822 }
823 
824 } // namespace ripple
ripple::tfGotMajority
constexpr std::uint32_t tfGotMajority
Definition: TxFlags.h:118
ripple::Section
Holds a collection of configuration values.
Definition: BasicConfig.h:42
ripple::Application
Definition: Application.h:115
ripple::AmendmentTableImpl::db_
DatabaseCon & db_
Definition: AmendmentTable.cpp:224
ripple::AmendmentState::supported
bool supported
Indicates an amendment that this server has code support for.
Definition: AmendmentTable.cpp:87
ripple::tfLostMajority
constexpr std::uint32_t tfLostMajority
Definition: TxFlags.h:119
ripple::AmendmentTableImpl::lastUpdateSeq_
std::uint32_t lastUpdateSeq_
Definition: AmendmentTable.cpp:204
std::for_each
T for_each(T... args)
ripple::AmendmentVote::up
@ up
ripple::AmendmentState
Current state of an amendment.
Definition: AmendmentTable.cpp:74
std::string
STL class.
ripple::Rules::enabled
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition: Rules.cpp:94
std::shared_ptr
STL class.
beast::Journal::trace
Stream trace() const
Severity stream access functions.
Definition: Journal.h:309
ripple::AmendmentSet::threshold_
int threshold_
Definition: AmendmentTable.cpp:105
ripple::AmendmentVote::obsolete
@ obsolete
ripple::AmendmentTableImpl::firstUnsupportedExpected_
std::optional< NetClock::time_point > firstUnsupportedExpected_
Definition: AmendmentTable.cpp:219
std::unordered_set
STL class.
ripple::AmendmentTableImpl::getDesired
std::vector< uint256 > getDesired() const override
Definition: AmendmentTable.cpp:618
std::pair
ripple::AmendmentTableImpl::mutex_
std::mutex mutex_
Definition: AmendmentTable.cpp:201
ripple::AmendmentTableImpl::unsupportedEnabled_
bool unsupportedEnabled_
Definition: AmendmentTable.cpp:214
ripple::AmendmentTableImpl::doValidation
std::vector< uint256 > doValidation(std::set< uint256 > const &enabledAmendments) const override
Definition: AmendmentTable.cpp:591
ripple::createFeatureVotes
bool createFeatureVotes(soci::session &session)
createFeatureVotes Creates the FeatureVote table if it does not exist.
Definition: Wallet.cpp:224
std::vector
STL class.
std::map::find
T find(T... args)
std::set::size
T size(T... args)
ripple::VoteBehavior::DefaultNo
@ DefaultNo
std::chrono::seconds
ripple::AmendmentTableImpl::find
uint256 find(std::string const &name) const override
Definition: AmendmentTable.cpp:489
beast::Journal::warn
Stream warn() const
Definition: Journal.h:327
ripple::AmendmentSet::votes_
hash_map< uint256, int > votes_
Definition: AmendmentTable.cpp:100
std::lock_guard
STL class.
ripple::AmendmentTableImpl::unVeto
bool unVeto(uint256 const &amendment) override
Definition: AmendmentTable.cpp:527
ripple::AmendmentState::vote
AmendmentVote vote
If an amendment is down-voted, a server will not vote to enable it.
Definition: AmendmentTable.cpp:77
ripple::AmendmentSet
The status of all amendments requested in a given window.
Definition: AmendmentTable.cpp:96
std::as_const
T as_const(T... args)
ripple::AmendmentTableImpl
Track the list of "amendments".
Definition: AmendmentTable.cpp:198
std::sort
T sort(T... args)
algorithm
ripple::parseSection
static std::vector< std::pair< uint256, std::string > > parseSection(Section const &section)
Definition: AmendmentTable.cpp:36
ripple::VoteBehavior::Obsolete
@ Obsolete
std::vector::push_back
T push_back(T... args)
ripple::AmendmentSet::passes
bool passes(uint256 const &amendment) const
Definition: AmendmentTable.cpp:147
ripple::AmendmentVote::down
@ down
ripple::base_uint< 256 >
ripple::Section::name
std::string const & name() const
Returns the name of this section.
Definition: BasicConfig.h:59
std::chrono::time_point::time_since_epoch
T time_since_epoch(T... args)
ripple::AmendmentSet::threshold
int threshold() const
Definition: AmendmentTable.cpp:184
ripple::DatabaseCon::checkoutDb
LockedSociSession checkoutDb()
Definition: DatabaseCon.h:178
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:43
ripple::AmendmentTableImpl::firstUnsupportedExpected
std::optional< NetClock::time_point > firstUnsupportedExpected() const override
Definition: AmendmentTable.cpp:584
ripple::preFixAmendmentMajorityCalcThreshold
constexpr std::ratio< 204, 256 > preFixAmendmentMajorityCalcThreshold
The minimum amount of support an amendment should have.
Definition: SystemParameters.h:83
ripple::fixAmendmentMajorityCalc
const uint256 fixAmendmentMajorityCalc
ripple::AmendmentTableImpl::AmendmentTableImpl
AmendmentTableImpl(Application &app, std::chrono::seconds majorityTime, std::vector< FeatureInfo > const &supported, Section const &enabled, Section const &vetoed, beast::Journal journal)
Definition: AmendmentTable.cpp:314
ripple::AmendmentState::AmendmentState
AmendmentState()=default
ripple::AmendmentTableImpl::doVoting
std::map< uint256, std::uint32_t > doVoting(Rules const &rules, NetClock::time_point closeTime, std::set< uint256 > const &enabledAmendments, majorityAmendments_t const &majorityAmendments, std::vector< std::shared_ptr< STValidation >> const &validations) override
Definition: AmendmentTable.cpp:625
ripple::readAmendments
void readAmendments(soci::session &session, std::function< void(boost::optional< std::string > amendment_hash, boost::optional< std::string > amendment_name, boost::optional< AmendmentVote > vote)> const &callback)
readAmendments Reads all amendments from the FeatureVotes table.
Definition: Wallet.cpp:248
ripple::AmendmentSet::rules_
Rules const & rules_
Definition: AmendmentTable.cpp:101
ripple::AmendmentTableImpl::get
AmendmentState * get(uint256 const &amendment, std::lock_guard< std::mutex > const &lock)
Definition: AmendmentTable.cpp:465
ripple::AmendmentTableImpl::isSupported
bool isSupported(uint256 const &amendment) const override
Definition: AmendmentTable.cpp:569
beast::Journal::error
Stream error() const
Definition: Journal.h:333
beast::Journal::info
Stream info() const
Definition: Journal.h:321
std::chrono::time_point
ripple::Section::lines
std::vector< std::string > const & lines() const
Returns all the lines in the section.
Definition: BasicConfig.h:68
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
std::uint32_t
std::map
STL class.
ripple::AmendmentTableImpl::veto
bool veto(uint256 const &amendment) override
Definition: AmendmentTable.cpp:514
ripple::AmendmentSet::trustedValidations_
int trustedValidations_
Definition: AmendmentTable.cpp:103
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::AmendmentTableImpl::injectJson
void injectJson(Json::Value &v, uint256 const &amendment, AmendmentState const &state, std::lock_guard< std::mutex > const &lock) const
Definition: AmendmentTable.cpp:744
ripple::AmendmentTableImpl::amendmentMap_
hash_map< uint256, AmendmentState > amendmentMap_
Definition: AmendmentTable.cpp:203
ripple::AmendmentTableImpl::lastVote_
std::unique_ptr< AmendmentSet > lastVote_
Definition: AmendmentTable.cpp:211
std::unordered_set::insert
T insert(T... args)
ripple::AmendmentTableImpl::majorityTime_
const std::chrono::seconds majorityTime_
Definition: AmendmentTable.cpp:207
ripple::voteAmendment
void voteAmendment(soci::session &session, uint256 const &amendment, std::string const &name, AmendmentVote vote)
voteAmendment Set the veto value for a particular amendment.
Definition: Wallet.cpp:284
ripple::AmendmentState::enabled
bool enabled
Indicates that the amendment has been enabled.
Definition: AmendmentTable.cpp:84
ripple::AmendmentSet::AmendmentSet
AmendmentSet(Rules const &rules, std::vector< std::shared_ptr< STValidation >> const &valSet)
Definition: AmendmentTable.cpp:108
ripple::AmendmentTableImpl::getJson
Json::Value getJson() const override
Definition: AmendmentTable.cpp:778
ripple::DatabaseCon
Definition: DatabaseCon.h:81
ripple::AmendmentState::name
std::string name
The name of this amendment, possibly empty.
Definition: AmendmentTable.cpp:90
std::unordered_set::count
T count(T... args)
std::string::empty
T empty(T... args)
ripple::Rules
Rules controlling protocol behavior.
Definition: Rules.h:33
ripple::AmendmentVote
AmendmentVote
Definition: Wallet.h:147
std::optional
mutex
beast::Journal::debug
Stream debug() const
Definition: Journal.h:315
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
ripple::make_AmendmentTable
std::unique_ptr< AmendmentTable > make_AmendmentTable(Application &app, std::chrono::seconds majorityTime, std::vector< AmendmentTable::FeatureInfo > const &supported, Section const &enabled, Section const &vetoed, beast::Journal journal)
Definition: AmendmentTable.cpp:812
std::make_pair
T make_pair(T... args)
std::map::end
T end(T... args)
ripple::AmendmentTableImpl::add
AmendmentState & add(uint256 const &amendment, std::lock_guard< std::mutex > const &lock)
Definition: AmendmentTable.cpp:456
ripple::AmendmentSet::trustedValidations
int trustedValidations() const
Definition: AmendmentTable.cpp:178
ripple::AmendmentTableImpl::isEnabled
bool isEnabled(uint256 const &amendment) const override
Definition: AmendmentTable.cpp:561
std::max
T max(T... args)
ripple::base_uint::parseHex
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition: base_uint.h:496
ripple::AmendmentTableImpl::j_
const beast::Journal j_
Definition: AmendmentTable.cpp:221
ripple::AmendmentTable
The amendment table stores the list of enabled and potential amendments.
Definition: AmendmentTable.h:37
ripple::AmendmentTableImpl::needValidatedLedger
bool needValidatedLedger(LedgerIndex seq) const override
Called to determine whether the amendment logic needs to process a new validated ledger.
Definition: AmendmentTable.cpp:696
ripple::AmendmentSet::votes
int votes(uint256 const &amendment) const
Definition: AmendmentTable.cpp:167
std::unique_ptr
STL class.
std::unordered_map
STL class.
ripple::AmendmentTableImpl::persistVote
void persistVote(uint256 const &amendment, std::string const &name, AmendmentVote vote) const
Definition: AmendmentTable.cpp:503
std::set
STL class.
ripple::postFixAmendmentMajorityCalcThreshold
constexpr std::ratio< 80, 100 > postFixAmendmentMajorityCalcThreshold
Definition: SystemParameters.h:85
ripple::AmendmentTableImpl::doValidatedLedger
void doValidatedLedger(LedgerIndex seq, std::set< uint256 > const &enabled, majorityAmendments_t const &majority) override
Definition: AmendmentTable.cpp:707
ripple::AmendmentTableImpl::enable
bool enable(uint256 const &amendment) override
Definition: AmendmentTable.cpp:540
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::sfAmendments
const SF_VECTOR256 sfAmendments
ripple::AmendmentTableImpl::hasUnsupportedEnabled
bool hasUnsupportedEnabled() const override
returns true if one or more amendments on the network have been enabled that this server does not sup...
Definition: AmendmentTable.cpp:577
ripple::VoteBehavior::DefaultYes
@ DefaultYes