|  | 
| 16 | 16 | 
 | 
| 17 | 17 | //! RPC API for GRANDPA. | 
| 18 | 18 | 
 | 
| 19 |  | -use futures::{FutureExt as _, TryFutureExt as _}; | 
|  | 19 | +use futures::{FutureExt, TryFutureExt}; | 
| 20 | 20 | use jsonrpc_derive::rpc; | 
| 21 |  | -use jsonrpc_core::{Error as RpcError, futures::future as rpc_future}; | 
|  | 21 | +use jsonrpc_core::Error; | 
|  | 22 | +use sc_finality_grandpa::{SharedVoterState, SharedAuthoritySet, AuthorityId, voter}; | 
|  | 23 | +use finality_grandpa::BlockNumberOps; | 
|  | 24 | +use serde::{Serialize, Deserialize}; | 
|  | 25 | +use std::{collections::HashSet, fmt::Debug}; | 
| 22 | 26 | 
 | 
| 23 |  | -type FutureResult<T> = Box<dyn rpc_future::Future<Item = T, Error = RpcError> + Send>; | 
|  | 27 | +type FutureResult<T> = Box<dyn jsonrpc_core::futures::Future<Item = T, Error = Error> + Send>; | 
| 24 | 28 | 
 | 
| 25 | 29 | #[rpc] | 
| 26 | 30 | pub trait GrandpaApi { | 
| 27 | 31 | 	#[rpc(name = "grandpa_roundState")] | 
| 28 |  | -	fn grandpa_roundState(&self) -> FutureResult<String>; | 
|  | 32 | +	fn grandpa_round_state(&self) -> FutureResult<RoundState>; | 
| 29 | 33 | } | 
| 30 | 34 | 
 | 
| 31 |  | -pub struct GrandpaRpcHandler; | 
|  | 35 | +pub struct GrandpaRpcHandler<Hash, Block> { | 
|  | 36 | +	// WIP: pass AuthorityId as type parameter | 
|  | 37 | +	shared_voter_state: SharedVoterState<AuthorityId>, | 
|  | 38 | +	shared_authority_set: SharedAuthoritySet<Hash, Block>, | 
|  | 39 | +} | 
|  | 40 | + | 
|  | 41 | +impl<Hash, Block> GrandpaRpcHandler<Hash, Block> { | 
|  | 42 | +	pub fn new( | 
|  | 43 | +		shared_voter_state: SharedVoterState<AuthorityId>, | 
|  | 44 | +		shared_authority_set: SharedAuthoritySet<Hash, Block> | 
|  | 45 | +	) -> Self { | 
|  | 46 | +		Self { | 
|  | 47 | +			shared_voter_state, | 
|  | 48 | +			shared_authority_set, | 
|  | 49 | +		} | 
|  | 50 | +	} | 
|  | 51 | +} | 
|  | 52 | + | 
|  | 53 | +#[derive(Serialize, Deserialize)] | 
|  | 54 | +pub struct RoundState { | 
|  | 55 | +	pub set_id: u64, | 
|  | 56 | +	pub round: u64, | 
|  | 57 | +	pub total_weight: u64, | 
|  | 58 | +	pub threshold_weight: u64, | 
|  | 59 | + | 
|  | 60 | +	pub prevote_current_weight: u64, | 
|  | 61 | +	pub prevote_missing: HashSet<AuthorityId>, | 
|  | 62 | + | 
|  | 63 | +	pub precommit_current_weight: u64, | 
|  | 64 | +	pub precommit_missing: HashSet<AuthorityId>, | 
|  | 65 | +} | 
|  | 66 | + | 
|  | 67 | +impl RoundState { | 
|  | 68 | +	pub fn from<Hash, Block>( | 
|  | 69 | +		voter_state: &SharedVoterState<AuthorityId>, | 
|  | 70 | +		authority_set: &SharedAuthoritySet<Hash, Block> | 
|  | 71 | +	) -> Self | 
|  | 72 | +	where | 
|  | 73 | +		Hash: Debug + Clone + Eq + Send + Sync + 'static, | 
|  | 74 | +		Block: BlockNumberOps + Send + Sync + 'static, | 
|  | 75 | +	{ | 
|  | 76 | +		let voter_state = voter_state.read().as_ref().map(|vs| vs.voter_state()); | 
|  | 77 | +		// WIP: handle unwrap of lazily instantiated VoterState | 
|  | 78 | +		let voter_state = voter_state.unwrap(); | 
|  | 79 | + | 
|  | 80 | +		let current_authorities = authority_set.current_authorities(); | 
|  | 81 | + | 
|  | 82 | +		let voters = current_authorities.voters(); | 
|  | 83 | +		let voters: HashSet<AuthorityId> = voters.iter().map(|p| p.0.clone()).collect(); | 
|  | 84 | + | 
|  | 85 | +		let prevotes = voter_state.best_round.1.prevote_ids; | 
|  | 86 | +		let missing_prevotes = voters.difference(&prevotes).cloned().collect(); | 
|  | 87 | + | 
|  | 88 | +		let precommits = voter_state.best_round.1.precommit_ids; | 
|  | 89 | +		let missing_precommits = voters.difference(&precommits).cloned().collect(); | 
|  | 90 | + | 
|  | 91 | +		Self { | 
|  | 92 | +			set_id: authority_set.set_id(), | 
|  | 93 | +			round: voter_state.best_round.0, | 
|  | 94 | +			total_weight: voter_state.best_round.1.total_weight, | 
|  | 95 | +			threshold_weight: voter_state.best_round.1.threshold_weight, | 
|  | 96 | + | 
|  | 97 | +			prevote_current_weight: voter_state.best_round.1.prevote_current_weight, | 
|  | 98 | +			prevote_missing: missing_prevotes, | 
|  | 99 | + | 
|  | 100 | +			precommit_current_weight: voter_state.best_round.1.precommit_current_weight, | 
|  | 101 | +			precommit_missing: missing_precommits, | 
|  | 102 | +		} | 
|  | 103 | +	} | 
|  | 104 | +} | 
| 32 | 105 | 
 | 
| 33 |  | -impl GrandpaApi for GrandpaRpcHandler { | 
| 34 |  | -	fn grandpa_roundState(&self) -> FutureResult<String> { | 
|  | 106 | +impl<Hash, Block: Send + Sync> GrandpaApi for GrandpaRpcHandler<Hash, Block> where | 
|  | 107 | +	Hash: Debug + Clone + Eq + Send + Sync + 'static, | 
|  | 108 | +	Block: BlockNumberOps + Send + Sync + 'static, | 
|  | 109 | +{ | 
|  | 110 | +	fn grandpa_round_state(&self) -> FutureResult<RoundState> { | 
|  | 111 | +		let round_state = RoundState::from(&self.shared_voter_state, &self.shared_authority_set); | 
| 35 | 112 | 		let future = async move { | 
| 36 |  | -			Ok(String::from("Hello world")) | 
|  | 113 | +			Ok(round_state) | 
| 37 | 114 | 		}.boxed(); | 
| 38 | 115 | 		Box::new(future.compat()) | 
| 39 | 116 | 	} | 
|  | 
0 commit comments