rippled
RCLConsensus.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/consensus/RCLConsensus.h>
21 #include <ripple/app/consensus/RCLValidations.h>
22 #include <ripple/app/ledger/BuildLedger.h>
23 #include <ripple/app/ledger/InboundLedgers.h>
24 #include <ripple/app/ledger/InboundTransactions.h>
25 #include <ripple/app/ledger/Ledger.h>
26 #include <ripple/app/ledger/LedgerMaster.h>
27 #include <ripple/app/ledger/LocalTxs.h>
28 #include <ripple/app/ledger/OpenLedger.h>
29 #include <ripple/app/misc/AmendmentTable.h>
30 #include <ripple/app/misc/HashRouter.h>
31 #include <ripple/app/misc/LoadFeeTrack.h>
32 #include <ripple/app/misc/NegativeUNLVote.h>
33 #include <ripple/app/misc/NetworkOPs.h>
34 #include <ripple/app/misc/TxQ.h>
35 #include <ripple/app/misc/ValidatorKeys.h>
36 #include <ripple/app/misc/ValidatorList.h>
37 #include <ripple/basics/random.h>
38 #include <ripple/beast/core/LexicalCast.h>
39 #include <ripple/consensus/LedgerTiming.h>
40 #include <ripple/nodestore/DatabaseShard.h>
41 #include <ripple/overlay/Overlay.h>
42 #include <ripple/overlay/predicates.h>
43 #include <ripple/protocol/BuildInfo.h>
44 #include <ripple/protocol/Feature.h>
45 #include <ripple/protocol/digest.h>
46 
47 #include <algorithm>
48 #include <mutex>
49 
50 namespace ripple {
51 
53  Application& app,
54  std::unique_ptr<FeeVote>&& feeVote,
55  LedgerMaster& ledgerMaster,
56  LocalTxs& localTxs,
57  InboundTransactions& inboundTransactions,
58  Consensus<Adaptor>::clock_type const& clock,
59  ValidatorKeys const& validatorKeys,
60  beast::Journal journal)
61  : adaptor_(
62  app,
63  std::move(feeVote),
65  localTxs,
66  inboundTransactions,
67  validatorKeys,
68  journal)
69  , consensus_(clock, adaptor_, journal)
70  , j_(journal)
71 {
72 }
73 
75  Application& app,
76  std::unique_ptr<FeeVote>&& feeVote,
77  LedgerMaster& ledgerMaster,
78  LocalTxs& localTxs,
79  InboundTransactions& inboundTransactions,
80  ValidatorKeys const& validatorKeys,
81  beast::Journal journal)
82  : app_(app)
83  , feeVote_(std::move(feeVote))
84  , ledgerMaster_(ledgerMaster)
85  , localTxs_(localTxs)
86  , inboundTransactions_{inboundTransactions}
87  , j_(journal)
88  , validatorKeys_(validatorKeys)
89  , valCookie_(
90  1 +
91  rand_int(
92  crypto_prng(),
94  , nUnlVote_(validatorKeys_.nodeID, j_)
95 {
96  assert(valCookie_ != 0);
97 
98  JLOG(j_.info()) << "Consensus engine started (cookie: " +
99  std::to_string(valCookie_) + ")";
100 
101  if (validatorKeys_.nodeID != beast::zero && validatorKeys_.keys)
102  {
104 
105  JLOG(j_.info()) << "Validator identity: "
106  << toBase58(
108  validatorKeys_.keys->masterPublicKey);
109 
110  if (validatorKeys_.keys->masterPublicKey !=
111  validatorKeys_.keys->publicKey)
112  {
113  JLOG(j_.debug())
114  << "Validator ephemeral signing key: "
115  << toBase58(
116  TokenType::NodePublic, validatorKeys_.keys->publicKey)
117  << " (seq: " << std::to_string(validatorKeys_.sequence) << ")";
118  }
119  }
120 }
121 
124 {
125  // we need to switch the ledger we're working from
126  auto built = ledgerMaster_.getLedgerByHash(hash);
127  if (!built)
128  {
129  if (acquiringLedger_ != hash)
130  {
131  // need to start acquiring the correct consensus LCL
132  JLOG(j_.warn()) << "Need consensus ledger " << hash;
133 
134  // Tell the ledger acquire system that we need the consensus ledger
135  acquiringLedger_ = hash;
136 
137  app_.getJobQueue().addJob(
138  jtADVANCE, "getConsensusLedger", [id = hash, &app = app_]() {
139  app.getInboundLedgers().acquire(
141  });
142  }
143  return std::nullopt;
144  }
145 
146  assert(!built->open() && built->isImmutable());
147  assert(built->info().hash == hash);
148 
149  // Notify inbound transactions of the new ledger sequence number
150  inboundTransactions_.newRound(built->info().seq);
151 
152  return RCLCxLedger(built);
153 }
154 
155 void
157 {
158  protocol::TMProposeSet prop;
159 
160  auto const& proposal = peerPos.proposal();
161 
162  prop.set_proposeseq(proposal.proposeSeq());
163  prop.set_closetime(proposal.closeTime().time_since_epoch().count());
164 
165  prop.set_currenttxhash(
166  proposal.position().begin(), proposal.position().size());
167  prop.set_previousledger(
168  proposal.prevLedger().begin(), proposal.position().size());
169 
170  auto const pk = peerPos.publicKey().slice();
171  prop.set_nodepubkey(pk.data(), pk.size());
172 
173  auto const sig = peerPos.signature();
174  prop.set_signature(sig.data(), sig.size());
175 
176  app_.overlay().relay(prop, peerPos.suppressionID(), peerPos.publicKey());
177 }
178 
179 void
181 {
182  // If we didn't relay this transaction recently, relay it to all peers
183  if (app_.getHashRouter().shouldRelay(tx.id()))
184  {
185  JLOG(j_.debug()) << "Relaying disputed tx " << tx.id();
186  auto const slice = tx.tx_->slice();
187  protocol::TMTransaction msg;
188  msg.set_rawtransaction(slice.data(), slice.size());
189  msg.set_status(protocol::tsNEW);
190  msg.set_receivetimestamp(
191  app_.timeKeeper().now().time_since_epoch().count());
192  static std::set<Peer::id_t> skip{};
193  app_.overlay().relay(tx.id(), msg, skip);
194  }
195  else
196  {
197  JLOG(j_.debug()) << "Not relaying disputed tx " << tx.id();
198  }
199 }
200 void
202 {
203  JLOG(j_.trace()) << (proposal.isBowOut() ? "We bow out: " : "We propose: ")
204  << ripple::to_string(proposal.prevLedger()) << " -> "
205  << ripple::to_string(proposal.position());
206 
207  protocol::TMProposeSet prop;
208 
209  prop.set_currenttxhash(
210  proposal.position().begin(), proposal.position().size());
211  prop.set_previousledger(
212  proposal.prevLedger().begin(), proposal.prevLedger().size());
213  prop.set_proposeseq(proposal.proposeSeq());
214  prop.set_closetime(proposal.closeTime().time_since_epoch().count());
215 
216  if (!validatorKeys_.keys)
217  {
218  JLOG(j_.warn()) << "RCLConsensus::Adaptor::propose: ValidatorKeys "
219  "not set: \n";
220  return;
221  }
222 
223  auto const& keys = *validatorKeys_.keys;
224 
225  prop.set_nodepubkey(keys.publicKey.data(), keys.publicKey.size());
226 
227  auto sig =
228  signDigest(keys.publicKey, keys.secretKey, proposal.signingHash());
229 
230  prop.set_signature(sig.data(), sig.size());
231 
232  auto const suppression = proposalUniqueId(
233  proposal.position(),
234  proposal.prevLedger(),
235  proposal.proposeSeq(),
236  proposal.closeTime(),
237  keys.publicKey,
238  sig);
239 
240  app_.getHashRouter().addSuppression(suppression);
241 
242  app_.overlay().broadcast(prop);
243 }
244 
245 void
247 {
248  inboundTransactions_.giveSet(txns.id(), txns.map_, false);
249 }
250 
253 {
254  if (auto txns = inboundTransactions_.getSet(setId, true))
255  {
256  return RCLTxSet{std::move(txns)};
257  }
258  return std::nullopt;
259 }
260 
261 bool
263 {
264  return !app_.openLedger().empty();
265 }
266 
269 {
270  return app_.getValidations().numTrustedForLedger(h);
271 }
272 
275  RCLCxLedger const& ledger,
276  LedgerHash const& h) const
277 {
278  RCLValidations& vals = app_.getValidations();
279  return vals.getNodesAfter(
280  RCLValidatedLedger(ledger.ledger_, vals.adaptor().journal()), h);
281 }
282 
283 uint256
285  uint256 ledgerID,
286  RCLCxLedger const& ledger,
288 {
289  RCLValidations& vals = app_.getValidations();
290  uint256 netLgr = vals.getPreferred(
291  RCLValidatedLedger{ledger.ledger_, vals.adaptor().journal()},
292  ledgerMaster_.getValidLedgerIndex());
293 
294  if (netLgr != ledgerID)
295  {
297  app_.getOPs().consensusViewChange();
298 
299  JLOG(j_.debug()) << Json::Compact(app_.getValidations().getJsonTrie());
300  }
301 
302  return netLgr;
303 }
304 
305 auto
307  RCLCxLedger const& ledger,
308  NetClock::time_point const& closeTime,
310 {
311  const bool wrongLCL = mode == ConsensusMode::wrongLedger;
312  const bool proposing = mode == ConsensusMode::proposing;
313 
314  notify(protocol::neCLOSING_LEDGER, ledger, !wrongLCL);
315 
316  auto const& prevLedger = ledger.ledger_;
317 
318  ledgerMaster_.applyHeldTransactions();
319  // Tell the ledger master not to acquire the ledger we're probably building
320  ledgerMaster_.setBuildingLedger(prevLedger->info().seq + 1);
321 
322  auto initialLedger = app_.openLedger().current();
323 
324  auto initialSet =
325  std::make_shared<SHAMap>(SHAMapType::TRANSACTION, app_.getNodeFamily());
326  initialSet->setUnbacked();
327 
328  // Build SHAMap containing all transactions in our open ledger
329  for (auto const& tx : initialLedger->txs)
330  {
331  JLOG(j_.trace()) << "Adding open ledger TX "
332  << tx.first->getTransactionID();
333  Serializer s(2048);
334  tx.first->add(s);
335  initialSet->addItem(
337  make_shamapitem(tx.first->getTransactionID(), s.slice()));
338  }
339 
340  // Add pseudo-transactions to the set
341  if (app_.config().standalone() || (proposing && !wrongLCL))
342  {
343  if (prevLedger->isFlagLedger())
344  {
345  // previous ledger was flag ledger, add fee and amendment
346  // pseudo-transactions
347  auto validations = app_.validators().negativeUNLFilter(
348  app_.getValidations().getTrustedForLedger(
349  prevLedger->info().parentHash, prevLedger->seq() - 1));
350  if (validations.size() >= app_.validators().quorum())
351  {
352  feeVote_->doVoting(prevLedger, validations, initialSet);
353  app_.getAmendmentTable().doVoting(
354  prevLedger, validations, initialSet);
355  }
356  }
357  else if (
358  prevLedger->isVotingLedger() &&
359  prevLedger->rules().enabled(featureNegativeUNL))
360  {
361  // previous ledger was a voting ledger,
362  // so the current consensus session is for a flag ledger,
363  // add negative UNL pseudo-transactions
364  nUnlVote_.doVoting(
365  prevLedger,
366  app_.validators().getTrustedMasterKeys(),
367  app_.getValidations(),
368  initialSet);
369  }
370  }
371 
372  // Now we need an immutable snapshot
373  initialSet = initialSet->snapShot(false);
374 
375  if (!wrongLCL)
376  {
377  LedgerIndex const seq = prevLedger->info().seq + 1;
379 
380  initialSet->visitLeaves(
381  [&proposed,
382  seq](boost::intrusive_ptr<SHAMapItem const> const& item) {
383  proposed.emplace_back(item->key(), seq);
384  });
385 
386  censorshipDetector_.propose(std::move(proposed));
387  }
388 
389  // Needed because of the move below.
390  auto const setHash = initialSet->getHash().as_uint256();
391 
392  return Result{
393  std::move(initialSet),
395  initialLedger->info().parentHash,
397  setHash,
398  closeTime,
399  app_.timeKeeper().closeTime(),
400  validatorKeys_.nodeID}};
401 }
402 
403 void
405  Result const& result,
406  RCLCxLedger const& prevLedger,
407  NetClock::duration const& closeResolution,
408  ConsensusCloseTimes const& rawCloseTimes,
409  ConsensusMode const& mode,
410  Json::Value&& consensusJson)
411 {
412  doAccept(
413  result,
414  prevLedger,
415  closeResolution,
416  rawCloseTimes,
417  mode,
418  std::move(consensusJson));
419 }
420 
421 void
423  Result const& result,
424  RCLCxLedger const& prevLedger,
425  NetClock::duration const& closeResolution,
426  ConsensusCloseTimes const& rawCloseTimes,
427  ConsensusMode const& mode,
428  Json::Value&& consensusJson)
429 {
430  app_.getJobQueue().addJob(
431  jtACCEPT,
432  "acceptLedger",
433  [=, this, cj = std::move(consensusJson)]() mutable {
434  // Note that no lock is held or acquired during this job.
435  // This is because generic Consensus guarantees that once a ledger
436  // is accepted, the consensus results and capture by reference state
437  // will not change until startRound is called (which happens via
438  // endConsensus).
439  this->doAccept(
440  result,
441  prevLedger,
442  closeResolution,
443  rawCloseTimes,
444  mode,
445  std::move(cj));
446  this->app_.getOPs().endConsensus();
447  });
448 }
449 
450 void
452  Result const& result,
453  RCLCxLedger const& prevLedger,
454  NetClock::duration closeResolution,
455  ConsensusCloseTimes const& rawCloseTimes,
456  ConsensusMode const& mode,
457  Json::Value&& consensusJson)
458 {
459  prevProposers_ = result.proposers;
460  prevRoundTime_ = result.roundTime.read();
461 
462  bool closeTimeCorrect;
463 
464  const bool proposing = mode == ConsensusMode::proposing;
465  const bool haveCorrectLCL = mode != ConsensusMode::wrongLedger;
466  const bool consensusFail = result.state == ConsensusState::MovedOn;
467 
468  auto consensusCloseTime = result.position.closeTime();
469 
470  if (consensusCloseTime == NetClock::time_point{})
471  {
472  // We agreed to disagree on the close time
473  using namespace std::chrono_literals;
474  consensusCloseTime = prevLedger.closeTime() + 1s;
475  closeTimeCorrect = false;
476  }
477  else
478  {
479  // We agreed on a close time
480  consensusCloseTime = effCloseTime(
481  consensusCloseTime, closeResolution, prevLedger.closeTime());
482  closeTimeCorrect = true;
483  }
484 
485  JLOG(j_.debug()) << "Report: Prop=" << (proposing ? "yes" : "no")
486  << " val=" << (validating_ ? "yes" : "no")
487  << " corLCL=" << (haveCorrectLCL ? "yes" : "no")
488  << " fail=" << (consensusFail ? "yes" : "no");
489  JLOG(j_.debug()) << "Report: Prev = " << prevLedger.id() << ":"
490  << prevLedger.seq();
491 
492  //--------------------------------------------------------------------------
493  std::set<TxID> failed;
494 
495  // We want to put transactions in an unpredictable but deterministic order:
496  // we use the hash of the set.
497  //
498  // FIXME: Use a std::vector and a custom sorter instead of CanonicalTXSet?
499  CanonicalTXSet retriableTxs{result.txns.map_->getHash().as_uint256()};
500 
501  JLOG(j_.debug()) << "Building canonical tx set: " << retriableTxs.key();
502 
503  for (auto const& item : *result.txns.map_)
504  {
505  try
506  {
507  retriableTxs.insert(
508  std::make_shared<STTx const>(SerialIter{item.slice()}));
509  JLOG(j_.debug()) << " Tx: " << item.key();
510  }
511  catch (std::exception const& ex)
512  {
513  failed.insert(item.key());
514  JLOG(j_.warn())
515  << " Tx: " << item.key() << " throws: " << ex.what();
516  }
517  }
518 
519  auto built = buildLCL(
520  prevLedger,
521  retriableTxs,
522  consensusCloseTime,
523  closeTimeCorrect,
524  closeResolution,
525  result.roundTime.read(),
526  failed);
527 
528  auto const newLCLHash = built.id();
529  JLOG(j_.debug()) << "Built ledger #" << built.seq() << ": " << newLCLHash;
530 
531  // Tell directly connected peers that we have a new LCL
532  notify(protocol::neACCEPTED_LEDGER, built, haveCorrectLCL);
533 
534  // As long as we're in sync with the network, attempt to detect attempts
535  // at censorship of transaction by tracking which ones don't make it in
536  // after a period of time.
537  if (haveCorrectLCL && result.state == ConsensusState::Yes)
538  {
540 
541  result.txns.map_->visitLeaves(
542  [&accepted](boost::intrusive_ptr<SHAMapItem const> const& item) {
543  accepted.push_back(item->key());
544  });
545 
546  // Track all the transactions which failed or were marked as retriable
547  for (auto const& r : retriableTxs)
548  failed.insert(r.first.getTXID());
549 
550  censorshipDetector_.check(
551  std::move(accepted),
552  [curr = built.seq(),
553  j = app_.journal("CensorshipDetector"),
554  &failed](uint256 const& id, LedgerIndex seq) {
555  if (failed.count(id))
556  return true;
557 
558  auto const wait = curr - seq;
559 
560  if (wait && (wait % censorshipWarnInternal == 0))
561  {
562  std::ostringstream ss;
563  ss << "Potential Censorship: Eligible tx " << id
564  << ", which we are tracking since ledger " << seq
565  << " has not been included as of ledger " << curr << ".";
566 
567  JLOG(j.warn()) << ss.str();
568  }
569 
570  return false;
571  });
572  }
573 
574  if (validating_)
575  validating_ = ledgerMaster_.isCompatible(
576  *built.ledger_, j_.warn(), "Not validating");
577 
578  if (validating_ && !consensusFail &&
579  app_.getValidations().canValidateSeq(built.seq()))
580  {
581  validate(built, result.txns, proposing);
582  JLOG(j_.info()) << "CNF Val " << newLCLHash;
583  }
584  else
585  JLOG(j_.info()) << "CNF buildLCL " << newLCLHash;
586 
587  // See if we can accept a ledger as fully-validated
588  ledgerMaster_.consensusBuilt(
589  built.ledger_, result.txns.id(), std::move(consensusJson));
590 
591  //-------------------------------------------------------------------------
592  {
593  // Apply disputed transactions that didn't get in
594  //
595  // The first crack of transactions to get into the new
596  // open ledger goes to transactions proposed by a validator
597  // we trust but not included in the consensus set.
598  //
599  // These are done first because they are the most likely
600  // to receive agreement during consensus. They are also
601  // ordered logically "sooner" than transactions not mentioned
602  // in the previous consensus round.
603  //
604  bool anyDisputes = false;
605  for (auto const& [_, dispute] : result.disputes)
606  {
607  (void)_;
608  if (!dispute.getOurVote())
609  {
610  // we voted NO
611  try
612  {
613  JLOG(j_.debug())
614  << "Test applying disputed transaction that did"
615  << " not get in " << dispute.tx().id();
616 
617  SerialIter sit(dispute.tx().tx_->slice());
618  auto txn = std::make_shared<STTx const>(sit);
619 
620  // Disputed pseudo-transactions that were not accepted
621  // can't be successfully applied in the next ledger
622  if (isPseudoTx(*txn))
623  continue;
624 
625  retriableTxs.insert(txn);
626 
627  anyDisputes = true;
628  }
629  catch (std::exception const& ex)
630  {
631  JLOG(j_.debug()) << "Failed to apply transaction we voted "
632  "NO on. Exception: "
633  << ex.what();
634  }
635  }
636  }
637 
638  // Build new open ledger
639  std::unique_lock lock{app_.getMasterMutex(), std::defer_lock};
640  std::unique_lock sl{ledgerMaster_.peekMutex(), std::defer_lock};
641  std::lock(lock, sl);
642 
643  auto const lastVal = ledgerMaster_.getValidatedLedger();
644  std::optional<Rules> rules;
645  if (lastVal)
646  rules = makeRulesGivenLedger(*lastVal, app_.config().features);
647  else
648  rules.emplace(app_.config().features);
649  app_.openLedger().accept(
650  app_,
651  *rules,
652  built.ledger_,
653  localTxs_.getTxSet(),
654  anyDisputes,
655  retriableTxs,
656  tapNONE,
657  "consensus",
658  [&](OpenView& view, beast::Journal j) {
659  // Stuff the ledger with transactions from the queue.
660  return app_.getTxQ().accept(app_, view);
661  });
662 
663  // Signal a potential fee change to subscribers after the open ledger
664  // is created
665  app_.getOPs().reportFeeChange();
666  }
667 
668  //-------------------------------------------------------------------------
669  {
670  ledgerMaster_.switchLCL(built.ledger_);
671 
672  // Do these need to exist?
673  assert(ledgerMaster_.getClosedLedger()->info().hash == built.id());
674  assert(app_.openLedger().current()->info().parentHash == built.id());
675  }
676 
677  //-------------------------------------------------------------------------
678  // we entered the round with the network,
679  // see how close our close time is to other node's
680  // close time reports, and update our clock.
681  if ((mode == ConsensusMode::proposing ||
683  !consensusFail)
684  {
685  auto closeTime = rawCloseTimes.self;
686 
687  JLOG(j_.info()) << "We closed at "
688  << closeTime.time_since_epoch().count();
689  using usec64_t = std::chrono::duration<std::uint64_t>;
690  usec64_t closeTotal =
691  std::chrono::duration_cast<usec64_t>(closeTime.time_since_epoch());
692  int closeCount = 1;
693 
694  for (auto const& [t, v] : rawCloseTimes.peers)
695  {
696  JLOG(j_.info()) << std::to_string(v) << " time votes for "
697  << std::to_string(t.time_since_epoch().count());
698  closeCount += v;
699  closeTotal +=
700  std::chrono::duration_cast<usec64_t>(t.time_since_epoch()) * v;
701  }
702 
703  closeTotal += usec64_t(closeCount / 2); // for round to nearest
704  closeTotal /= closeCount;
705 
706  // Use signed times since we are subtracting
707  using duration = std::chrono::duration<std::int32_t>;
709  auto offset = time_point{closeTotal} -
710  std::chrono::time_point_cast<duration>(closeTime);
711  JLOG(j_.info()) << "Our close offset is estimated at " << offset.count()
712  << " (" << closeCount << ")";
713 
714  app_.timeKeeper().adjustCloseTime(offset);
715  }
716 }
717 
718 void
720  protocol::NodeEvent ne,
721  RCLCxLedger const& ledger,
722  bool haveCorrectLCL)
723 {
724  protocol::TMStatusChange s;
725 
726  if (!haveCorrectLCL)
727  s.set_newevent(protocol::neLOST_SYNC);
728  else
729  s.set_newevent(ne);
730 
731  s.set_ledgerseq(ledger.seq());
732  s.set_networktime(app_.timeKeeper().now().time_since_epoch().count());
733  s.set_ledgerhashprevious(
734  ledger.parentID().begin(),
735  std::decay_t<decltype(ledger.parentID())>::bytes);
736  s.set_ledgerhash(
737  ledger.id().begin(), std::decay_t<decltype(ledger.id())>::bytes);
738 
739  std::uint32_t uMin, uMax;
740  if (!ledgerMaster_.getFullValidatedRange(uMin, uMax))
741  {
742  uMin = 0;
743  uMax = 0;
744  }
745  else
746  {
747  // Don't advertise ledgers we're not willing to serve
748  uMin = std::max(uMin, ledgerMaster_.getEarliestFetch());
749  }
750  s.set_firstseq(uMin);
751  s.set_lastseq(uMax);
752  app_.overlay().foreach(
753  send_always(std::make_shared<Message>(s, protocol::mtSTATUS_CHANGE)));
754  JLOG(j_.trace()) << "send status change to peer";
755 }
756 
759  RCLCxLedger const& previousLedger,
760  CanonicalTXSet& retriableTxs,
761  NetClock::time_point closeTime,
762  bool closeTimeCorrect,
763  NetClock::duration closeResolution,
764  std::chrono::milliseconds roundTime,
765  std::set<TxID>& failedTxs)
766 {
767  std::shared_ptr<Ledger> built = [&]() {
768  if (auto const replayData = ledgerMaster_.releaseReplay())
769  {
770  assert(replayData->parent()->info().hash == previousLedger.id());
771  return buildLedger(*replayData, tapNONE, app_, j_);
772  }
773  return buildLedger(
774  previousLedger.ledger_,
775  closeTime,
776  closeTimeCorrect,
777  closeResolution,
778  app_,
779  retriableTxs,
780  failedTxs,
781  j_);
782  }();
783 
784  // Update fee computations based on accepted txs
785  using namespace std::chrono_literals;
786  app_.getTxQ().processClosedLedger(app_, *built, roundTime > 5s);
787 
788  // And stash the ledger in the ledger master
789  if (ledgerMaster_.storeLedger(built))
790  JLOG(j_.debug()) << "Consensus built ledger we already had";
791  else if (app_.getInboundLedgers().find(built->info().hash))
792  JLOG(j_.debug()) << "Consensus built ledger we were acquiring";
793  else
794  JLOG(j_.debug()) << "Consensus built new ledger";
795  return RCLCxLedger{std::move(built)};
796 }
797 
798 void
800  RCLCxLedger const& ledger,
801  RCLTxSet const& txns,
802  bool proposing)
803 {
804  using namespace std::chrono_literals;
805 
806  auto validationTime = app_.timeKeeper().closeTime();
807  if (validationTime <= lastValidationTime_)
808  validationTime = lastValidationTime_ + 1s;
809  lastValidationTime_ = validationTime;
810 
811  if (!validatorKeys_.keys)
812  {
813  JLOG(j_.warn()) << "RCLConsensus::Adaptor::validate: ValidatorKeys "
814  "not set\n";
815  return;
816  }
817 
818  auto const& keys = *validatorKeys_.keys;
819 
820  auto v = std::make_shared<STValidation>(
821  lastValidationTime_,
822  keys.publicKey,
823  keys.secretKey,
824  validatorKeys_.nodeID,
825  [&](STValidation& v) {
826  v.setFieldH256(sfLedgerHash, ledger.id());
827  v.setFieldH256(sfConsensusHash, txns.id());
828 
829  v.setFieldU32(sfLedgerSequence, ledger.seq());
830 
831  if (proposing)
832  v.setFlag(vfFullValidation);
833 
834  if (ledger.ledger_->rules().enabled(featureHardenedValidations))
835  {
836  // Attest to the hash of what we consider to be the last fully
837  // validated ledger. This may be the hash of the ledger we are
838  // validating here, and that's fine.
839  if (auto const vl = ledgerMaster_.getValidatedLedger())
840  v.setFieldH256(sfValidatedHash, vl->info().hash);
841 
842  v.setFieldU64(sfCookie, valCookie_);
843 
844  // Report our server version every flag ledger:
845  if (ledger.ledger_->isVotingLedger())
846  v.setFieldU64(
847  sfServerVersion, BuildInfo::getEncodedVersion());
848  }
849 
850  // Report our load
851  {
852  auto const& ft = app_.getFeeTrack();
853  auto const fee = std::max(ft.getLocalFee(), ft.getClusterFee());
854  if (fee > ft.getLoadBase())
855  v.setFieldU32(sfLoadFee, fee);
856  }
857 
858  // If the next ledger is a flag ledger, suggest fee changes and
859  // new features:
860  if (ledger.ledger_->isVotingLedger())
861  {
862  // Fees:
863  feeVote_->doValidation(
864  ledger.ledger_->fees(), ledger.ledger_->rules(), v);
865 
866  // Amendments
867  // FIXME: pass `v` and have the function insert the array
868  // directly?
869  auto const amendments = app_.getAmendmentTable().doValidation(
870  getEnabledAmendments(*ledger.ledger_));
871 
872  if (!amendments.empty())
873  v.setFieldV256(
874  sfAmendments, STVector256(sfAmendments, amendments));
875  }
876  });
877 
878  auto const serialized = v->getSerialized();
879 
880  // suppress it if we receive it
881  app_.getHashRouter().addSuppression(sha512Half(makeSlice(serialized)));
882 
883  handleNewValidation(app_, v, "local");
884 
885  // Broadcast to all our peers:
886  protocol::TMValidation val;
887  val.set_validation(serialized.data(), serialized.size());
888  app_.overlay().broadcast(val);
889 
890  // Publish to all our subscribers:
891  app_.getOPs().pubValidation(v);
892 }
893 
894 void
896 {
897  JLOG(j_.info()) << "Consensus mode change before=" << to_string(before)
898  << ", after=" << to_string(after);
899 
900  // If we were proposing but aren't any longer, we need to reset the
901  // censorship tracking to avoid bogus warnings.
902  if ((before == ConsensusMode::proposing ||
903  before == ConsensusMode::observing) &&
904  before != after)
905  censorshipDetector_.reset();
906 
907  mode_ = after;
908 }
909 
911 RCLConsensus::getJson(bool full) const
912 {
913  Json::Value ret;
914  {
916  ret = consensus_.getJson(full);
917  }
918  ret["validating"] = adaptor_.validating();
919  return ret;
920 }
921 
922 void
924 {
925  try
926  {
928  consensus_.timerEntry(now);
929  }
930  catch (SHAMapMissingNode const& mn)
931  {
932  // This should never happen
933  JLOG(j_.error()) << "During consensus timerEntry: " << mn.what();
934  Rethrow();
935  }
936 }
937 
938 void
940 {
941  try
942  {
944  consensus_.gotTxSet(now, txSet);
945  }
946  catch (SHAMapMissingNode const& mn)
947  {
948  // This should never happen
949  JLOG(j_.error()) << "During consensus gotTxSet: " << mn.what();
950  Rethrow();
951  }
952 }
953 
955 
956 void
958  NetClock::time_point const& now,
960 {
962  consensus_.simulate(now, consensusDelay);
963 }
964 
965 bool
967  NetClock::time_point const& now,
968  RCLCxPeerPos const& newProposal)
969 {
971  return consensus_.peerProposal(now, newProposal);
972 }
973 
974 bool
976  RCLCxLedger const& prevLgr,
977  hash_set<NodeID> const& nowTrusted)
978 {
979  // We have a key, we do not want out of sync validations after a restart
980  // and are not amendment blocked.
981  validating_ = validatorKeys_.keys &&
982  prevLgr.seq() >= app_.getMaxDisallowedLedger() &&
983  !app_.getOPs().isBlocked();
984 
985  // If we are not running in standalone mode and there's a configured UNL,
986  // check to make sure that it's not expired.
987  if (validating_ && !app_.config().standalone() && app_.validators().count())
988  {
989  auto const when = app_.validators().expires();
990 
991  if (!when || *when < app_.timeKeeper().now())
992  {
993  JLOG(j_.error()) << "Voluntarily bowing out of consensus process "
994  "because of an expired validator list.";
995  validating_ = false;
996  }
997  }
998 
999  const bool synced = app_.getOPs().getOperatingMode() == OperatingMode::FULL;
1000 
1001  if (validating_)
1002  {
1003  JLOG(j_.info()) << "Entering consensus process, validating, synced="
1004  << (synced ? "yes" : "no");
1005  }
1006  else
1007  {
1008  // Otherwise we just want to monitor the validation process.
1009  JLOG(j_.info()) << "Entering consensus process, watching, synced="
1010  << (synced ? "yes" : "no");
1011  }
1012 
1013  // Notify inbound ledgers that we are starting a new round
1014  inboundTransactions_.newRound(prevLgr.seq());
1015 
1016  // Notify NegativeUNLVote that new validators are added
1017  if (prevLgr.ledger_->rules().enabled(featureNegativeUNL) &&
1018  !nowTrusted.empty())
1019  nUnlVote_.newValidators(prevLgr.seq() + 1, nowTrusted);
1020 
1021  // propose only if we're in sync with the network (and validating)
1022  return validating_ && synced;
1023 }
1024 
1025 bool
1027 {
1028  return ledgerMaster_.haveValidated();
1029 }
1030 
1033 {
1034  return ledgerMaster_.getValidLedgerIndex();
1035 }
1036 
1039 {
1040  return app_.validators().getQuorumKeys();
1041 }
1042 
1045  Ledger_t::Seq const seq,
1046  hash_set<RCLConsensus::Adaptor::NodeKey_t>& trustedKeys) const
1047 {
1048  return app_.getValidations().laggards(seq, trustedKeys);
1049 }
1050 
1051 bool
1053 {
1054  return validatorKeys_.keys.has_value();
1055 }
1056 
1057 void
1059 {
1060  if (!positions && app_.getOPs().isFull())
1061  app_.getOPs().setMode(OperatingMode::CONNECTED);
1062 }
1063 
1064 void
1066  NetClock::time_point const& now,
1067  RCLCxLedger::ID const& prevLgrId,
1068  RCLCxLedger const& prevLgr,
1069  hash_set<NodeID> const& nowUntrusted,
1070  hash_set<NodeID> const& nowTrusted)
1071 {
1073  consensus_.startRound(
1074  now,
1075  prevLgrId,
1076  prevLgr,
1077  nowUntrusted,
1078  adaptor_.preStartRound(prevLgr, nowTrusted));
1079 }
1080 } // namespace ripple
ripple::Application
Definition: Application.h:116
ripple::RCLCxPeerPos
A peer's signed, proposed position for use in RCLConsensus.
Definition: RCLCxPeerPos.h:43
ripple::HashPrefix::ledgerMaster
@ ledgerMaster
ledger master data for signing
std::lock
T lock(T... args)
ripple::makeSlice
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Definition: Slice.h:241
ripple::InboundLedger::Reason::CONSENSUS
@ CONSENSUS
ripple::RCLCxPeerPos::signature
Slice signature() const
Signature of the proposal (not necessarily verified)
Definition: RCLCxPeerPos.h:71
std::shared_ptr< Ledger >
ripple::ConsensusMode::proposing
@ proposing
We are normal participant in consensus and propose our position.
ripple::RCLConsensus::getJson
Json::Value getJson(bool full) const
Definition: RCLConsensus.cpp:911
std::exception
STL class.
ripple::RCLConsensus::startRound
void startRound(NetClock::time_point const &now, RCLCxLedger::ID const &prevLgrId, RCLCxLedger const &prevLgr, hash_set< NodeID > const &nowUntrusted, hash_set< NodeID > const &nowTrusted)
Adjust the set of trusted validators and kick-off the next round of consensus.
Definition: RCLConsensus.cpp:1065
beast::Journal::trace
Stream trace() const
Severity stream access functions.
Definition: Journal.h:308
ripple::RCLConsensus::Adaptor::acquireLedger
std::optional< RCLCxLedger > acquireLedger(LedgerHash const &hash)
Attempt to acquire a specific ledger.
Definition: RCLConsensus.cpp:123
ripple::RCLConsensus::consensus_
Consensus< Adaptor > consensus_
Definition: RCLConsensus.h:530
ripple::jtACCEPT
@ jtACCEPT
Definition: Job.h:74
std::unordered_set
STL class.
std::pair
ripple::SHAMapType::TRANSACTION
@ TRANSACTION
ripple::RCLConsensus::Adaptor::preStartRound
bool preStartRound(RCLCxLedger const &prevLedger, hash_set< NodeID > const &nowTrusted)
Called before kicking off a new consensus round.
Definition: RCLConsensus.cpp:975
ripple::make_shamapitem
boost::intrusive_ptr< SHAMapItem > make_shamapitem(uint256 const &tag, Slice data)
Definition: SHAMapItem.h:160
ripple::RCLConsensus::mutex_
std::recursive_mutex mutex_
Definition: RCLConsensus.h:527
ripple::LedgerMaster
Definition: LedgerMaster.h:70
ripple::ConsensusMode::wrongLedger
@ wrongLedger
We have the wrong ledger and are attempting to acquire it.
Json::Compact
Decorator for streaming out compact json.
Definition: json_writer.h:316
ripple::RCLConsensus::Adaptor::hasOpenTransactions
bool hasOpenTransactions() const
Whether the open ledger has any transactions.
Definition: RCLConsensus.cpp:262
std::vector< TxIDSeq >
ripple::ConsensusState::Yes
@ Yes
We have consensus along with the network.
ripple::RCLConsensus::gotTxSet
void gotTxSet(NetClock::time_point const &now, RCLTxSet const &txSet)
Definition: RCLConsensus.cpp:939
std::chrono::duration
ripple::crypto_prng
csprng_engine & crypto_prng()
The default cryptographically secure PRNG.
Definition: csprng.cpp:99
ripple::toBase58
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition: AccountID.cpp:104
ripple::RCLConsensus::Adaptor::getPrevLedger
uint256 getPrevLedger(uint256 ledgerID, RCLCxLedger const &ledger, ConsensusMode mode)
Get the ID of the previous ledger/last closed ledger(LCL) on the network.
Definition: RCLConsensus.cpp:284
std::optional::emplace
T emplace(T... args)
ripple::RCLTxSet::map_
std::shared_ptr< SHAMap > map_
The SHAMap representing the transactions.
Definition: RCLCxTx.h:188
std::stringstream
STL class.
beast::Journal::warn
Stream warn() const
Definition: Journal.h:326
std::lock_guard
STL class.
ripple::RCLConsensus::j_
const beast::Journal j_
Definition: RCLConsensus.h:531
ripple::PublicKey::slice
Slice slice() const noexcept
Definition: PublicKey.h:123
ripple::ConsensusResult::roundTime
ConsensusTimer roundTime
Definition: ConsensusTypes.h:233
ripple::RCLConsensus::timerEntry
void timerEntry(NetClock::time_point const &now)
Definition: RCLConsensus.cpp:923
ripple::RCLValidationsAdaptor::journal
beast::Journal journal() const
Definition: RCLValidations.h:225
ripple::RCLConsensus::Adaptor::onClose
Result onClose(RCLCxLedger const &ledger, NetClock::time_point const &closeTime, ConsensusMode mode)
Close the open ledger and return initial consensus position.
Definition: RCLConsensus.cpp:306
ripple::RCLCxLedger::closeTime
NetClock::time_point closeTime() const
The close time of this ledger.
Definition: RCLCxLedger.h:96
ripple::tapNONE
@ tapNONE
Definition: ApplyView.h:30
ripple::RCLValidatedLedger
Wraps a ledger instance for use in generic Validations LedgerTrie.
Definition: RCLValidations.h:153
ripple::ConsensusResult
Encapsulates the result of consensus.
Definition: ConsensusTypes.h:201
algorithm
ripple::SHAMapNodeType::tnTRANSACTION_NM
@ tnTRANSACTION_NM
ripple::ValidatorKeys
Validator keys and manifest as set in configuration file.
Definition: ValidatorKeys.h:36
ripple::RCLCxLedger::seq
Seq const & seq() const
Sequence number of the ledger.
Definition: RCLCxLedger.h:61
ripple::STValidation
Definition: STValidation.h:44
ripple::RCLCxLedger::parentID
ID const & parentID() const
Unique identifier (hash) of this ledger's parent.
Definition: RCLCxLedger.h:75
ripple::CanonicalTXSet
Holds transactions which were deferred to the next pass of consensus.
Definition: CanonicalTXSet.h:38
ripple::send_always
Sends a message to all peers.
Definition: predicates.h:31
ripple::RCLCxPeerPos::proposal
Proposal const & proposal() const
Definition: RCLCxPeerPos.h:91
ripple::RCLConsensus::Adaptor::doAccept
void doAccept(Result const &result, RCLCxLedger const &prevLedger, NetClock::duration closeResolution, ConsensusCloseTimes const &rawCloseTimes, ConsensusMode const &mode, Json::Value &&consensusJson)
Accept a new ledger based on the given transactions.
Definition: RCLConsensus.cpp:451
ripple::RCLConsensus::RCLConsensus
RCLConsensus(Application &app, std::unique_ptr< FeeVote > &&feeVote, LedgerMaster &ledgerMaster, LocalTxs &localTxs, InboundTransactions &inboundTransactions, Consensus< Adaptor >::clock_type const &clock, ValidatorKeys const &validatorKeys, beast::Journal journal)
Constructor.
Definition: RCLConsensus.cpp:52
ripple::SHAMapMissingNode
Definition: SHAMapMissingNode.h:55
ripple::RCLConsensus::simulate
void simulate(NetClock::time_point const &now, std::optional< std::chrono::milliseconds > consensusDelay)
Definition: RCLConsensus.cpp:957
ripple::RCLConsensus::Adaptor::onAccept
void onAccept(Result const &result, RCLCxLedger const &prevLedger, NetClock::duration const &closeResolution, ConsensusCloseTimes const &rawCloseTimes, ConsensusMode const &mode, Json::Value &&consensusJson)
Process the accepted ledger.
Definition: RCLConsensus.cpp:422
ripple::ConsensusMode::observing
@ observing
We are observing peer positions, but not proposing our position.
ripple::base_uint< 256 >
ripple::RCLConsensus::Adaptor::updateOperatingMode
void updateOperatingMode(std::size_t const positions) const
Update operating mode based on current peer positions.
Definition: RCLConsensus.cpp:1058
ripple::isPseudoTx
bool isPseudoTx(STObject const &tx)
Check whether a transaction is a pseudo-transaction.
Definition: STTx.cpp:576
ripple::RCLConsensus::Adaptor::haveValidated
bool haveValidated() const
Definition: RCLConsensus.cpp:1026
ripple::RCLConsensus::Adaptor::laggards
std::size_t laggards(Ledger_t::Seq const seq, hash_set< NodeKey_t > &trustedKeys) const
Definition: RCLConsensus.cpp:1044
ripple::rand_int
std::enable_if_t< std::is_integral< Integral >::value &&detail::is_engine< Engine >::value, Integral > rand_int(Engine &engine, Integral min, Integral max)
Return a uniformly distributed random integer.
Definition: ripple/basics/random.h:115
ripple::RCLConsensus::Adaptor::share
void share(RCLCxPeerPos const &peerPos)
Share the given proposal with all peers.
Definition: RCLConsensus.cpp:156
ripple::OperatingMode::CONNECTED
@ CONNECTED
convinced we are talking to the network
ripple::ConsensusResult::state
ConsensusState state
Definition: ConsensusTypes.h:237
ripple::ConsensusTimer::read
std::chrono::milliseconds read() const
Definition: ConsensusTypes.h:142
ripple::signDigest
Buffer signDigest(PublicKey const &pk, SecretKey const &sk, uint256 const &digest)
Generate a signature for a message digest.
Definition: SecretKey.cpp:212
ripple::RCLConsensus::peerProposal
bool peerProposal(NetClock::time_point const &now, RCLCxPeerPos const &newProposal)
Definition: RCLConsensus.cpp:966
ripple::Rethrow
void Rethrow()
Rethrow the exception currently being handled.
Definition: contract.h:48
ripple::RCLTxSet
Represents a set of transactions in RCLConsensus.
Definition: RCLCxTx.h:65
ripple::RCLConsensus::Adaptor::validate
void validate(RCLCxLedger const &ledger, RCLTxSet const &txns, bool proposing)
Validate the given ledger and share with peers as necessary.
Definition: RCLConsensus.cpp:799
ripple::Validations::getNodesAfter
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.
Definition: Validations.h:971
std::unique_lock
STL class.
ripple::RCLTxSet::id
ID id() const
The unique ID/hash of the transaction set.
Definition: RCLCxTx.h:155
std::to_string
T to_string(T... args)
ripple::Serializer::slice
Slice slice() const noexcept
Definition: Serializer.h:64
ripple::RCLConsensus::Adaptor::Adaptor
Adaptor(Application &app, std::unique_ptr< FeeVote > &&feeVote, LedgerMaster &ledgerMaster, LocalTxs &localTxs, InboundTransactions &inboundTransactions, ValidatorKeys const &validatorKeys, beast::Journal journal)
Definition: RCLConsensus.cpp:74
beast::Journal::error
Stream error() const
Definition: Journal.h:332
beast::Journal::info
Stream info() const
Definition: Journal.h:320
std::chrono::time_point
ripple::HashPrefix::proposal
@ proposal
proposal for signing
ripple::RCLCxLedger::id
ID const & id() const
Unique identifier (hash) of this ledger.
Definition: RCLCxLedger.h:68
ripple::RCLConsensus::mode
ConsensusMode mode() const
Definition: RCLConsensus.h:463
ripple::LocalTxs
Definition: LocalTxs.h:33
ripple::SerialIter
Definition: Serializer.h:311
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
std::uint32_t
ripple::RCLConsensus::Adaptor::notify
void notify(protocol::NodeEvent ne, RCLCxLedger const &ledger, bool haveCorrectLCL)
Notify peers of a consensus state change.
Definition: RCLConsensus.cpp:719
ripple::ConsensusState::MovedOn
@ MovedOn
The network has consensus without us.
ripple::RCLConsensus::adaptor_
Adaptor adaptor_
Definition: RCLConsensus.h:529
ripple::RCLConsensus::Adaptor::validator
bool validator() const
Whether I am a validator.
Definition: RCLConsensus.cpp:1052
beast::abstract_clock< std::chrono::steady_clock >
ripple::proposalUniqueId
uint256 proposalUniqueId(uint256 const &proposeHash, uint256 const &previousLedger, std::uint32_t proposeSeq, NetClock::time_point closeTime, Slice const &publicKey, Slice const &signature)
Calculate a unique identifier for a signed proposal.
Definition: RCLCxPeerPos.cpp:66
ripple::RCLConsensus::Adaptor::acquireTxSet
std::optional< RCLTxSet > acquireTxSet(RCLTxSet::ID const &setId)
Acquire the transaction set associated with a proposal.
Definition: RCLConsensus.cpp:252
ripple::RCLConsensus::Adaptor::buildLCL
RCLCxLedger buildLCL(RCLCxLedger const &previousLedger, CanonicalTXSet &retriableTxs, NetClock::time_point closeTime, bool closeTimeCorrect, NetClock::duration closeResolution, std::chrono::milliseconds roundTime, std::set< TxID > &failedTxs)
Build the new last closed ledger.
Definition: RCLConsensus.cpp:758
ripple::RCLCxPeerPos::publicKey
PublicKey const & publicKey() const
Public key of peer that sent the proposal.
Definition: RCLCxPeerPos.h:78
std::decay_t
ripple::RCLConsensus::Adaptor::onModeChange
void onModeChange(ConsensusMode before, ConsensusMode after)
Notified of change in consensus mode.
Definition: RCLConsensus.cpp:895
ripple::ManifestDisposition::accepted
@ accepted
Manifest is valid.
ripple::Serializer
Definition: Serializer.h:40
ripple::RCLCxLedger
Represents a ledger in RCLConsensus.
Definition: RCLCxLedger.h:35
ripple::ConsensusProposal::closeTime
NetClock::time_point const & closeTime() const
The current position on the consensus close time.
Definition: ConsensusProposal.h:127
std::vector::emplace_back
T emplace_back(T... args)
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::ConsensusMode
ConsensusMode
Represents how a node currently participates in Consensus.
Definition: ConsensusTypes.h:55
ripple::RCLConsensus::Adaptor::getValidLedgerIndex
LedgerIndex getValidLedgerIndex() const
Definition: RCLConsensus.cpp:1032
ripple::ShardState::acquire
@ acquire
ripple::base_uint::begin
iterator begin()
Definition: base_uint.h:133
std
STL namespace.
ripple::featureNegativeUNL
const uint256 featureNegativeUNL
std::set::insert
T insert(T... args)
ripple::sha512Half
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition: digest.h:216
ripple::ConsensusResult::position
Proposal_t position
Our proposed position on transactions/close time.
Definition: ConsensusTypes.h:224
ripple::ConsensusProposal< NodeID, uint256, uint256 >::seqJoin
static const std::uint32_t seqJoin
Definition: ConsensusProposal.h:61
ripple::buildLedger
std::shared_ptr< Ledger > buildLedger(std::shared_ptr< Ledger const > const &parent, NetClock::time_point closeTime, const bool closeTimeCorrect, NetClock::duration closeResolution, Application &app, CanonicalTXSet &txns, std::set< TxID > &failedTxs, beast::Journal j)
Build a new ledger by applying consensus transactions.
Definition: BuildLedger.cpp:178
ripple::makeRulesGivenLedger
Rules makeRulesGivenLedger(DigestAwareReadView const &ledger, Rules const &current)
Definition: ReadView.cpp:69
std::unordered_set::empty
T empty(T... args)
ripple::Validations::getPreferred
std::optional< std::pair< Seq, ID > > getPreferred(Ledger const &curr)
Return the sequence number and ID of the preferred working ledger.
Definition: Validations.h:847
ripple::TokenType::NodePublic
@ NodePublic
ripple::RCLConsensus::Adaptor::proposersValidated
std::size_t proposersValidated(LedgerHash const &h) const
Number of proposers that have validated the given ledger.
Definition: RCLConsensus.cpp:268
ripple::Validations< RCLValidationsAdaptor >
ripple::RCLCxPeerPos::suppressionID
uint256 const & suppressionID() const
Unique id used by hash router to suppress duplicates.
Definition: RCLCxPeerPos.h:85
std::optional
mutex
ripple::ConsensusResult::txns
TxSet_t txns
The set of transactions consensus agrees go in the ledger.
Definition: ConsensusTypes.h:221
beast::Journal::debug
Stream debug() const
Definition: Journal.h:314
ripple::after
static bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
Definition: Escrow.cpp:88
std::size_t
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:38
ripple::RCLCxLedger::ledger_
std::shared_ptr< Ledger const > ledger_
The ledger instance.
Definition: RCLCxLedger.h:120
ripple::jtADVANCE
@ jtADVANCE
Definition: Job.h:68
std::max
T max(T... args)
ripple::RCLCxTx
Represents a transaction in RCLConsensus.
Definition: RCLCxTx.h:35
ripple::Validations::adaptor
Adaptor const & adaptor() const
Return the adaptor instance.
Definition: Validations.h:586
ripple::RCLCxTx::tx_
boost::intrusive_ptr< SHAMapItem const > tx_
The SHAMapItem that represents the transaction.
Definition: RCLCxTx.h:57
ripple::RCLCxTx::id
ID const & id() const
The unique identifier/hash of the transaction.
Definition: RCLCxTx.h:51
std::unique_ptr
STL class.
ripple::RCLConsensus::Adaptor::propose
void propose(RCLCxPeerPos::Proposal const &proposal)
Propose the given position to my peers.
Definition: RCLConsensus.cpp:201
ripple::RCLConsensus::Adaptor::proposersFinished
std::size_t proposersFinished(RCLCxLedger const &ledger, LedgerHash const &h) const
Number of proposers that have validated a ledger descended from requested ledger.
Definition: RCLConsensus.cpp:274
std::numeric_limits
ripple::RCLConsensus::Adaptor::onForceAccept
void onForceAccept(Result const &result, RCLCxLedger const &prevLedger, NetClock::duration const &closeResolution, ConsensusCloseTimes const &rawCloseTimes, ConsensusMode const &mode, Json::Value &&consensusJson)
Process the accepted ledger that was a result of simulation/force accept.
Definition: RCLConsensus.cpp:404
std::set
STL class.
ripple::RCLConsensus::Adaptor::getQuorumKeys
std::pair< std::size_t, hash_set< NodeKey_t > > getQuorumKeys() const
Definition: RCLConsensus.cpp:1038
ripple::handleNewValidation
void handleNewValidation(Application &app, std::shared_ptr< STValidation > const &val, std::string const &source)
Handle a new validation.
Definition: RCLValidations.cpp:152
ripple::RCLConsensus::Adaptor::validating
bool validating() const
Definition: RCLConsensus.h:109
std::exception::what
T what(T... args)
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
ripple::ConsensusCloseTimes
Stores the set of initial close times.
Definition: ConsensusTypes.h:174
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::ConsensusResult::proposers
std::size_t proposers
Definition: ConsensusTypes.h:240
ripple::InboundTransactions
Manages the acquisition and lifetime of transaction sets.
Definition: InboundTransactions.h:35
ripple::ConsensusProposal< NodeID, uint256, uint256 >
ripple::OperatingMode::FULL
@ FULL
we have the ledger and can even validate