mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-01 02:11:01 +00:00
Expose GRANDPA round state through RPC (#5375)
* grandpa: wire up basic RPC call * grandpa: make it compile against GRANDPA with expose round state * grandpa: use shared voter state to expose RPC endpoint * grandpa: restructure into nested structs * grandpa: return background rounds too * grandpa: return error when endpoint not ready * grandpa: collect grandpa rpc deps * grandpa: decide to use concrete AuthorityId in finality-grandpa-rpc * grandpa: remove unncessary type annotation * grandpa: move error code to const * grandpa: remove unnecessary WIP comment * grandpa: remove Id type parameter for SharedVoterState * grandpa: update tests to add shared_voter_state in parameters * grandpa: remove old deprecated test * grandpa: fix getting the correct set_id * grandpa: make SharedVoterState a struct * grandpa: wrap shared_voter_state in rpc_setup * grandpa: replace spaces with tabs * grandpa: limit RwLock write attempt to 1 sec * grandpa: add missing doc comments and remove some pub * Apply suggestions from code review Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com> Co-Authored-By: Hernando Castano <HCastano@users.noreply.github.com> * grandpa: update function name call after change in finality-grandpa * grandpa: group pub use and only export voter::report * grandpa: add missing docs * grandpa: extract out structs used for json serialization * grandpa: stick to u32 for fields intended for js * grandpa: move Error type to its own file * grandpa: group pub use better * Apply code review suggestion Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * grandpa: use correct version of finality-granpda in rpc crate * grandpa: add back basic rpc unit test * grandpa: replace SharedVoterState::new() with empty() * node: cleanup grandpa::SharedVoterState usage in macro * grandpa: remove VoterState error variant * grandpa: enable missing futures compat feature * grandpa: fix typo in error variant * grandpa: remove test_utils * grandpa: allow mocking rpc handler components * grandpa: rename serialized to report in rpc module * grandpa: add proper test for RPC * grandpa: update to finality-grandpa v0.12.1 Co-authored-by: André Silva <andre.beat@gmail.com> Co-authored-by: Demi Obenour <demi@parity.io> Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com> Co-authored-by: Hernando Castano <HCastano@users.noreply.github.com> Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
// Copyright 2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::{
|
||||
collections::{BTreeSet, HashSet},
|
||||
fmt::Debug,
|
||||
ops::Add,
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use sc_finality_grandpa::{report, AuthorityId, SharedAuthoritySet, SharedVoterState};
|
||||
|
||||
use crate::error::Error;
|
||||
|
||||
/// Utility trait to get reporting data for the current GRANDPA authority set.
|
||||
pub trait ReportAuthoritySet {
|
||||
fn get(&self) -> (u64, HashSet<AuthorityId>);
|
||||
}
|
||||
|
||||
/// Utility trait to get reporting data for the current GRANDPA voter state.
|
||||
pub trait ReportVoterState {
|
||||
fn get(&self) -> Option<report::VoterState<AuthorityId>>;
|
||||
}
|
||||
|
||||
impl<H, N> ReportAuthoritySet for SharedAuthoritySet<H, N>
|
||||
where
|
||||
N: Add<Output = N> + Ord + Clone + Debug,
|
||||
H: Clone + Debug + Eq,
|
||||
{
|
||||
fn get(&self) -> (u64, HashSet<AuthorityId>) {
|
||||
let current_voters: HashSet<AuthorityId> = self
|
||||
.current_authorities()
|
||||
.iter()
|
||||
.map(|p| p.0.clone())
|
||||
.collect();
|
||||
|
||||
(self.set_id(), current_voters)
|
||||
}
|
||||
}
|
||||
|
||||
impl ReportVoterState for SharedVoterState {
|
||||
fn get(&self) -> Option<report::VoterState<AuthorityId>> {
|
||||
self.voter_state()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct Prevotes {
|
||||
current_weight: u32,
|
||||
missing: BTreeSet<AuthorityId>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct Precommits {
|
||||
current_weight: u32,
|
||||
missing: BTreeSet<AuthorityId>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct RoundState {
|
||||
round: u32,
|
||||
total_weight: u32,
|
||||
threshold_weight: u32,
|
||||
prevotes: Prevotes,
|
||||
precommits: Precommits,
|
||||
}
|
||||
|
||||
impl RoundState {
|
||||
fn from(
|
||||
round: u64,
|
||||
round_state: &report::RoundState<AuthorityId>,
|
||||
voters: &HashSet<AuthorityId>,
|
||||
) -> Result<Self, Error> {
|
||||
use std::convert::TryInto;
|
||||
|
||||
let prevotes = &round_state.prevote_ids;
|
||||
let missing_prevotes = voters.difference(&prevotes).cloned().collect();
|
||||
|
||||
let precommits = &round_state.precommit_ids;
|
||||
let missing_precommits = voters.difference(&precommits).cloned().collect();
|
||||
|
||||
Ok(Self {
|
||||
round: round.try_into()?,
|
||||
total_weight: round_state.total_weight.get().try_into()?,
|
||||
threshold_weight: round_state.threshold_weight.get().try_into()?,
|
||||
prevotes: Prevotes {
|
||||
current_weight: round_state.prevote_current_weight.0.try_into()?,
|
||||
missing: missing_prevotes,
|
||||
},
|
||||
precommits: Precommits {
|
||||
current_weight: round_state.precommit_current_weight.0.try_into()?,
|
||||
missing: missing_precommits,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// The state of the current best round, as well as the background rounds in a
|
||||
/// form suitable for serialization.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ReportedRoundStates {
|
||||
set_id: u32,
|
||||
best: RoundState,
|
||||
background: Vec<RoundState>,
|
||||
}
|
||||
|
||||
impl ReportedRoundStates {
|
||||
pub fn from<AuthoritySet, VoterState>(
|
||||
authority_set: &AuthoritySet,
|
||||
voter_state: &VoterState,
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
AuthoritySet: ReportAuthoritySet,
|
||||
VoterState: ReportVoterState,
|
||||
{
|
||||
use std::convert::TryFrom;
|
||||
|
||||
let voter_state = voter_state.get().ok_or(Error::EndpointNotReady)?;
|
||||
|
||||
let (set_id, current_voters) = authority_set.get();
|
||||
let set_id =
|
||||
u32::try_from(set_id).map_err(|_| Error::AuthoritySetIdReportedAsUnreasonablyLarge)?;
|
||||
|
||||
let best = {
|
||||
let (round, round_state) = voter_state.best_round;
|
||||
RoundState::from(round, &round_state, ¤t_voters)?
|
||||
};
|
||||
|
||||
let background = voter_state
|
||||
.background_rounds
|
||||
.iter()
|
||||
.map(|(round, round_state)| RoundState::from(*round, round_state, ¤t_voters))
|
||||
.collect::<Result<Vec<_>, Error>>()?;
|
||||
|
||||
Ok(Self {
|
||||
set_id,
|
||||
best,
|
||||
background,
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user