Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

grandpa: Re-add Grandpa runtime API for genesis authority set. #3985

Merged
merged 1 commit into from
Nov 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 60 additions & 3 deletions core/finality-grandpa/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ extern crate alloc;

#[cfg(feature = "std")]
use serde::Serialize;
use codec::{Encode, Decode, Codec};
use codec::{Encode, Decode, Input, Codec};
use sr_primitives::{ConsensusEngineId, RuntimeDebug};
use client::decl_runtime_apis;
use rstd::borrow::Cow;
use rstd::vec::Vec;

mod app {
Expand All @@ -46,6 +47,10 @@ pub type AuthoritySignature = app::Signature;
/// The `ConsensusEngineId` of GRANDPA.
pub const GRANDPA_ENGINE_ID: ConsensusEngineId = *b"FRNK";

/// The storage key for the current set of weighted Grandpa authorities.
/// The value stored is an encoded VersionedAuthorityList.
pub const GRANDPA_AUTHORITIES_KEY: &'static [u8] = b":grandpa_authorities";

/// The weight of an authority.
pub type AuthorityWeight = u64;

Expand All @@ -58,12 +63,15 @@ pub type SetId = u64;
/// The round indicator.
pub type RoundNumber = u64;

/// A list of Grandpa authorities with associated weights.
pub type AuthorityList = Vec<(AuthorityId, AuthorityWeight)>;

/// A scheduled change of authority set.
#[cfg_attr(feature = "std", derive(Serialize))]
#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug)]
pub struct ScheduledChange<N> {
/// The new authorities after the change, along with their respective weights.
pub next_authorities: Vec<(AuthorityId, AuthorityWeight)>,
pub next_authorities: AuthorityList,
/// The number of blocks to delay.
pub delay: N,
}
Expand Down Expand Up @@ -154,6 +162,55 @@ pub const PENDING_CHANGE_CALL: &str = "grandpa_pending_change";
/// WASM function call to get current GRANDPA authorities.
pub const AUTHORITIES_CALL: &str = "grandpa_authorities";

/// The current version of the stored AuthorityList type. The encoding version MUST be updated any
/// time the AuthorityList type changes.
const AUTHORITIES_VERISON: u8 = 1;

/// An AuthorityList that is encoded with a version specifier. The encoding version is updated any
/// time the AuthorityList type changes. This ensures that encodings of different versions of an
/// AuthorityList are differentiable. Attempting to decode an authority list with an unknown
/// version will fail.
#[derive(Default)]
pub struct VersionedAuthorityList<'a>(Cow<'a, AuthorityList>);

impl<'a> From<AuthorityList> for VersionedAuthorityList<'a> {
fn from(authorities: AuthorityList) -> Self {
VersionedAuthorityList(Cow::Owned(authorities))
}
}

impl<'a> From<&'a AuthorityList> for VersionedAuthorityList<'a> {
fn from(authorities: &'a AuthorityList) -> Self {
VersionedAuthorityList(Cow::Borrowed(authorities))
}
}

impl<'a> Into<AuthorityList> for VersionedAuthorityList<'a> {
fn into(self) -> AuthorityList {
self.0.into_owned()
}
}

impl<'a> Encode for VersionedAuthorityList<'a> {
fn size_hint(&self) -> usize {
(AUTHORITIES_VERISON, self.0.as_ref()).size_hint()
}

fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
(AUTHORITIES_VERISON, self.0.as_ref()).using_encoded(f)
}
}

impl<'a> Decode for VersionedAuthorityList<'a> {
fn decode<I: Input>(value: &mut I) -> Result<Self, codec::Error> {
let (version, authorities): (u8, AuthorityList) = Decode::decode(value)?;
if version != AUTHORITIES_VERISON {
return Err("unknown Grandpa authorities version".into());
}
Ok(authorities.into())
}
}

decl_runtime_apis! {
/// APIs for integrating the GRANDPA finality gadget into runtimes.
/// This should be implemented on the runtime side.
Expand All @@ -172,6 +229,6 @@ decl_runtime_apis! {
/// When called at block B, it will return the set of authorities that should be
/// used to finalize descendants of this block (B+1, B+2, ...). The block B itself
/// is finalized by the authorities from block B-1.
fn grandpa_authorities() -> Vec<(AuthorityId, AuthorityWeight)>;
fn grandpa_authorities() -> AuthorityList;
}
}
8 changes: 4 additions & 4 deletions core/finality-grandpa/src/authorities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use grandpa::voter_set::VoterSet;
use codec::{Encode, Decode};
use log::{debug, info};
use substrate_telemetry::{telemetry, CONSENSUS_INFO};
use fg_primitives::AuthorityId;
use fg_primitives::{AuthorityId, AuthorityList};

