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