Kagome
Polkadot Runtime Engine in C++17
voting_round_impl.hpp
Go to the documentation of this file.
1 
6 #ifndef KAGOME_CONSENSUS_GRANDPA_VOTINGROUNDIMPL
7 #define KAGOME_CONSENSUS_GRANDPA_VOTINGROUNDIMPL
8 
10 
11 #include <boost/asio/basic_waitable_timer.hpp>
12 #include <boost/signals2.hpp>
13 #include <libp2p/basic/scheduler.hpp>
14 
23 #include "log/logger.hpp"
24 
26 
27  class Grandpa;
28 
29  class VotingRoundImpl : public VotingRound {
30  private:
32  const std::shared_ptr<Grandpa> &grandpa,
33  const GrandpaConfig &config,
34  std::shared_ptr<authority::AuthorityManager> authority_manager,
35  std::shared_ptr<Environment> env,
36  std::shared_ptr<VoteCryptoProvider> vote_crypto_provider,
37  std::shared_ptr<VoteTracker> prevotes,
38  std::shared_ptr<VoteTracker> precommits,
39  std::shared_ptr<VoteGraph> vote_graph,
40  std::shared_ptr<Clock> clock,
41  std::shared_ptr<libp2p::basic::Scheduler> scheduler);
42 
43  protected:
44  // This ctor is needed only for tests purposes
46 
47  public:
49  const std::shared_ptr<Grandpa> &grandpa,
50  const GrandpaConfig &config,
51  const std::shared_ptr<authority::AuthorityManager> authority_manager,
52  const std::shared_ptr<Environment> &env,
53  const std::shared_ptr<VoteCryptoProvider> &vote_crypto_provider,
54  const std::shared_ptr<VoteTracker> &prevotes,
55  const std::shared_ptr<VoteTracker> &precommits,
56  const std::shared_ptr<VoteGraph> &vote_graph,
57  const std::shared_ptr<Clock> &clock,
58  const std::shared_ptr<libp2p::basic::Scheduler> &scheduler,
59  const MovableRoundState &round_state);
60 
62  const std::shared_ptr<Grandpa> &grandpa,
63  const GrandpaConfig &config,
64  const std::shared_ptr<authority::AuthorityManager> authority_manager,
65  const std::shared_ptr<Environment> &env,
66  const std::shared_ptr<VoteCryptoProvider> &vote_crypto_provider,
67  const std::shared_ptr<VoteTracker> &prevotes,
68  const std::shared_ptr<VoteTracker> &precommits,
69  const std::shared_ptr<VoteGraph> &vote_graph,
70  const std::shared_ptr<Clock> &clock,
71  const std::shared_ptr<libp2p::basic::Scheduler> &scheduler,
72  const std::shared_ptr<VotingRound> &previous_round);
73 
74  enum class Stage {
75  // Initial stage, round is just created
76  INIT,
77 
78  // Beginner stage, round is just start to play
79  START,
80 
81  // Stages for prevote mechanism
85 
86  // Stages for precommit mechanism
90 
91  // Stages for waiting finalisation
95 
96  // Final state. Round was finalized
97  COMPLETED
98  };
99 
100  // Start/stop round
101 
102  void play() override;
103  void end() override;
104 
105  // Workflow of round
106 
107  void startPrevoteStage();
108  void endPrevoteStage();
109  void startPrecommitStage();
110  void endPrecommitStage();
111  void startWaitingStage();
112  void endWaitingStage();
113 
114  // Actions of round
115 
116  void doProposal() override;
117  void doPrevote() override;
118  void doPrecommit() override;
119  void doFinalize() override;
120  void doCommit() override;
121 
122  // Handlers of incoming messages
123 
124  outcome::result<void> applyJustification(
125  const BlockInfo &block_info,
126  const GrandpaJustification &justification) override;
127 
133  void onProposal(const SignedMessage &proposal,
134  Propagation propagation) override;
135 
143  bool onPrevote(const SignedMessage &prevote,
144  Propagation propagation) override;
145 
152  bool onPrecommit(const SignedMessage &precommit,
153  Propagation propagation) override;
154 
162  void update(IsPreviousRoundChanged is_previous_round_changed,
163  IsPrevotesChanged is_prevotes_changed,
164  IsPrecommitsChanged is_precommits_changed) override;
165 
169  std::shared_ptr<VotingRound> getPreviousRound() const override {
170  return previous_round_;
171  };
172 
176  void forgetPreviousRound() override {
177  previous_round_.reset();
178  }
179 
185  void attemptToFinalizeRound() override;
186 
187  // Catch-up actions
188 
189  void doCatchUpResponse(const libp2p::peer::PeerId &peer_id) override;
190 
191  // Getters
192 
193  RoundNumber roundNumber() const override;
194  VoterSetId voterSetId() const override;
195 
201  bool completable() const override;
202 
207  BlockInfo lastFinalizedBlock() const override {
208  return last_finalized_block_;
209  }
210 
215  BlockInfo bestPrevoteCandidate() override;
216 
227  BlockInfo bestFinalCandidate() override;
228 
232  const std::optional<BlockInfo> &finalizedBlock() const override {
233  return finalized_;
234  };
235 
240  MovableRoundState state() const override;
241 
242  void sendNeighborMessage();
243 
244  private:
246  bool isPrimary(const Id &id) const;
247 
249  template <typename T>
250  outcome::result<void> onSigned(const SignedMessage &vote);
251 
258  bool updateGrandpaGhost();
259 
264  bool updateEstimate();
265 
272  std::vector<SignedPrevote> getPrevoteJustification(
273  const BlockInfo &estimate, const std::vector<VoteVariant> &votes) const;
274 
282  std::vector<SignedPrecommit> getPrecommitJustification(
283  const BlockInfo &precommits,
284  const std::vector<VoteVariant> &votes) const;
285 
292  outcome::result<void> validatePrecommitJustification(
293  const BlockInfo &vote, const GrandpaJustification &justification) const;
294 
295  void sendProposal(const PrimaryPropose &primary_proposal);
296  void sendPrevote(const Prevote &prevote);
297  void sendPrecommit(const Precommit &precommit);
298  void pending();
299 
300  std::shared_ptr<VoterSet> voter_set_;
302  std::shared_ptr<VotingRound> previous_round_;
303 
304  const Duration duration_; // length of round
305  bool isPrimary_ = false;
306  size_t threshold_; // supermajority threshold
307  const std::optional<Id> id_; // id of current peer
308  std::chrono::milliseconds start_time_; // time of start round to play
309 
310  std::weak_ptr<Grandpa> grandpa_;
311  std::shared_ptr<authority::AuthorityManager> authority_manager_;
312  std::shared_ptr<const primitives::AuthorityList> authorities_;
313  std::shared_ptr<Environment> env_;
314  std::shared_ptr<VoteCryptoProvider> vote_crypto_provider_;
315  std::shared_ptr<VoteGraph> graph_;
316  std::shared_ptr<Clock> clock_;
317  std::shared_ptr<libp2p::basic::Scheduler> scheduler_;
318 
319  std::function<void()> on_complete_handler_;
320 
321  // Note: Pending interval must be longer than total voting time:
322  // 2*Duration + 2*Duration + Gap
323  // Spec says to send at least once per five minutes.
324  // Substrate sends at least once per two minutes.
325  const std::chrono::milliseconds pending_interval_ =
326  std::chrono::duration_cast<std::chrono::milliseconds>(
327  std::max<Clock::Duration>(duration_ * 10,
328  std::chrono::seconds(12)));
329 
331 
332  std::shared_ptr<VoteTracker> prevotes_;
333  std::shared_ptr<VoteTracker> precommits_;
334 
335  // equivocators arrays. Index in vector corresponds to the index of voter in
336  // voter set, value corresponds to the weight of the voter
337  std::vector<bool> prevote_equivocators_;
338  std::vector<bool> precommit_equivocators_;
339 
340  // Proposed primary vote.
341  // It's best final candidate of previous round
342  std::optional<BlockInfo> primary_vote_;
343 
344  // Our vote at prevote stage.
345  // It's the deepest descendant of primary vote (or last finalized)
346  std::optional<BlockInfo> prevote_;
347 
348  // Our vote at precommit stage. Setting once.
349  // It's the deepest descendant of best prevote candidate with prevote
350  // supermajority
351  std::optional<BlockInfo> precommit_;
352 
353  // Last finalized block at the moment of round is cteated
355 
356  // Prevote ghost. Updating by each prevote.
357  // It's deepest descendant of primary vote (or last finalized) with prevote
358  // supermajority Is't also the best prevote candidate
359  std::optional<BlockInfo> prevote_ghost_;
360 
361  std::optional<BlockInfo> estimate_;
362  std::optional<BlockInfo> finalized_;
363 
364  libp2p::basic::Scheduler::Handle stage_timer_handle_;
365  libp2p::basic::Scheduler::Handle pending_timer_handle_;
366 
367  log::Logger logger_ = log::createLogger("VotingRound", "voting_round");
368 
369  bool completable_ = false;
370  };
371 } // namespace kagome::consensus::grandpa
372 
373 #endif // KAGOME_CONSENSUS_GRANDPA_VOTINGROUNDIMPL
libp2p::basic::Scheduler::Handle pending_timer_handle_
std::shared_ptr< libp2p::basic::Scheduler > scheduler_
std::shared_ptr< VotingRound > previous_round_
void doPrecommit() override
Calculate precommit and broadcast signed precommit message.
libp2p::basic::Scheduler::Handle stage_timer_handle_
std::shared_ptr< VotingRound > getPreviousRound() const override
void sendProposal(const PrimaryPropose &primary_proposal)
const std::optional< BlockInfo > & finalizedBlock() const override
std::shared_ptr< VoteTracker > precommits_
Clock::Duration Duration
Definition: common.hpp:29
const std::chrono::milliseconds pending_interval_
outcome::result< void > validatePrecommitJustification(const BlockInfo &vote, const GrandpaJustification &justification) const
std::shared_ptr< const primitives::AuthorityList > authorities_
crypto::Ed25519PublicKey Id
Definition: common.hpp:19
MovableRoundState state() const override
libp2p::peer::PeerId PeerId
outcome::result< void > onSigned(const SignedMessage &vote)
Triggered when we receive {.
std::shared_ptr< soralog::Logger > Logger
Definition: logger.hpp:23
void sendPrecommit(const Precommit &precommit)
void update(IsPreviousRoundChanged is_previous_round_changed, IsPrevotesChanged is_prevotes_changed, IsPrecommitsChanged is_precommits_changed) override
outcome::result< void > applyJustification(const BlockInfo &block_info, const GrandpaJustification &justification) override
std::shared_ptr< authority::AuthorityManager > authority_manager_
void doPrevote() override
Calculate prevote and broadcast signed prevote message.
void doCatchUpResponse(const libp2p::peer::PeerId &peer_id) override
Stores the current state of the round.
void doFinalize() override
Collect and save justifications finalizing this round.
bool onPrevote(const SignedMessage &prevote, Propagation propagation) override
bool isPrimary(const Id &id) const
Check if peer.
std::vector< SignedPrevote > getPrevoteJustification(const BlockInfo &estimate, const std::vector< VoteVariant > &votes) const
Logger createLogger(const std::string &tag)
Definition: logger.cpp:112
void onProposal(const SignedMessage &proposal, Propagation propagation) override
bool onPrecommit(const SignedMessage &precommit, Propagation propagation) override
void doCommit() override
Broadcast commit message.
std::shared_ptr< VoteCryptoProvider > vote_crypto_provider_
std::vector< SignedPrecommit > getPrecommitJustification(const BlockInfo &precommits, const std::vector< VoteVariant > &votes) const