use std::cmp::Ord;
use std::fmt::Debug;
Expand Down Expand Up @@ -86,7 +86,7 @@ pub(crate) struct Status<H, N> {
/// A set of authorities.
#[derive(Debug, Clone, Encode, Decode, PartialEq)]
pub(crate) struct AuthoritySet<H, N> {
pub(crate) current_authorities: Vec<(AuthorityId, u64)>,
pub(crate) current_authorities: AuthorityList,
pub(crate) set_id: u64,
// Tree of pending standard changes across forks. Standard changes are
// enacted on finality and must be enacted (i.e. finalized) in-order across
Expand All @@ -103,7 +103,7 @@ where H: PartialEq,
N: Ord,
{
/// Get a genesis set with given authorities.
pub(crate) fn genesis(initial: Vec<(AuthorityId, u64)>) -> Self {
pub(crate) fn genesis(initial: AuthorityList) -> Self {
AuthoritySet {
current_authorities: initial,
set_id: 0,
Expand Down Expand Up @@ -390,7 +390,7 @@ pub(crate) enum DelayKind<N> {
#[derive(Debug, Clone, Encode, PartialEq)]
pub(crate) struct PendingChange<H, N> {
/// The new authorities and weights to apply.
pub(crate) next_authorities: Vec<(AuthorityId, u64)>,
pub(crate) next_authorities: AuthorityList,
/// How deep in the chain the announcing block must be
/// before the change is applied.
pub(crate) delay: N,
Expand Down
9 changes: 5 additions & 4 deletions core/finality-grandpa/src/aux_schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use fork_tree::ForkTree;
use grandpa::round::State as RoundState;
use sr_primitives::traits::{Block as BlockT, NumberFor};
use log::{info, warn};
use fg_primitives::{AuthorityId, AuthorityWeight, SetId, RoundNumber};
use fg_primitives::{AuthorityList, SetId, RoundNumber};

use crate::authorities::{AuthoritySet, SharedAuthoritySet, PendingChange, DelayKind};
use crate::consensus_changes::{SharedConsensusChanges, ConsensusChanges};
Expand Down Expand Up @@ -55,15 +55,15 @@ type V0VoterSetState<H, N> = (RoundNumber, RoundState<H, N>);

#[derive(Debug, Clone, Encode, Decode, PartialEq)]
struct V0PendingChange<H, N> {
next_authorities: Vec<(AuthorityId, AuthorityWeight)>,
next_authorities: AuthorityList,
delay: N,
canon_height: N,
canon_hash: H,
}

#[derive(Debug, Clone, Encode, Decode, PartialEq)]
struct V0AuthoritySet<H, N> {
current_authorities: Vec<(AuthorityId, AuthorityWeight)>,
current_authorities: AuthorityList,
set_id: SetId,
pending_changes: Vec<V0PendingChange<H, N>>,
}
Expand Down Expand Up @@ -266,7 +266,7 @@ pub(crate) fn load_persistent<Block: BlockT, B, G>(
-> ClientResult<PersistentData<Block>>
where
B: AuxStore,
G: FnOnce() -> ClientResult<Vec<(AuthorityId, AuthorityWeight)>>,
G: FnOnce() -> ClientResult<AuthorityList>,
{
let version: Option<u32> = load_decode(backend, VERSION_KEY)?;
let consensus_changes = load_decode(backend, CONSENSUS_CHANGES_KEY)?
Expand Down Expand Up @@ -426,6 +426,7 @@ pub(crate) fn load_authorities<B: AuxStore, H: Decode, N: Decode>(backend: &B)

#[cfg(test)]
mod test {
use fg_primitives::AuthorityId;
use primitives::H256;
use test_client;
use super::*;
Expand Down
3 changes: 2 additions & 1 deletion core/finality-grandpa/src/communication/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use codec::Encode;
use sr_primitives::traits::NumberFor;

use crate::environment::SharedVoterSetState;
use fg_primitives::AuthorityList;
use super::gossip::{self, GossipValidator};
use super::{AuthorityId, VoterSet, Round, SetId};

Expand Down Expand Up @@ -200,7 +201,7 @@ fn make_test_network() -> (
)
}

fn make_ids(keys: &[Ed25519Keyring]) -> Vec<(AuthorityId, u64)> {
fn make_ids(keys: &[Ed25519Keyring]) -> AuthorityList {
keys.iter()
.map(|key| key.clone().public().into())
.map(|id| (id, 1))
Expand Down
86 changes: 45 additions & 41 deletions core/finality-grandpa/src/finality_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,24 @@
//! finality proof (that finalizes some block C that is ancestor of the B and descendant
//! of the U) could be returned.

use std::iter;
use std::sync::Arc;
use log::{trace, warn};

use client::{
backend::Backend, blockchain::Backend as BlockchainBackend, CallExecutor, Client,
error::{Error as ClientError, Result as ClientResult},
light::fetcher::{FetchChecker, RemoteCallRequest, StorageProof}, ExecutionStrategy,
light::fetcher::{FetchChecker, RemoteReadRequest, StorageProof},
};
use codec::{Encode, Decode};
use grandpa::BlockNumberOps;
use sr_primitives::{
Justification, generic::BlockId,
traits::{NumberFor, Block as BlockT, Header as HeaderT, One},
};
use primitives::{H256, Blake2Hasher};
use primitives::{H256, Blake2Hasher, storage::StorageKey};
use substrate_telemetry::{telemetry, CONSENSUS_INFO};
use fg_primitives::AuthorityId;
use fg_primitives::{AuthorityId, AuthorityList, VersionedAuthorityList, GRANDPA_AUTHORITIES_KEY};

use crate::justification::GrandpaJustification;

Expand All @@ -59,9 +60,9 @@ const MAX_FRAGMENTS_IN_PROOF: usize = 8;

/// GRANDPA authority set related methods for the finality proof provider.
pub trait AuthoritySetForFinalityProver<Block: BlockT>: Send + Sync {
/// Call GrandpaApi::grandpa_authorities at given block.
fn authorities(&self, block: &BlockId<Block>) -> ClientResult<Vec<(AuthorityId, u64)>>;
/// Prove call of GrandpaApi::grandpa_authorities at given block.
/// Read GRANDPA_AUTHORITIES_KEY from storage at given block.
fn authorities(&self, block: &BlockId<Block>) -> ClientResult<AuthorityList>;
/// Prove storage read of GRANDPA_AUTHORITIES_KEY at given block.
fn prove_authorities(&self, block: &BlockId<Block>) -> ClientResult<StorageProof>;
}

Expand All @@ -72,33 +73,28 @@ impl<B, E, Block: BlockT<Hash=H256>, RA> AuthoritySetForFinalityProver<Block> fo
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
RA: Send + Sync,
{
fn authorities(&self, block: &BlockId<Block>) -> ClientResult<Vec<(AuthorityId, u64)>> {
self.executor().call(
block,
"GrandpaApi_grandpa_authorities",
&[],
ExecutionStrategy::NativeElseWasm,
None,
).and_then(|call_result| Decode::decode(&mut &call_result[..])
.map_err(|err| ClientError::CallResultDecode(
"failed to decode GRANDPA authorities set proof".into(), err
)))
fn authorities(&self, block: &BlockId<Block>) -> ClientResult<AuthorityList> {
let storage_key = StorageKey(GRANDPA_AUTHORITIES_KEY.to_vec());
self.storage(block, &storage_key)?
.and_then(|encoded| VersionedAuthorityList::decode(&mut encoded.0.as_slice()).ok())
.map(|versioned| versioned.into())
.ok_or(ClientError::InvalidAuthoritiesSet)
}

fn prove_authorities(&self, block: &BlockId<Block>) -> ClientResult<StorageProof> {
self.execution_proof(block, "GrandpaApi_grandpa_authorities",&[]).map(|(_, proof)| proof)
self.read_proof(block, iter::once(GRANDPA_AUTHORITIES_KEY))
}
}

/// GRANDPA authority set related methods for the finality proof checker.
pub trait AuthoritySetForFinalityChecker<Block: BlockT>: Send + Sync {
/// Check execution proof of Grandpa::grandpa_authorities at given block.
/// Check storage read proof of GRANDPA_AUTHORITIES_KEY at given block.
fn check_authorities_proof(
&self,
hash: Block::Hash,
header: Block::Header,
proof: StorageProof,
) -> ClientResult<Vec<(AuthorityId, u64)>>;
) -> ClientResult<AuthorityList>;
}

/// FetchChecker-based implementation of AuthoritySetForFinalityChecker.
Expand All @@ -108,22 +104,30 @@ impl<Block: BlockT> AuthoritySetForFinalityChecker<Block> for Arc<dyn FetchCheck
hash: Block::Hash,
header: Block::Header,
proof: StorageProof,
) -> ClientResult<Vec<(AuthorityId, u64)>> {
let request = RemoteCallRequest {
) -> ClientResult<AuthorityList> {
let storage_key = GRANDPA_AUTHORITIES_KEY.to_vec();
let request = RemoteReadRequest {
block: hash,
header,
method: "GrandpaApi_grandpa_authorities".into(),
call_data: vec![],
keys: vec![storage_key.clone()],
retry_count: None,
};

self.check_execution_proof(&request, proof)
.and_then(|authorities| {
let authorities: Vec<(AuthorityId, u64)> = Decode::decode(&mut &authorities[..])
.map_err(|err| ClientError::CallResultDecode(
"failed to decode GRANDPA authorities set proof".into(), err
))?;
Ok(authorities.into_iter().collect())
self.check_read_proof(&request, proof)
.and_then(|results| {
let maybe_encoded = results.get(&storage_key)
.expect(
"storage_key is listed in the request keys; \
check_read_proof must return a value for each requested key;
qed"
);
maybe_encoded
.as_ref()
.and_then(|encoded| {
VersionedAuthorityList::decode(&mut encoded.as_slice()).ok()
})
.map(|versioned| versioned.into())
.ok_or(ClientError::InvalidAuthoritiesSet)
})
}
}
Expand Down Expand Up @@ -189,7 +193,7 @@ pub struct FinalityEffects<Header: HeaderT> {
/// New authorities set id that should be applied starting from block.
pub new_set_id: u64,
/// New authorities set that should be applied starting from block.
pub new_authorities: Vec<(AuthorityId, u64)>,
pub new_authorities: AuthorityList,
}

/// Single fragment of proof-of-finality.
Expand Down Expand Up @@ -408,7 +412,7 @@ pub(crate) fn prove_finality<Block: BlockT<Hash=H256>, B: BlockchainBackend<Bloc
pub(crate) fn check_finality_proof<Block: BlockT<Hash=H256>, B>(
blockchain: &B,
current_set_id: u64,
current_authorities: Vec<(AuthorityId, u64)>,
current_authorities: AuthorityList,
authorities_provider: &dyn AuthoritySetForFinalityChecker<Block>,
remote_proof: Vec<u8>,
) -> ClientResult<FinalityEffects<Block::Header>>
Expand All @@ -427,7 +431,7 @@ pub(crate) fn check_finality_proof<Block: BlockT<Hash=H256>, B>(
fn do_check_finality_proof<Block: BlockT<Hash=H256>, B, J>(
blockchain: &B,
current_set_id: u64,
current_authorities: Vec<(AuthorityId, u64)>,
current_authorities: AuthorityList,
authorities_provider: &dyn AuthoritySetForFinalityChecker<Block>,
remote_proof: Vec<u8>,
) -> ClientResult<FinalityEffects<Block::Header>>
Expand Down Expand Up @@ -522,12 +526,12 @@ fn check_finality_proof_fragment<Block: BlockT<Hash=H256>, B, J>(

/// Authorities set from initial authorities set or finality effects.
enum AuthoritiesOrEffects<Header: HeaderT> {
Authorities(u64, Vec<(AuthorityId, u64)>),
Authorities(u64, AuthorityList),
Effects(FinalityEffects<Header>),
}

impl<Header: HeaderT> AuthoritiesOrEffects<Header> {
pub fn extract_authorities(self) -> (u64, Vec<(AuthorityId, u64)>) {
pub fn extract_authorities(self) -> (u64, AuthorityList) {
match self {
AuthoritiesOrEffects::Authorities(set_id, authorities) => (set_id, authorities),
AuthoritiesOrEffects::Effects(effects) => (effects.new_set_id, effects.new_authorities),
Expand Down Expand Up @@ -581,10 +585,10 @@ pub(crate) mod tests {

impl<GetAuthorities, ProveAuthorities> AuthoritySetForFinalityProver<Block> for (GetAuthorities, ProveAuthorities)
where
GetAuthorities: Send + Sync + Fn(BlockId<Block>) -> ClientResult<Vec<(AuthorityId, u64)>>,
GetAuthorities: Send + Sync + Fn(BlockId<Block>) -> ClientResult<AuthorityList>,
ProveAuthorities: Send + Sync + Fn(BlockId<Block>) -> ClientResult<StorageProof>,
{
fn authorities(&self, block: &BlockId<Block>) -> ClientResult<Vec<(AuthorityId, u64)>> {
fn authorities(&self, block: &BlockId<Block>) -> ClientResult<AuthorityList> {
self.0(*block)
}

Expand All @@ -597,14 +601,14 @@ pub(crate) mod tests {

impl<Closure> AuthoritySetForFinalityChecker<Block> for ClosureAuthoritySetForFinalityChecker<Closure>
where
Closure: Send + Sync + Fn(H256, Header, StorageProof) -> ClientResult<Vec<(AuthorityId, u64)>>,
Closure: Send + Sync + Fn(H256, Header, StorageProof) -> ClientResult<AuthorityList>,
{
fn check_authorities_proof(
&self,
hash: H256,
header: Header,
proof: StorageProof,
) -> ClientResult<Vec<(AuthorityId, u64)>> {
proof: StorageProof
) -> ClientResult<AuthorityList> {
self.0(hash, header, proof)
}
}
Expand Down
Loading