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