From e8239bc345f291e7f6c7ab70450f00df99175323 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Thu, 31 Oct 2019 17:46:44 +0100 Subject: [PATCH] grandpa: Re-add Grandpa runtime API for genesis authority set. --- Cargo.lock | 1 + core/authority-discovery/src/lib.rs | 2 +- core/finality-grandpa/primitives/Cargo.toml | 2 ++ core/finality-grandpa/primitives/src/lib.rs | 23 +++++++++++++++++++++ core/finality-grandpa/src/lib.rs | 20 ++++++++++++++---- core/finality-grandpa/src/tests.rs | 18 ++++++++++++++-- node-template/runtime/src/lib.rs | 9 +++++++- node/runtime/src/lib.rs | 9 +++++++- srml/grandpa/src/lib.rs | 3 +++ 9 files changed, 78 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5bee6302ec8ef..13fc0dcd51a77 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5275,6 +5275,7 @@ dependencies = [ "sr-primitives 2.0.0", "sr-std 2.0.0", "substrate-application-crypto 2.0.0", + "substrate-client 2.0.0", ] [[package]] diff --git a/core/authority-discovery/src/lib.rs b/core/authority-discovery/src/lib.rs index 8e2663d210a83..6365002e22cca 100644 --- a/core/authority-discovery/src/lib.rs +++ b/core/authority-discovery/src/lib.rs @@ -44,7 +44,7 @@ //! 4. Adds the retrieved external addresses as priority nodes to the peerset. use authority_discovery_primitives::{AuthorityDiscoveryApi, AuthorityId, Signature}; -use client::{blockchain::HeaderBackend, runtime_api::StorageProof}; +use client::blockchain::HeaderBackend; use error::{Error, Result}; use futures::{prelude::*, sync::mpsc::Receiver}; use log::{debug, error, log_enabled, warn}; diff --git a/core/finality-grandpa/primitives/Cargo.toml b/core/finality-grandpa/primitives/Cargo.toml index 90d7af5777c7c..02439d4150d81 100644 --- a/core/finality-grandpa/primitives/Cargo.toml +++ b/core/finality-grandpa/primitives/Cargo.toml @@ -5,6 +5,7 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] +client = { package = "substrate-client", path = "../../client", default-features = false } app-crypto = { package = "substrate-application-crypto", path = "../../application-crypto", default-features = false } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } sr-primitives = { path = "../../sr-primitives", default-features = false } @@ -14,6 +15,7 @@ serde = { version = "1.0.101", optional = true, features = ["derive"] } [features] default = ["std"] std = [ + "client/std", "codec/std", "sr-primitives/std", "rstd/std", diff --git a/core/finality-grandpa/primitives/src/lib.rs b/core/finality-grandpa/primitives/src/lib.rs index 3f5b4cb7f6ed2..e7d399a89200b 100644 --- a/core/finality-grandpa/primitives/src/lib.rs +++ b/core/finality-grandpa/primitives/src/lib.rs @@ -25,6 +25,7 @@ extern crate alloc; use serde::Serialize; use codec::{Encode, Decode, Input, Codec}; use sr_primitives::{ConsensusEngineId, RuntimeDebug}; +use client::decl_runtime_apis; use rstd::borrow::Cow; use rstd::vec::Vec; @@ -209,3 +210,25 @@ impl<'a> Decode for VersionedAuthorityList<'a> { Ok(authorities.into()) } } + +decl_runtime_apis! { + /// APIs for integrating the GRANDPA finality gadget into runtimes. + /// This should be implemented on the runtime side. + /// + /// This is primarily used for negotiating authority-set changes for the + /// gadget. GRANDPA uses a signaling model of changing authority sets: + /// changes should be signaled with a delay of N blocks, and then automatically + /// applied in the runtime after those N blocks have passed. + /// + /// The consensus protocol will coordinate the handoff externally. + #[api_version(2)] + pub trait GrandpaApi { + /// Get the current GRANDPA authorities and weights. This should not change except + /// for when changes are scheduled and the corresponding delay has passed. + /// + /// 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() -> AuthorityList; + } +} diff --git a/core/finality-grandpa/src/lib.rs b/core/finality-grandpa/src/lib.rs index 67acaa21d760b..a22257af3d30d 100644 --- a/core/finality-grandpa/src/lib.rs +++ b/core/finality-grandpa/src/lib.rs @@ -57,9 +57,10 @@ use log::{debug, error, info}; use futures::sync::mpsc; use client::{ BlockchainEvents, CallExecutor, Client, backend::Backend, error::Error as ClientError, + ExecutionStrategy, }; use client::blockchain::HeaderBackend; -use codec::Encode; +use codec::{Decode, Encode}; use sr_primitives::generic::BlockId; use sr_primitives::traits::{NumberFor, Block as BlockT, DigestFor, Zero}; use keystore::KeyStorePtr; @@ -377,9 +378,20 @@ impl, RA> GenesisAuthoritySetProvider for RA: Send + Sync, { fn get(&self) -> Result { - use finality_proof::AuthoritySetForFinalityProver; - - self.authorities(&BlockId::Number(Zero::zero())) + self.executor() + .call( + &BlockId::Number(Zero::zero()), + "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 + )) + }) } } diff --git a/core/finality-grandpa/src/tests.rs b/core/finality-grandpa/src/tests.rs index 93c08a9661baf..f56fe689e1573 100644 --- a/core/finality-grandpa/src/tests.rs +++ b/core/finality-grandpa/src/tests.rs @@ -199,13 +199,15 @@ impl TestApi { } } -pub(crate) struct RuntimeApi; +pub(crate) struct RuntimeApi { + inner: TestApi, +} impl ProvideRuntimeApi for TestApi { type Api = RuntimeApi; fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api> { - RuntimeApi.into() + RuntimeApi { inner: self.clone() }.into() } } @@ -262,6 +264,18 @@ impl ApiExt for RuntimeApi { } } +impl GrandpaApi for RuntimeApi { + fn GrandpaApi_grandpa_authorities_runtime_api_impl( + &self, + _: &BlockId, + _: ExecutionContext, + _: Option<()>, + _: Vec, + ) -> Result> { + Ok(self.inner.genesis_authorities.clone()).map(NativeOrEncoded::Native) + } +} + impl GenesisAuthoritySetProvider for TestApi { fn get(&self) -> Result { Ok(self.genesis_authorities.clone()) diff --git a/node-template/runtime/src/lib.rs b/node-template/runtime/src/lib.rs index 5b440cdd9b705..071e07a52e8b5 100644 --- a/node-template/runtime/src/lib.rs +++ b/node-template/runtime/src/lib.rs @@ -23,7 +23,8 @@ use client::{ runtime_api as client_api, impl_runtime_apis }; use aura_primitives::sr25519::AuthorityId as AuraId; -use grandpa::AuthorityId as GrandpaId; +use grandpa::AuthorityList as GrandpaAuthorityList; +use grandpa::fg_primitives; use version::RuntimeVersion; #[cfg(feature = "std")] use version::NativeVersion; @@ -352,4 +353,10 @@ impl_runtime_apis! { opaque::SessionKeys::generate(seed) } } + + impl fg_primitives::GrandpaApi for Runtime { + fn grandpa_authorities() -> GrandpaAuthorityList { + Grandpa::grandpa_authorities() + } + } } diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index adee13775d7d3..fe6890bfaee16 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -45,7 +45,8 @@ use version::RuntimeVersion; #[cfg(any(feature = "std", test))] use version::NativeVersion; use primitives::OpaqueMetadata; -use grandpa::AuthorityId as GrandpaId; +use grandpa::AuthorityList as GrandpaAuthorityList; +use grandpa::fg_primitives; use im_online::sr25519::{AuthorityId as ImOnlineId}; use transaction_payment_rpc_runtime_api::RuntimeDispatchInfo; use contracts_rpc_runtime_api::ContractExecResult; @@ -610,6 +611,12 @@ impl_runtime_apis! { } } + impl fg_primitives::GrandpaApi for Runtime { + fn grandpa_authorities() -> GrandpaAuthorityList { + Grandpa::grandpa_authorities() + } + } + impl babe_primitives::BabeApi for Runtime { fn configuration() -> babe_primitives::BabeConfiguration { // The choice of `c` parameter (where `1 - c` represents the diff --git a/srml/grandpa/src/lib.rs b/srml/grandpa/src/lib.rs index b635b88521ba3..877521c9746d9 100644 --- a/srml/grandpa/src/lib.rs +++ b/srml/grandpa/src/lib.rs @@ -21,6 +21,9 @@ //! //! In the future, it will also handle misbehavior reports, and on-chain //! finality notifications. +//! +//! For full integration with GRANDPA, the `GrandpaApi` should be implemented. +//! The necessary items are re-exported via the `fg_primitives` crate. #![cfg_attr(not(feature = "std"), no_std)]