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