diff --git a/Cargo.lock b/Cargo.lock index 84f487ceedc99..fb944b782abd9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1679,9 +1679,9 @@ dependencies = [ [[package]] name = "finality-grandpa" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6447e2f8178843749e8c8003206def83ec124a7859475395777a28b5338647c" +checksum = "74a1bfdcc776e63e49f741c7ce6116fa1b887e8ac2e3ccb14dd4aa113e54feb9" dependencies = [ "either", "futures 0.3.15", diff --git a/client/finality-grandpa-warp-sync/Cargo.toml b/client/finality-grandpa-warp-sync/Cargo.toml index 3557d543c987e..27728e159c762 100644 --- a/client/finality-grandpa-warp-sync/Cargo.toml +++ b/client/finality-grandpa-warp-sync/Cargo.toml @@ -28,7 +28,7 @@ sp-finality-grandpa = { version = "3.0.0", path = "../../primitives/finality-gra sp-runtime = { version = "3.0.0", path = "../../primitives/runtime" } [dev-dependencies] -finality-grandpa = { version = "0.14.0" } +finality-grandpa = { version = "0.14.1" } rand = "0.8" sc-block-builder = { version = "0.9.0", path = "../block-builder" } sp-consensus = { version = "0.9.0", path = "../../primitives/consensus/common" } diff --git a/client/finality-grandpa-warp-sync/src/lib.rs b/client/finality-grandpa-warp-sync/src/lib.rs index a6b7e46a0f029..c0ef93e625fd8 100644 --- a/client/finality-grandpa-warp-sync/src/lib.rs +++ b/client/finality-grandpa-warp-sync/src/lib.rs @@ -40,7 +40,8 @@ pub fn request_response_config_for_chain, authority_set: SharedAuthoritySet>, ) -> RequestResponseConfig - where NumberFor: sc_finality_grandpa::BlockNumberOps, +where + NumberFor: sc_finality_grandpa::BlockNumberOps, { let protocol_id = config.protocol_id(); @@ -54,7 +55,7 @@ pub fn request_response_config_for_chain SyncCryptoStorePtr{ + fn keystore(&self) -> SyncCryptoStorePtr { (self.0).1.clone() } } diff --git a/client/finality-grandpa/src/environment.rs b/client/finality-grandpa/src/environment.rs index d3a5b49b50726..3d593a17ffdbf 100644 --- a/client/finality-grandpa/src/environment.rs +++ b/client/finality-grandpa/src/environment.rs @@ -23,43 +23,42 @@ use std::pin::Pin; use std::sync::Arc; use std::time::Duration; +use finality_grandpa::{ + round::State as RoundState, voter, voter_set::VoterSet, BlockNumberOps, Error as GrandpaError, +}; use futures::prelude::*; use futures_timer::Delay; use log::{debug, warn}; use parity_scale_codec::{Decode, Encode}; use parking_lot::RwLock; +use prometheus_endpoint::{register, Counter, Gauge, PrometheusError, U64}; -use sc_client_api::{backend::{Backend, apply_aux}, utils::is_descendent_of}; -use finality_grandpa::{ - BlockNumberOps, Error as GrandpaError, round::State as RoundState, - voter, voter_set::VoterSet, +use sc_client_api::{ + backend::{apply_aux, Backend}, + utils::is_descendent_of, }; +use sc_telemetry::{telemetry, TelemetryHandle, CONSENSUS_DEBUG, CONSENSUS_INFO}; use sp_blockchain::HeaderMetadata; -use sp_runtime::generic::BlockId; -use sp_runtime::traits::{ - Block as BlockT, Header as HeaderT, NumberFor, Zero, +use sp_consensus::SelectChain; +use sp_finality_grandpa::{ + AuthorityId, AuthoritySignature, Equivocation, EquivocationProof, GrandpaApi, RoundNumber, + SetId, GRANDPA_ENGINE_ID, }; -use sc_telemetry::{telemetry, TelemetryHandle, CONSENSUS_DEBUG, CONSENSUS_INFO}; +use sp_runtime::generic::BlockId; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero}; use crate::{ - local_authority_id, CommandOrError, Commit, Config, Error, NewAuthoritySet, Precommit, Prevote, + authorities::{AuthoritySet, SharedAuthoritySet}, + communication::Network as NetworkT, + justification::GrandpaJustification, + local_authority_id, + notification::GrandpaJustificationSender, + until_imported::UntilVoteTargetImported, + voting_rule::VotingRule, + ClientForGrandpa, CommandOrError, Commit, Config, Error, NewAuthoritySet, Precommit, Prevote, PrimaryPropose, SignedMessage, VoterCommand, }; -use sp_consensus::SelectChain; - -use crate::authorities::{AuthoritySet, SharedAuthoritySet}; -use crate::communication::Network as NetworkT; -use crate::notification::GrandpaJustificationSender; -use crate::justification::GrandpaJustification; -use crate::until_imported::UntilVoteTargetImported; -use crate::voting_rule::VotingRule; -use sp_finality_grandpa::{ - AuthorityId, AuthoritySignature, Equivocation, EquivocationProof, GRANDPA_ENGINE_ID, - GrandpaApi, RoundNumber, SetId, -}; -use prometheus_endpoint::{register, Counter, Gauge, PrometheusError, U64}; - type HistoricalVotes = finality_grandpa::HistoricalVotes< ::Hash, NumberFor, @@ -480,10 +479,10 @@ impl Environment where Block: BlockT, BE: Backend, - C: crate::ClientForGrandpa, + C: ClientForGrandpa, C::Api: GrandpaApi, N: NetworkT, - SC: SelectChain + 'static, + SC: SelectChain, { /// Report the given equivocation to the GRANDPA runtime module. This method /// generates a session membership proof of the offender and then submits an @@ -578,24 +577,26 @@ where } } -impl - finality_grandpa::Chain> -for Environment +impl finality_grandpa::Chain> + for Environment where - Block: 'static, + Block: BlockT, BE: Backend, - C: crate::ClientForGrandpa, - N: NetworkT + 'static + Send, - SC: SelectChain + 'static, + C: ClientForGrandpa, + N: NetworkT, + SC: SelectChain, VR: VotingRule, NumberFor: BlockNumberOps, { - fn ancestry(&self, base: Block::Hash, block: Block::Hash) -> Result, GrandpaError> { + fn ancestry( + &self, + base: Block::Hash, + block: Block::Hash, + ) -> Result, GrandpaError> { ancestry(&self.client, base, block) } } - pub(crate) fn ancestry( client: &Arc, base: Block::Hash, @@ -624,27 +625,31 @@ where // skip one because our ancestry is meant to start from the parent of `block`, // and `tree_route` includes it. - Ok(tree_route.retracted().iter().skip(1).map(|e| e.hash).collect()) + Ok(tree_route + .retracted() + .iter() + .skip(1) + .map(|e| e.hash) + .collect()) } -impl voter::Environment> +impl voter::Environment> for Environment where - Block: 'static, + Block: BlockT, B: Backend, - C: crate::ClientForGrandpa + 'static, + C: ClientForGrandpa + 'static, C::Api: GrandpaApi, - N: NetworkT + 'static + Send + Sync, - SC: SelectChain + 'static, + N: NetworkT, + SC: SelectChain, VR: VotingRule, NumberFor: BlockNumberOps, { - type Timer = Pin> + Send + Sync>>; + type Timer = Pin> + Send>>; type BestChain = Pin< Box< dyn Future)>, Self::Error>> - + Send - + Sync + + Send, >, >; @@ -652,13 +657,29 @@ where type Signature = AuthoritySignature; // regular round message streams - type In = Pin, Self::Signature, Self::Id>, Self::Error> - > + Send + Sync>>; - type Out = Pin>, - Error = Self::Error, - > + Send + Sync>>; + type In = Pin< + Box< + dyn Stream< + Item = Result< + ::finality_grandpa::SignedMessage< + Block::Hash, + NumberFor, + Self::Signature, + Self::Id, + >, + Self::Error, + >, + > + Send, + >, + >; + type Out = Pin< + Box< + dyn Sink< + ::finality_grandpa::Message>, + Error = Self::Error, + > + Send, + >, + >; type Error = CommandOrError>; @@ -1223,7 +1244,7 @@ pub(crate) fn finalize_block( where Block: BlockT, BE: Backend, - Client: crate::ClientForGrandpa, + Client: ClientForGrandpa, { // NOTE: lock must be held through writing to DB to avoid race. this lock // also implicitly synchronizes the check for last finalized number diff --git a/client/finality-grandpa/src/finality_proof.rs b/client/finality-grandpa/src/finality_proof.rs index 6735d91ba8b75..ec33d48774ae5 100644 --- a/client/finality-grandpa/src/finality_proof.rs +++ b/client/finality-grandpa/src/finality_proof.rs @@ -62,9 +62,10 @@ pub struct FinalityProofProvider { shared_authority_set: Option>>, } -impl FinalityProofProvider +impl FinalityProofProvider where - B: Backend + Send + Sync + 'static, + Block: BlockT, + B: Backend, { /// Create new finality proof provider using: /// @@ -97,7 +98,7 @@ where impl FinalityProofProvider where Block: BlockT, - B: Backend + Send + Sync + 'static, + B: Backend, { /// Prove finality for the given block number by returning a Justification for the last block of /// the authority set. diff --git a/client/finality-grandpa/src/import.rs b/client/finality-grandpa/src/import.rs index 3d22cc8866100..de02ea357cac4 100644 --- a/client/finality-grandpa/src/import.rs +++ b/client/finality-grandpa/src/import.rs @@ -16,36 +16,33 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::{sync::Arc, collections::HashMap}; +use std::{collections::HashMap, marker::PhantomData, sync::Arc}; use log::debug; use parity_scale_codec::Encode; -use sp_blockchain::{BlockStatus, well_known_cache_keys}; use sc_client_api::{backend::Backend, utils::is_descendent_of}; +use sc_consensus::shared_data::{SharedDataLocked, SharedDataLockedUpgradable}; use sc_telemetry::TelemetryHandle; -use sp_utils::mpsc::TracingUnboundedSender; use sp_api::TransactionFor; -use sc_consensus::shared_data::{SharedDataLockedUpgradable, SharedDataLocked}; - +use sp_blockchain::{well_known_cache_keys, BlockStatus}; use sp_consensus::{ - BlockImport, Error as ConsensusError, - BlockCheckParams, BlockImportParams, BlockOrigin, ImportResult, JustificationImport, - SelectChain, + BlockCheckParams, BlockImport, BlockImportParams, BlockOrigin, Error as ConsensusError, + ImportResult, JustificationImport, SelectChain, }; use sp_finality_grandpa::{ConsensusLog, ScheduledChange, SetId, GRANDPA_ENGINE_ID}; -use sp_runtime::Justification; use sp_runtime::generic::{BlockId, OpaqueDigestItemId}; -use sp_runtime::traits::{ - Block as BlockT, DigestFor, Header as HeaderT, NumberFor, Zero, -}; +use sp_runtime::traits::{Block as BlockT, DigestFor, Header as HeaderT, NumberFor, Zero}; +use sp_runtime::Justification; +use sp_utils::mpsc::TracingUnboundedSender; -use crate::{Error, CommandOrError, NewAuthoritySet, VoterCommand}; -use crate::authorities::{AuthoritySet, SharedAuthoritySet, DelayKind, PendingChange}; -use crate::environment::finalize_block; -use crate::justification::GrandpaJustification; -use crate::notification::GrandpaJustificationSender; -use std::marker::PhantomData; +use crate::{ + authorities::{AuthoritySet, DelayKind, PendingChange, SharedAuthoritySet}, + environment::finalize_block, + justification::GrandpaJustification, + notification::GrandpaJustificationSender, + ClientForGrandpa, CommandOrError, Error, NewAuthoritySet, VoterCommand, +}; /// A block-import handler for GRANDPA. /// @@ -67,8 +64,8 @@ pub struct GrandpaBlockImport { _phantom: PhantomData, } -impl Clone for - GrandpaBlockImport +impl Clone + for GrandpaBlockImport { fn clone(&self) -> Self { GrandpaBlockImport { @@ -85,12 +82,13 @@ impl Clone for } impl JustificationImport - for GrandpaBlockImport where - NumberFor: finality_grandpa::BlockNumberOps, - DigestFor: Encode, - BE: Backend, - Client: crate::ClientForGrandpa, - SC: SelectChain, + for GrandpaBlockImport +where + NumberFor: finality_grandpa::BlockNumberOps, + DigestFor: Encode, + BE: Backend, + Client: ClientForGrandpa, + SC: SelectChain, { type Error = ConsensusError; @@ -219,13 +217,12 @@ pub fn find_forced_change( header.digest().convert_first(|l| l.try_to(id).and_then(filter_log)) } -impl - GrandpaBlockImport +impl GrandpaBlockImport where NumberFor: finality_grandpa::BlockNumberOps, DigestFor: Encode, BE: Backend, - Client: crate::ClientForGrandpa, + Client: ClientForGrandpa, { // check for a new authority set change. fn check_new_change( @@ -416,21 +413,25 @@ where let just_in_case = just_in_case.map(|(o, i)| (o, i.release_mutex())); - Ok(PendingSetChanges { just_in_case, applied_changes, do_pause }) + Ok(PendingSetChanges { + just_in_case, + applied_changes, + do_pause, + }) } } #[async_trait::async_trait] -impl BlockImport - for GrandpaBlockImport where - NumberFor: finality_grandpa::BlockNumberOps, - DigestFor: Encode, - BE: Backend, - Client: crate::ClientForGrandpa, - for<'a> &'a Client: - BlockImport>, - TransactionFor: Send + 'static, - SC: Send, +impl BlockImport for GrandpaBlockImport +where + NumberFor: finality_grandpa::BlockNumberOps, + DigestFor: Encode, + BE: Backend, + Client: ClientForGrandpa, + for<'a> &'a Client: + BlockImport>, + TransactionFor: 'static, + SC: Send, { type Error = ConsensusError; type Transaction = TransactionFor; @@ -630,7 +631,7 @@ impl GrandpaBlockImport GrandpaBlockImport where BE: Backend, - Client: crate::ClientForGrandpa, + Client: ClientForGrandpa, NumberFor: finality_grandpa::BlockNumberOps, { /// Import a block justification and finalize the block. diff --git a/client/finality-grandpa/src/lib.rs b/client/finality-grandpa/src/lib.rs index f249d3982cf25..a133319fdbef4 100644 --- a/client/finality-grandpa/src/lib.rs +++ b/client/finality-grandpa/src/lib.rs @@ -627,13 +627,17 @@ fn global_communication( metrics: Option, ) -> ( impl Stream< - Item = Result, CommandOrError>>, + Item = Result< + CommunicationInH, + CommandOrError>, + >, >, impl Sink< CommunicationOutH, Error = CommandOrError>, - > + Unpin, -) where + >, +) +where BE: Backend + 'static, C: ClientForGrandpa + 'static, N: NetworkT, @@ -707,11 +711,11 @@ pub fn grandpa_peers_set_config() -> sc_network::config::NonDefaultSetConfig { /// block import worker that has already been instantiated with `block_import`. pub fn run_grandpa_voter( grandpa_params: GrandpaParams, -) -> sp_blockchain::Result + Unpin + Send + 'static> +) -> sp_blockchain::Result + Send> where Block::Hash: Ord, BE: Backend + 'static, - N: NetworkT + Send + Sync + Clone + 'static, + N: NetworkT + Sync + 'static, SC: SelectChain + 'static, VR: VotingRule + Clone + 'static, NumberFor: BlockNumberOps, diff --git a/client/finality-grandpa/src/observer.rs b/client/finality-grandpa/src/observer.rs index 5434cd08a91d0..23c4f873a10b7 100644 --- a/client/finality-grandpa/src/observer.rs +++ b/client/finality-grandpa/src/observer.rs @@ -16,33 +16,33 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use std::marker::{PhantomData, Unpin}; use std::pin::Pin; use std::sync::Arc; use std::task::{Context, Poll}; +use finality_grandpa::{voter, voter_set::VoterSet, BlockNumberOps, Error as GrandpaError}; use futures::prelude::*; - -use finality_grandpa::{ - BlockNumberOps, Error as GrandpaError, voter, voter_set::VoterSet -}; use log::{debug, info, warn}; -use sp_keystore::SyncCryptoStorePtr; -use sp_consensus::SelectChain; + use sc_client_api::backend::Backend; use sc_telemetry::TelemetryHandle; -use sp_utils::mpsc::TracingUnboundedReceiver; -use sp_runtime::traits::{NumberFor, Block as BlockT}; use sp_blockchain::HeaderMetadata; +use sp_consensus::SelectChain; +use sp_finality_grandpa::AuthorityId; +use sp_keystore::SyncCryptoStorePtr; +use sp_runtime::traits::{Block as BlockT, NumberFor}; +use sp_utils::mpsc::TracingUnboundedReceiver; use crate::{ - global_communication, CommandOrError, CommunicationIn, Config, environment, - LinkHalf, Error, aux_schema::PersistentData, VoterCommand, VoterSetState, + authorities::SharedAuthoritySet, + aux_schema::PersistentData, + communication::{Network as NetworkT, NetworkBridge}, + environment, global_communication, + notification::GrandpaJustificationSender, + ClientForGrandpa, CommandOrError, CommunicationIn, Config, Error, LinkHalf, VoterCommand, + VoterSetState, }; -use crate::authorities::SharedAuthoritySet; -use crate::communication::{Network as NetworkT, NetworkBridge}; -use crate::notification::GrandpaJustificationSender; -use sp_finality_grandpa::AuthorityId; -use std::marker::{PhantomData, Unpin}; struct ObserverChain<'a, Block: BlockT, Client> { client: &'a Arc, @@ -50,12 +50,17 @@ struct ObserverChain<'a, Block: BlockT, Client> { } impl<'a, Block, Client> finality_grandpa::Chain> - for ObserverChain<'a, Block, Client> where - Block: BlockT, - Client: HeaderMetadata, - NumberFor: BlockNumberOps, + for ObserverChain<'a, Block, Client> +where + Block: BlockT, + Client: HeaderMetadata, + NumberFor: BlockNumberOps, { - fn ancestry(&self, base: Block::Hash, block: Block::Hash) -> Result, GrandpaError> { + fn ancestry( + &self, + base: Block::Hash, + block: Block::Hash, + ) -> Result, GrandpaError> { environment::ancestry(&self.client, base, block) } } @@ -75,7 +80,7 @@ where S: Stream, CommandOrError>>>, F: Fn(u64), BE: Backend, - Client: crate::ClientForGrandpa, + Client: ClientForGrandpa, { let authority_set = authority_set.clone(); let client = client.clone(); @@ -160,13 +165,13 @@ pub fn run_grandpa_observer( config: Config, link: LinkHalf, network: N, -) -> sp_blockchain::Result + Unpin + Send + 'static> +) -> sp_blockchain::Result + Send> where BE: Backend + Unpin + 'static, - N: NetworkT + Send + Clone + 'static, - SC: SelectChain + 'static, + N: NetworkT, + SC: SelectChain, NumberFor: BlockNumberOps, - Client: crate::ClientForGrandpa + 'static, + Client: ClientForGrandpa + 'static, { let LinkHalf { client, @@ -223,7 +228,7 @@ impl ObserverWork where B: BlockT, BE: Backend + 'static, - Client: crate::ClientForGrandpa + 'static, + Client: ClientForGrandpa + 'static, Network: NetworkT, NumberFor: BlockNumberOps, { @@ -236,7 +241,6 @@ where justification_sender: Option>, telemetry: Option, ) -> Self { - let mut work = ObserverWork { // `observer` is set to a temporary value and replaced below when // calling `rebuild_observer`. @@ -344,7 +348,7 @@ impl Future for ObserverWork where B: BlockT, BE: Backend + Unpin + 'static, - C: crate::ClientForGrandpa + 'static, + C: ClientForGrandpa + 'static, N: NetworkT, NumberFor: BlockNumberOps, { diff --git a/client/finality-grandpa/src/tests.rs b/client/finality-grandpa/src/tests.rs index 475c11191b10c..725beec6a94b2 100644 --- a/client/finality-grandpa/src/tests.rs +++ b/client/finality-grandpa/src/tests.rs @@ -1013,7 +1013,7 @@ fn voter_persists_its_votes() { fn alice_voter2( peers: &[Ed25519Keyring], net: Arc>, - ) -> impl Future + Unpin + Send + 'static { + ) -> impl Future + Send { let (keystore, _) = create_keystore(peers[0]); let mut net = net.lock(); diff --git a/client/finality-grandpa/src/until_imported.rs b/client/finality-grandpa/src/until_imported.rs index d2e896685658b..7cfd9e6074c47 100644 --- a/client/finality-grandpa/src/until_imported.rs +++ b/client/finality-grandpa/src/until_imported.rs @@ -136,12 +136,14 @@ impl Drop for Metrics { fn drop(&mut self) { // Reduce the global counter by the amount of messages that were still left in the dropped // queue. - self.global_waiting_messages.sub(self.local_waiting_messages) + self.global_waiting_messages + .sub(self.local_waiting_messages) } } /// Buffering incoming messages until blocks with given hashes are imported. -pub(crate) struct UntilImported where +pub(crate) struct UntilImported +where Block: BlockT, I: Stream + Unpin, M: BlockUntilImported, @@ -152,7 +154,7 @@ pub(crate) struct UntilImported wh incoming_messages: Fuse, ready: VecDeque, /// Interval at which to check status of each awaited block. - check_pending: Pin> + Send + Sync>>, + check_pending: Pin> + Send>>, /// Mapping block hashes to their block number, the point in time it was /// first encountered (Instant) and a list of GRANDPA messages referencing /// the block hash. @@ -164,13 +166,18 @@ pub(crate) struct UntilImported wh metrics: Option, } -impl Unpin for UntilImported where +impl Unpin + for UntilImported +where Block: BlockT, I: Stream + Unpin, M: BlockUntilImported, -{} +{ +} -impl UntilImported where +impl + UntilImported +where Block: BlockT, BlockStatus: BlockStatusT, BlockSyncRequester: BlockSyncRequesterT, diff --git a/client/finality-grandpa/src/voting_rule.rs b/client/finality-grandpa/src/voting_rule.rs index 3ede7649a1387..a5515c1be23ed 100644 --- a/client/finality-grandpa/src/voting_rule.rs +++ b/client/finality-grandpa/src/voting_rule.rs @@ -34,10 +34,11 @@ use sp_runtime::traits::{Block as BlockT, Header, NumberFor, One, Zero}; /// A future returned by a `VotingRule` to restrict a given vote, if any restriction is necessary. pub type VotingRuleResult = - Pin::Hash, NumberFor)>> + Send + Sync>>; + Pin::Hash, NumberFor)>> + Send>>; /// A trait for custom voting rules in GRANDPA. -pub trait VotingRule: DynClone + Send + Sync where +pub trait VotingRule: DynClone + Send + Sync +where Block: BlockT, B: HeaderBackend, { diff --git a/frame/grandpa/Cargo.toml b/frame/grandpa/Cargo.toml index c6cfa96f7da1b..5c3cac8f82182 100644 --- a/frame/grandpa/Cargo.toml +++ b/frame/grandpa/Cargo.toml @@ -31,7 +31,7 @@ log = { version = "0.4.14", default-features = false } [dev-dependencies] frame-benchmarking = { version = "3.1.0", path = "../benchmarking" } -grandpa = { package = "finality-grandpa", version = "0.14.0", features = ["derive-codec"] } +grandpa = { package = "finality-grandpa", version = "0.14.1", features = ["derive-codec"] } sp-keyring = { version = "3.0.0", path = "../../primitives/keyring" } pallet-balances = { version = "3.0.0", path = "../balances" } pallet-offences = { version = "3.0.0", path = "../offences" } diff --git a/primitives/finality-grandpa/Cargo.toml b/primitives/finality-grandpa/Cargo.toml index 95aa65c930f78..ec9e89105d581 100644 --- a/primitives/finality-grandpa/Cargo.toml +++ b/primitives/finality-grandpa/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } -grandpa = { package = "finality-grandpa", version = "0.14.0", default-features = false, features = ["derive-codec"] } +grandpa = { package = "finality-grandpa", version = "0.14.1", default-features = false, features = ["derive-codec"] } log = { version = "0.4.8", optional = true } serde = { version = "1.0.101", optional = true, features = ["derive"] } sp-api = { version = "3.0.0", default-features = false, path = "../api" }