xrpld
Loading...
Searching...
No Matches
RCLConsensus.h
1#pragma once
2
3#include <xrpld/app/consensus/RCLCxLedger.h>
4#include <xrpld/app/consensus/RCLCxPeerPos.h>
5#include <xrpld/app/consensus/RCLCxTx.h>
6#include <xrpld/app/main/Application.h>
7#include <xrpld/app/misc/FeeVote.h>
8#include <xrpld/app/misc/NegativeUNLVote.h>
9
10#include <xrpl/basics/UnorderedContainers.h>
11#include <xrpl/basics/base_uint.h>
12#include <xrpl/basics/chrono.h>
13#include <xrpl/beast/utility/Journal.h>
14#include <xrpl/consensus/CensorshipDetector.h>
15#include <xrpl/consensus/Consensus.h>
16#include <xrpl/consensus/ConsensusParms.h>
17#include <xrpl/consensus/ConsensusTypes.h>
18#include <xrpl/json/json_value.h>
19#include <xrpl/ledger/CanonicalTXSet.h>
20#include <xrpl/protocol/Protocol.h>
21#include <xrpl/protocol/PublicKey.h>
22#include <xrpl/protocol/RippleLedgerHash.h>
23#include <xrpl/protocol/UintTypes.h>
24
25#include <xrpl.pb.h>
26
27#include <atomic>
28#include <chrono>
29#include <cstddef>
30#include <cstdint>
31#include <memory>
32#include <mutex>
33#include <optional>
34#include <set>
35#include <sstream>
36#include <string>
37#include <utility>
38
39namespace xrpl {
40
42class LocalTxs;
43class LedgerMaster;
44class ValidatorKeys;
45
50{
54 static constexpr unsigned int kCensorshipWarnInternal = 15;
55
56 // Implements the Adaptor template interface required by Consensus.
57 class Adaptor
58 {
65
66 // If the server is validating, the necessary keying information:
68
69 // A randomly selected non-zero value used to tag our validations
71
72 // Ledger we most recently needed to acquire
75
76 // The timestamp of the last validation we used
78
79 // These members are queried via public accessors and are atomic for
80 // thread safety.
85
88
89 public:
95
97
98 Adaptor(
99 Application& app,
100 std::unique_ptr<FeeVote>&& feeVote,
101 LedgerMaster& ledgerMaster,
102 LocalTxs& localTxs,
103 InboundTransactions& inboundTransactions,
104 ValidatorKeys const& validatorKeys,
105 beast::Journal journal);
106
107 bool
109 {
110 return validating_;
111 }
112
115 {
116 return prevProposers_;
117 }
118
121 {
122 return prevRoundTime_;
123 }
124
126 mode() const
127 {
128 return mode_;
129 }
130
138 bool
139 preStartRound(RCLCxLedger const& prevLedger, hash_set<NodeID> const& nowTrusted);
140
141 bool
142 haveValidated() const;
143
145 getValidLedgerIndex() const;
146
148 getQuorumKeys() const;
149
151 laggards(Ledger_t::Seq const seq, hash_set<NodeKey_t>& trustedKeys) const;
152
158 bool
159 validator() const;
160
169 void
170 updateOperatingMode(std::size_t const positions) const;
171
175 ConsensusParms const&
176 parms() const
177 {
178 return parms_;
179 }
180
181 private:
182 //---------------------------------------------------------------------
183 // The following members implement the generic Consensus requirements
184 // and are marked private to indicate ONLY Consensus<Adaptor> will call
185 // them (via friendship). Since they are called only from
186 // Consensus<Adaptor> methods and since RCLConsensus::consensus_ should
187 // only be accessed under lock, these will only be called under lock.
188 //
189 // In general, the idea is that there is only ONE thread that is running
190 // consensus code at anytime. The only special case is the dispatched
191 // onAccept call, which does not take a lock and relies on Consensus not
192 // changing state until a future call to startRound.
193 friend class Consensus<Adaptor>;
194
204 acquireLedger(LedgerHash const& hash);
205
211 void
212 share(RCLCxPeerPos const& peerPos);
213
221 void
222 share(RCLCxTx const& tx);
223
234 acquireTxSet(RCLTxSet::ID const& setId);
235
239 bool
240 hasOpenTransactions() const;
241
249 proposersValidated(LedgerHash const& h) const;
250
261 proposersFinished(RCLCxLedger const& ledger, LedgerHash const& h) const;
262
268 void
269 propose(RCLCxPeerPos::Proposal const& proposal);
270
276 void
277 share(RCLTxSet const& txns);
278
291 uint256
292 getPrevLedger(uint256 ledgerID, RCLCxLedger const& ledger, ConsensusMode mode);
293
300 void
302
311 Result
312 onClose(
313 RCLCxLedger const& ledger,
314 NetClock::time_point const& closeTime,
316
331 void
332 onAccept(
333 Result const& result,
334 RCLCxLedger const& prevLedger,
335 NetClock::duration const& closeResolution,
336 ConsensusCloseTimes const& rawCloseTimes,
337 ConsensusMode const& mode,
338 json::Value&& consensusJson,
339 bool const validating);
340
347 void
349 Result const& result,
350 RCLCxLedger const& prevLedger,
351 NetClock::duration const& closeResolution,
352 ConsensusCloseTimes const& rawCloseTimes,
353 ConsensusMode const& mode,
354 json::Value&& consensusJson);
355
363 void
364 notify(protocol::NodeEvent ne, RCLCxLedger const& ledger, bool haveCorrectLCL);
365
371 void
372 doAccept(
373 Result const& result,
374 RCLCxLedger const& prevLedger,
375 NetClock::duration closeResolution,
376 ConsensusCloseTimes const& rawCloseTimes,
377 ConsensusMode const& mode,
378 json::Value&& consensusJson);
379
403 buildLCL(
404 RCLCxLedger const& previousLedger,
405 CanonicalTXSet& retriableTxs,
406 NetClock::time_point closeTime,
407 bool closeTimeCorrect,
408 NetClock::duration closeResolution,
410 std::set<TxID>& failedTxs);
411
423 void
424 validate(RCLCxLedger const& ledger, RCLTxSet const& txns, bool proposing);
425 };
426
427public:
432 Application& app,
433 std::unique_ptr<FeeVote>&& feeVote,
434 LedgerMaster& ledgerMaster,
435 LocalTxs& localTxs,
436 InboundTransactions& inboundTransactions,
438 ValidatorKeys const& validatorKeys,
439 beast::Journal journal);
440
441 RCLConsensus(RCLConsensus const&) = delete;
442
444 operator=(RCLConsensus const&) = delete;
445
449 bool
451 {
452 return adaptor_.validating();
453 }
454
461 {
462 return adaptor_.prevProposers();
463 }
464
475 {
476 return adaptor_.prevRoundTime();
477 }
478
483 mode() const
484 {
485 return adaptor_.mode();
486 }
487
489 phase() const
490 {
491 return consensus_.phase();
492 }
493
498 getJson(bool full) const;
499
504 void
506 NetClock::time_point const& now,
507 RCLCxLedger::ID const& prevLgrId,
508 RCLCxLedger const& prevLgr,
509 hash_set<NodeID> const& nowUntrusted,
510 hash_set<NodeID> const& nowTrusted,
512
516 void
518 NetClock::time_point const& now,
519 std::unique_ptr<std::stringstream> const& clog = {});
520
524 void
525 gotTxSet(NetClock::time_point const& now, RCLTxSet const& txSet);
526
532 {
533 std::scoped_lock const _{mutex_};
534 return consensus_.prevLedgerID();
535 }
536
540 void
541 simulate(
542 NetClock::time_point const& now,
544
548 bool
549 peerProposal(NetClock::time_point const& now, RCLCxPeerPos const& newProposal);
550
551 ConsensusParms const&
552 parms() const
553 {
554 return adaptor_.parms();
555 }
556
557private:
558 // Since Consensus does not provide intrinsic thread-safety, this mutex
559 // guards all calls to consensus_. adaptor_ uses atomics internally
560 // to allow concurrent access of its data members that have getters.
562
566};
567
579{
583 std::chrono::steady_clock::time_point start_;
584
585public:
586 explicit RclConsensusLogger(char const* label, bool validating, beast::Journal j);
588
591 {
592 return ss_;
593 }
594};
595} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:44
Represents a JSON value.
Definition json_value.h:117
Holds transactions which were deferred to the next pass of consensus.
Generic implementation of consensus algorithm.
Definition Consensus.h:290
beast::AbstractClock< std::chrono::steady_clock > clock_type
Clock type for measuring time within the consensus code.
Definition Consensus.h:328
Manages the acquisition and lifetime of transaction sets.
Manager to create NegativeUNL votes.
std::chrono::time_point< NetClock > time_point
Definition chrono.h:48
std::chrono::duration< rep, period > duration
Definition chrono.h:47
A public key.
Definition PublicKey.h:53
InboundTransactions & inboundTransactions_
CensorshipDetector< TxID, LedgerIndex > censorshipDetector_
Result onClose(RCLCxLedger const &ledger, NetClock::time_point const &closeTime, ConsensusMode mode)
Close the open ledger and return initial consensus position.
bool preStartRound(RCLCxLedger const &prevLedger, hash_set< NodeID > const &nowTrusted)
Called before kicking off a new consensus round.
bool validator() const
Whether I am a validator.
LedgerIndex getValidLedgerIndex() const
Adaptor(Application &app, std::unique_ptr< FeeVote > &&feeVote, LedgerMaster &ledgerMaster, LocalTxs &localTxs, InboundTransactions &inboundTransactions, ValidatorKeys const &validatorKeys, beast::Journal journal)
void updateOperatingMode(std::size_t const positions) const
Update operating mode based on current peer positions.
std::size_t proposersFinished(RCLCxLedger const &ledger, LedgerHash const &h) const
Number of proposers that have validated a ledger descended from requested ledger.
void onAccept(Result const &result, RCLCxLedger const &prevLedger, NetClock::duration const &closeResolution, ConsensusCloseTimes const &rawCloseTimes, ConsensusMode const &mode, json::Value &&consensusJson, bool const validating)
Process the accepted ledger.
void validate(RCLCxLedger const &ledger, RCLTxSet const &txns, bool proposing)
Validate the given ledger and share with peers as necessary.
std::size_t prevProposers() const
ConsensusParms const & parms() const
Consensus simulation parameters.
std::unique_ptr< FeeVote > feeVote_
std::atomic< bool > validating_
void propose(RCLCxPeerPos::Proposal const &proposal)
Propose the given position to my peers.
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.
ConsensusMode mode() const
NetClock::time_point lastValidationTime_
std::size_t proposersValidated(LedgerHash const &h) const
Number of proposers that have validated the given ledger.
void notify(protocol::NodeEvent ne, RCLCxLedger const &ledger, bool haveCorrectLCL)
Notify peers of a consensus state change.
std::atomic< ConsensusMode > mode_
std::pair< std::size_t, hash_set< NodeKey_t > > getQuorumKeys() const
std::optional< RCLTxSet > acquireTxSet(RCLTxSet::ID const &setId)
Acquire the transaction set associated with a proposal.
ValidatorKeys const & validatorKeys_
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.
uint256 getPrevLedger(uint256 ledgerID, RCLCxLedger const &ledger, ConsensusMode mode)
Get the ID of the previous ledger/last closed ledger(LCL) on the network.
beast::Journal const j_
std::atomic< std::chrono::milliseconds > prevRoundTime_
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.
std::size_t laggards(Ledger_t::Seq const seq, hash_set< NodeKey_t > &trustedKeys) const
ConsensusResult< Adaptor > Result
std::optional< RCLCxLedger > acquireLedger(LedgerHash const &hash)
Attempt to acquire a specific ledger.
std::chrono::milliseconds prevRoundTime() const
bool hasOpenTransactions() const
Whether the open ledger has any transactions.
std::atomic< std::size_t > prevProposers_
void onModeChange(ConsensusMode before, ConsensusMode after)
Notified of change in consensus mode.
std::uint64_t const valCookie_
void share(RCLCxPeerPos const &peerPos)
Share the given proposal with all peers.
Consensus< Adaptor > consensus_
void timerEntry(NetClock::time_point const &now, std::unique_ptr< std::stringstream > const &clog={})
void startRound(NetClock::time_point const &now, RCLCxLedger::ID const &prevLgrId, RCLCxLedger const &prevLgr, hash_set< NodeID > const &nowUntrusted, hash_set< NodeID > const &nowTrusted, std::unique_ptr< std::stringstream > const &clog)
Adjust the set of trusted validators and kick-off the next round of consensus.
bool validating() const
Whether we are validating consensus ledgers.
std::size_t prevProposers() const
Get the number of proposing peers that participated in the previous round.
RCLConsensus(RCLConsensus const &)=delete
json::Value getJson(bool full) const
beast::Journal const j_
bool peerProposal(NetClock::time_point const &now, RCLCxPeerPos const &newProposal)
void simulate(NetClock::time_point const &now, std::optional< std::chrono::milliseconds > consensusDelay)
ConsensusParms const & parms() const
RCLConsensus & operator=(RCLConsensus const &)=delete
std::chrono::milliseconds prevRoundTime() const
Get duration of the previous round.
std::recursive_mutex mutex_
static constexpr unsigned int kCensorshipWarnInternal
Warn for transactions that haven't been included every so many ledgers.
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.
ConsensusMode mode() const
void gotTxSet(NetClock::time_point const &now, RCLTxSet const &txSet)
RCLCxLedger::ID prevLedgerID() const
ConsensusPhase phase() const
Represents a ledger in RCLConsensus.
Definition RCLCxLedger.h:23
LedgerHash ID
Unique identifier of a ledger.
Definition RCLCxLedger.h:28
LedgerIndex Seq
Sequence number of a ledger.
Definition RCLCxLedger.h:32
A peer's signed, proposed position for use in RCLConsensus.
ConsensusProposal< NodeID, uint256, uint256 > Proposal
Represents a transaction in RCLConsensus.
Definition RCLCxTx.h:22
Represents a set of transactions in RCLConsensus.
Definition RCLCxTx.h:60
uint256 ID
Unique identifier/hash of the set of transactions.
Definition RCLCxTx.h:65
std::unique_ptr< std::stringstream > const & ss()
std::chrono::steady_clock::time_point start_
RclConsensusLogger(char const *label, bool validating, beast::Journal j)
std::unique_ptr< std::stringstream > ss_
Validator keys and manifest as set in configuration file.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
ConsensusMode
Represents how a node currently participates in Consensus.
@ Observing
We are observing peer positions, but not proposing our position.
std::uint32_t LedgerIndex
A ledger index.
Definition Protocol.h:370
std::unordered_set< Value, Hash, Pred, Allocator > hash_set
boost::outcome_v2::result< T, std::error_code > Result
Definition b58_utils.h:19
uint256 LedgerHash
ConsensusPhase
Phases of consensus for a single ledger round.
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
Definition View.cpp:572
BaseUInt< 256 > uint256
Definition base_uint.h:580
BaseUInt< 160, detail::NodeIDTag > NodeID
NodeID is a 160-bit hash representing one node.
Definition UintTypes.h:47
Stores the set of initial close times.
Consensus algorithm parameters.
Encapsulates the result of consensus.