mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-20 07:01:02 +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:
@@ -39,7 +39,7 @@ pub enum Error<E> {
|
||||
}
|
||||
|
||||
/// A shared authority set.
|
||||
pub(crate) struct SharedAuthoritySet<H, N> {
|
||||
pub struct SharedAuthoritySet<H, N> {
|
||||
inner: Arc<RwLock<AuthoritySet<H, N>>>,
|
||||
}
|
||||
|
||||
@@ -67,12 +67,12 @@ where N: Add<Output=N> + Ord + Clone + Debug,
|
||||
}
|
||||
|
||||
/// Get the current set ID. This is incremented every time the set changes.
|
||||
pub(crate) fn set_id(&self) -> u64 {
|
||||
pub fn set_id(&self) -> u64 {
|
||||
self.inner.read().set_id
|
||||
}
|
||||
|
||||
/// Get the current authorities and their weights (for the current set ID).
|
||||
pub(crate) fn current_authorities(&self) -> VoterSet<AuthorityId> {
|
||||
pub fn current_authorities(&self) -> VoterSet<AuthorityId> {
|
||||
VoterSet::new(self.inner.read().current_authorities.iter().cloned()).expect(
|
||||
"current_authorities is non-empty and weights are non-zero; \
|
||||
constructor and all mutating operations on `AuthoritySet` ensure this; \
|
||||
|
||||
@@ -52,6 +52,8 @@
|
||||
//! or prune any signaled changes based on whether the signaling block is
|
||||
//! included in the newly-finalized chain.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
|
||||
use futures::prelude::*;
|
||||
use futures::StreamExt;
|
||||
use log::{debug, info};
|
||||
@@ -72,6 +74,7 @@ use sp_core::Pair;
|
||||
use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver};
|
||||
use sc_telemetry::{telemetry, CONSENSUS_INFO, CONSENSUS_DEBUG};
|
||||
use serde_json;
|
||||
use parking_lot::RwLock;
|
||||
|
||||
use sp_finality_tracker;
|
||||
|
||||
@@ -114,12 +117,14 @@ mod observer;
|
||||
mod until_imported;
|
||||
mod voting_rule;
|
||||
|
||||
pub use authorities::SharedAuthoritySet;
|
||||
pub use finality_proof::{FinalityProofProvider, StorageAndProofProvider};
|
||||
pub use justification::GrandpaJustification;
|
||||
pub use light_import::light_block_import;
|
||||
pub use voting_rule::{
|
||||
BeforeBestBlockBy, ThreeQuartersOfTheUnfinalizedChain, VotingRule, VotingRulesBuilder
|
||||
};
|
||||
pub use finality_grandpa::voter::report;
|
||||
|
||||
use aux_schema::PersistentData;
|
||||
use environment::{Environment, VoterSetState};
|
||||
@@ -203,7 +208,44 @@ type CommunicationOutH<Block, H> = finality_grandpa::voter::CommunicationOut<
|
||||
AuthorityId,
|
||||
>;
|
||||
|
||||
/// Configuration for the GRANDPA service.
|
||||
/// Shared voter state for querying.
|
||||
pub struct SharedVoterState {
|
||||
inner: Arc<RwLock<Option<Box<dyn voter::VoterState<AuthorityId> + Sync + Send>>>>,
|
||||
}
|
||||
|
||||
impl SharedVoterState {
|
||||
/// Create a new empty `SharedVoterState` instance.
|
||||
pub fn empty() -> Self {
|
||||
Self {
|
||||
inner: Arc::new(RwLock::new(None)),
|
||||
}
|
||||
}
|
||||
|
||||
fn reset(
|
||||
&self,
|
||||
voter_state: Box<dyn voter::VoterState<AuthorityId> + Sync + Send>,
|
||||
) -> Option<()> {
|
||||
let mut shared_voter_state = self
|
||||
.inner
|
||||
.try_write_for(Duration::from_secs(1))?;
|
||||
|
||||
*shared_voter_state = Some(voter_state);
|
||||
Some(())
|
||||
}
|
||||
|
||||
/// Get the inner `VoterState` instance.
|
||||
pub fn voter_state(&self) -> Option<voter::report::VoterState<AuthorityId>> {
|
||||
self.inner.read().as_ref().map(|vs| vs.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for SharedVoterState {
|
||||
fn clone(&self) -> Self {
|
||||
SharedVoterState { inner: self.inner.clone() }
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration for the GRANDPA service
|
||||
#[derive(Clone)]
|
||||
pub struct Config {
|
||||
/// The expected duration for a message to be gossiped across the network.
|
||||
@@ -392,6 +434,7 @@ impl<H, N> fmt::Display for CommandOrError<H, N> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Link between the block importer and the background voter.
|
||||
pub struct LinkHalf<Block: BlockT, C, SC> {
|
||||
client: Arc<C>,
|
||||
select_chain: SC,
|
||||
@@ -399,6 +442,13 @@ pub struct LinkHalf<Block: BlockT, C, SC> {
|
||||
voter_commands_rx: TracingUnboundedReceiver<VoterCommand<Block::Hash, NumberFor<Block>>>,
|
||||
}
|
||||
|
||||
impl<Block: BlockT, C, SC> LinkHalf<Block, C, SC> {
|
||||
/// Get the shared authority set.
|
||||
pub fn shared_authority_set(&self) -> &SharedAuthoritySet<Block::Hash, NumberFor<Block>> {
|
||||
&self.persistent_data.authority_set
|
||||
}
|
||||
}
|
||||
|
||||
/// Provider for the Grandpa authority set configured on the genesis block.
|
||||
pub trait GenesisAuthoritySetProvider<Block: BlockT> {
|
||||
/// Get the authority set at the genesis block.
|
||||
@@ -620,6 +670,8 @@ pub struct GrandpaParams<Block: BlockT, C, N, SC, VR> {
|
||||
pub voting_rule: VR,
|
||||
/// The prometheus metrics registry.
|
||||
pub prometheus_registry: Option<prometheus_endpoint::Registry>,
|
||||
/// The voter state is exposed at an RPC endpoint.
|
||||
pub shared_voter_state: SharedVoterState,
|
||||
}
|
||||
|
||||
/// Run a GRANDPA voter as a task. Provide configuration and a link to a
|
||||
@@ -644,6 +696,7 @@ pub fn run_grandpa_voter<Block: BlockT, BE: 'static, C, N, SC, VR>(
|
||||
telemetry_on_connect,
|
||||
voting_rule,
|
||||
prometheus_registry,
|
||||
shared_voter_state,
|
||||
} = grandpa_params;
|
||||
|
||||
// NOTE: we have recently removed `run_grandpa_observer` from the public
|
||||
@@ -704,6 +757,7 @@ pub fn run_grandpa_voter<Block: BlockT, BE: 'static, C, N, SC, VR>(
|
||||
persistent_data,
|
||||
voter_commands_rx,
|
||||
prometheus_registry,
|
||||
shared_voter_state,
|
||||
);
|
||||
|
||||
let voter_work = voter_work
|
||||
@@ -734,6 +788,7 @@ impl Metrics {
|
||||
#[must_use]
|
||||
struct VoterWork<B, Block: BlockT, C, N: NetworkT<Block>, SC, VR> {
|
||||
voter: Pin<Box<dyn Future<Output = Result<(), CommandOrError<Block::Hash, NumberFor<Block>>>> + Send>>,
|
||||
shared_voter_state: SharedVoterState,
|
||||
env: Arc<Environment<B, Block, C, N, SC, VR>>,
|
||||
voter_commands_rx: TracingUnboundedReceiver<VoterCommand<Block::Hash, NumberFor<Block>>>,
|
||||
network: NetworkBridge<Block, N>,
|
||||
@@ -761,6 +816,7 @@ where
|
||||
persistent_data: PersistentData<Block>,
|
||||
voter_commands_rx: TracingUnboundedReceiver<VoterCommand<Block::Hash, NumberFor<Block>>>,
|
||||
prometheus_registry: Option<prometheus_endpoint::Registry>,
|
||||
shared_voter_state: SharedVoterState,
|
||||
) -> Self {
|
||||
let metrics = match prometheus_registry.as_ref().map(Metrics::register) {
|
||||
Some(Ok(metrics)) => Some(metrics),
|
||||
@@ -791,6 +847,7 @@ where
|
||||
// `voter` is set to a temporary value and replaced below when
|
||||
// calling `rebuild_voter`.
|
||||
voter: Box::pin(future::pending()),
|
||||
shared_voter_state,
|
||||
env,
|
||||
voter_commands_rx,
|
||||
network,
|
||||
@@ -858,6 +915,14 @@ where
|
||||
last_finalized,
|
||||
);
|
||||
|
||||
// Repoint shared_voter_state so that the RPC endpoint can query the state
|
||||
if let None = self.shared_voter_state.reset(voter.voter_state()) {
|
||||
info!(target: "afg",
|
||||
"Timed out trying to update shared GRANDPA voter state. \
|
||||
RPC endpoints may return stale data."
|
||||
);
|
||||
}
|
||||
|
||||
self.voter = Box::pin(voter);
|
||||
},
|
||||
VoterSetState::Paused { .. } =>
|
||||
|
||||
@@ -295,8 +295,6 @@ fn run_to_completion_with<F>(
|
||||
) -> u64 where
|
||||
F: FnOnce(Handle) -> Option<Pin<Box<dyn Future<Output = ()>>>>
|
||||
{
|
||||
use parking_lot::RwLock;
|
||||
|
||||
let mut wait_for = Vec::new();
|
||||
|
||||
let highest_finalized = Arc::new(RwLock::new(0));
|
||||
@@ -354,6 +352,7 @@ fn run_to_completion_with<F>(
|
||||
telemetry_on_connect: None,
|
||||
voting_rule: (),
|
||||
prometheus_registry: None,
|
||||
shared_voter_state: SharedVoterState::empty(),
|
||||
};
|
||||
let voter = run_grandpa_voter(grandpa_params).expect("all in order with client and network");
|
||||
|
||||
@@ -485,6 +484,7 @@ fn finalize_3_voters_1_full_observer() {
|
||||
telemetry_on_connect: None,
|
||||
voting_rule: (),
|
||||
prometheus_registry: None,
|
||||
shared_voter_state: SharedVoterState::empty(),
|
||||
};
|
||||
|
||||
voters.push(run_grandpa_voter(grandpa_params).expect("all in order with client and network"));
|
||||
@@ -648,6 +648,7 @@ fn transition_3_voters_twice_1_full_observer() {
|
||||
telemetry_on_connect: None,
|
||||
voting_rule: (),
|
||||
prometheus_registry: None,
|
||||
shared_voter_state: SharedVoterState::empty(),
|
||||
};
|
||||
let voter = run_grandpa_voter(grandpa_params).expect("all in order with client and network");
|
||||
|
||||
@@ -1072,6 +1073,7 @@ fn voter_persists_its_votes() {
|
||||
telemetry_on_connect: None,
|
||||
voting_rule: VotingRulesBuilder::default().build(),
|
||||
prometheus_registry: None,
|
||||
shared_voter_state: SharedVoterState::empty(),
|
||||
};
|
||||
|
||||
let voter = run_grandpa_voter(grandpa_params)
|
||||
@@ -1417,6 +1419,7 @@ fn voter_catches_up_to_latest_round_when_behind() {
|
||||
telemetry_on_connect: None,
|
||||
voting_rule: (),
|
||||
prometheus_registry: None,
|
||||
shared_voter_state: SharedVoterState::empty(),
|
||||
};
|
||||
|
||||
Box::pin(run_grandpa_voter(grandpa_params).expect("all in order with client and network"))
|
||||
|
||||
Reference in New Issue
Block a user