Simplify runtime api error handling (#8114)

* Ahh

* Work work work

* Fix all the compilation errors

* Fix test

* More fixes...
This commit is contained in:
Bastian Köcher
2021-02-15 12:55:40 +01:00
committed by GitHub
parent b5e692104c
commit 33f9becf41
48 changed files with 270 additions and 415 deletions
+1 -1
View File
@@ -99,7 +99,7 @@ pub fn executor() -> NativeExecutor<Executor> {
pub fn executor_call< pub fn executor_call<
R:Decode + Encode + PartialEq, R:Decode + Encode + PartialEq,
NC: FnOnce() -> std::result::Result<R, String> + std::panic::UnwindSafe NC: FnOnce() -> std::result::Result<R, Box<dyn std::error::Error + Send + Sync>> + std::panic::UnwindSafe
>( >(
t: &mut TestExternalities<BlakeTwo256>, t: &mut TestExternalities<BlakeTwo256>,
method: &str, method: &str,
+1 -1
View File
@@ -78,7 +78,7 @@ pub trait CallExecutor<B: BlockT> {
Result<NativeOrEncoded<R>, Self::Error> Result<NativeOrEncoded<R>, Self::Error>
) -> Result<NativeOrEncoded<R>, Self::Error>, ) -> Result<NativeOrEncoded<R>, Self::Error>,
R: Encode + Decode + PartialEq, R: Encode + Decode + PartialEq,
NC: FnOnce() -> result::Result<R, String> + UnwindSafe, NC: FnOnce() -> result::Result<R, sp_api::ApiError> + UnwindSafe,
>( >(
&self, &self,
initialize_block_fn: IB, initialize_block_fn: IB,
@@ -93,7 +93,7 @@ where
Block: BlockT + Unpin + 'static, Block: BlockT + Unpin + 'static,
Network: NetworkProvider, Network: NetworkProvider,
Client: ProvideRuntimeApi<Block> + Send + Sync + 'static + HeaderBackend<Block>, Client: ProvideRuntimeApi<Block> + Send + Sync + 'static + HeaderBackend<Block>,
<Client as ProvideRuntimeApi<Block>>::Api: AuthorityDiscoveryApi<Block, Error = sp_blockchain::Error>, <Client as ProvideRuntimeApi<Block>>::Api: AuthorityDiscoveryApi<Block>,
DhtEventStream: Stream<Item = DhtEvent> + Unpin, DhtEventStream: Stream<Item = DhtEvent> + Unpin,
{ {
new_worker_and_service_with_config( new_worker_and_service_with_config(
@@ -121,7 +121,7 @@ where
Block: BlockT + Unpin + 'static, Block: BlockT + Unpin + 'static,
Network: NetworkProvider, Network: NetworkProvider,
Client: ProvideRuntimeApi<Block> + Send + Sync + 'static + HeaderBackend<Block>, Client: ProvideRuntimeApi<Block> + Send + Sync + 'static + HeaderBackend<Block>,
<Client as ProvideRuntimeApi<Block>>::Api: AuthorityDiscoveryApi<Block, Error = sp_blockchain::Error>, <Client as ProvideRuntimeApi<Block>>::Api: AuthorityDiscoveryApi<Block>,
DhtEventStream: Stream<Item = DhtEvent> + Unpin, DhtEventStream: Stream<Item = DhtEvent> + Unpin,
{ {
let (to_worker, from_service) = mpsc::channel(0); let (to_worker, from_service) = mpsc::channel(0);
@@ -132,7 +132,7 @@ where
Network: NetworkProvider, Network: NetworkProvider,
Client: ProvideRuntimeApi<Block> + Send + Sync + 'static + HeaderBackend<Block>, Client: ProvideRuntimeApi<Block> + Send + Sync + 'static + HeaderBackend<Block>,
<Client as ProvideRuntimeApi<Block>>::Api: <Client as ProvideRuntimeApi<Block>>::Api:
AuthorityDiscoveryApi<Block, Error = sp_blockchain::Error>, AuthorityDiscoveryApi<Block>,
DhtEventStream: Stream<Item = DhtEvent> + Unpin, DhtEventStream: Stream<Item = DhtEvent> + Unpin,
{ {
/// Construct a [`Worker`]. /// Construct a [`Worker`].
@@ -332,7 +332,7 @@ where
.client .client
.runtime_api() .runtime_api()
.authorities(&id) .authorities(&id)
.map_err(Error::CallingRuntime)? .map_err(|e| Error::CallingRuntime(e.into()))?
.into_iter() .into_iter()
.filter(|id| !local_keys.contains(id.as_ref())) .filter(|id| !local_keys.contains(id.as_ref()))
.collect(); .collect();
@@ -546,7 +546,7 @@ where
let id = BlockId::hash(client.info().best_hash); let id = BlockId::hash(client.info().best_hash);
let authorities = client.runtime_api() let authorities = client.runtime_api()
.authorities(&id) .authorities(&id)
.map_err(Error::CallingRuntime)? .map_err(|e| Error::CallingRuntime(e.into()))?
.into_iter() .into_iter()
.map(std::convert::Into::into) .map(std::convert::Into::into)
.collect::<HashSet<_>>(); .collect::<HashSet<_>>();
@@ -100,8 +100,6 @@ pub(crate) struct RuntimeApi {
sp_api::mock_impl_runtime_apis! { sp_api::mock_impl_runtime_apis! {
impl AuthorityDiscoveryApi<Block> for RuntimeApi { impl AuthorityDiscoveryApi<Block> for RuntimeApi {
type Error = sp_blockchain::Error;
fn authorities(&self) -> Vec<AuthorityId> { fn authorities(&self) -> Vec<AuthorityId> {
self.authorities.clone() self.authorities.clone()
} }
@@ -99,7 +99,7 @@ impl<B, Block, C, A> ProposerFactory<A, B, C>
C: BlockBuilderProvider<B, Block, C> + HeaderBackend<Block> + ProvideRuntimeApi<Block> C: BlockBuilderProvider<B, Block, C> + HeaderBackend<Block> + ProvideRuntimeApi<Block>
+ Send + Sync + 'static, + Send + Sync + 'static,
C::Api: ApiExt<Block, StateBackend = backend::StateBackendFor<B, Block>> C::Api: ApiExt<Block, StateBackend = backend::StateBackendFor<B, Block>>
+ BlockBuilderApi<Block, Error = sp_blockchain::Error>, + BlockBuilderApi<Block>,
{ {
pub fn init_with_now( pub fn init_with_now(
&mut self, &mut self,
@@ -138,7 +138,7 @@ impl<A, B, Block, C> sp_consensus::Environment<Block> for
C: BlockBuilderProvider<B, Block, C> + HeaderBackend<Block> + ProvideRuntimeApi<Block> C: BlockBuilderProvider<B, Block, C> + HeaderBackend<Block> + ProvideRuntimeApi<Block>
+ Send + Sync + 'static, + Send + Sync + 'static,
C::Api: ApiExt<Block, StateBackend = backend::StateBackendFor<B, Block>> C::Api: ApiExt<Block, StateBackend = backend::StateBackendFor<B, Block>>
+ BlockBuilderApi<Block, Error = sp_blockchain::Error>, + BlockBuilderApi<Block>,
{ {
type CreateProposer = future::Ready<Result<Self::Proposer, Self::Error>>; type CreateProposer = future::Ready<Result<Self::Proposer, Self::Error>>;
type Proposer = Proposer<B, Block, C, A>; type Proposer = Proposer<B, Block, C, A>;
@@ -175,7 +175,7 @@ impl<A, B, Block, C> sp_consensus::Proposer<Block> for
C: BlockBuilderProvider<B, Block, C> + HeaderBackend<Block> + ProvideRuntimeApi<Block> C: BlockBuilderProvider<B, Block, C> + HeaderBackend<Block> + ProvideRuntimeApi<Block>
+ Send + Sync + 'static, + Send + Sync + 'static,
C::Api: ApiExt<Block, StateBackend = backend::StateBackendFor<B, Block>> C::Api: ApiExt<Block, StateBackend = backend::StateBackendFor<B, Block>>
+ BlockBuilderApi<Block, Error = sp_blockchain::Error>, + BlockBuilderApi<Block>,
{ {
type Transaction = backend::TransactionFor<B, Block>; type Transaction = backend::TransactionFor<B, Block>;
type Proposal = Pin<Box<dyn Future< type Proposal = Pin<Box<dyn Future<
@@ -221,7 +221,7 @@ impl<A, B, Block, C> Proposer<B, Block, C, A>
C: BlockBuilderProvider<B, Block, C> + HeaderBackend<Block> + ProvideRuntimeApi<Block> C: BlockBuilderProvider<B, Block, C> + HeaderBackend<Block> + ProvideRuntimeApi<Block>
+ Send + Sync + 'static, + Send + Sync + 'static,
C::Api: ApiExt<Block, StateBackend = backend::StateBackendFor<B, Block>> C::Api: ApiExt<Block, StateBackend = backend::StateBackendFor<B, Block>>
+ BlockBuilderApi<Block, Error = sp_blockchain::Error>, + BlockBuilderApi<Block>,
{ {
async fn propose_with( async fn propose_with(
self, self,
+8 -13
View File
@@ -35,8 +35,7 @@ use sp_runtime::{
use sp_blockchain::{ApplyExtrinsicFailed, Error}; use sp_blockchain::{ApplyExtrinsicFailed, Error};
use sp_core::ExecutionContext; use sp_core::ExecutionContext;
use sp_api::{ use sp_api::{
Core, ApiExt, ApiErrorFor, ApiRef, ProvideRuntimeApi, StorageChanges, StorageProof, Core, ApiExt, ApiRef, ProvideRuntimeApi, StorageChanges, StorageProof, TransactionOutcome,
TransactionOutcome,
}; };
use sp_consensus::RecordProof; use sp_consensus::RecordProof;
@@ -106,8 +105,7 @@ impl<'a, Block, A, B> BlockBuilder<'a, Block, A, B>
where where
Block: BlockT, Block: BlockT,
A: ProvideRuntimeApi<Block> + 'a, A: ProvideRuntimeApi<Block> + 'a,
A::Api: BlockBuilderApi<Block, Error = Error> + A::Api: BlockBuilderApi<Block> + ApiExt<Block, StateBackend = backend::StateBackendFor<B, Block>>,
ApiExt<Block, StateBackend = backend::StateBackendFor<B, Block>>,
B: backend::Backend<Block>, B: backend::Backend<Block>,
{ {
/// Create a new instance of builder based on the given `parent_hash` and `parent_number`. /// Create a new instance of builder based on the given `parent_hash` and `parent_number`.
@@ -122,7 +120,7 @@ where
record_proof: RecordProof, record_proof: RecordProof,
inherent_digests: DigestFor<Block>, inherent_digests: DigestFor<Block>,
backend: &'a B, backend: &'a B,
) -> Result<Self, ApiErrorFor<A, Block>> { ) -> Result<Self, Error> {
let header = <<Block as BlockT>::Header as HeaderT>::new( let header = <<Block as BlockT>::Header as HeaderT>::new(
parent_number + One::one(), parent_number + One::one(),
Default::default(), Default::default(),
@@ -155,7 +153,7 @@ where
/// Push onto the block's list of extrinsics. /// Push onto the block's list of extrinsics.
/// ///
/// This will ensure the extrinsic can be validly executed (by executing it). /// This will ensure the extrinsic can be validly executed (by executing it).
pub fn push(&mut self, xt: <Block as BlockT>::Extrinsic) -> Result<(), ApiErrorFor<A, Block>> { pub fn push(&mut self, xt: <Block as BlockT>::Extrinsic) -> Result<(), Error> {
let block_id = &self.block_id; let block_id = &self.block_id;
let extrinsics = &mut self.extrinsics; let extrinsics = &mut self.extrinsics;
@@ -174,7 +172,7 @@ where
Err(ApplyExtrinsicFailed::Validity(tx_validity).into()), Err(ApplyExtrinsicFailed::Validity(tx_validity).into()),
) )
}, },
Err(e) => TransactionOutcome::Rollback(Err(e)), Err(e) => TransactionOutcome::Rollback(Err(Error::from(e))),
} }
}) })
} }
@@ -184,10 +182,7 @@ where
/// Returns the build `Block`, the changes to the storage and an optional `StorageProof` /// Returns the build `Block`, the changes to the storage and an optional `StorageProof`
/// supplied by `self.api`, combined as [`BuiltBlock`]. /// supplied by `self.api`, combined as [`BuiltBlock`].
/// The storage proof will be `Some(_)` when proof recording was enabled. /// The storage proof will be `Some(_)` when proof recording was enabled.
pub fn build(mut self) -> Result< pub fn build(mut self) -> Result<BuiltBlock<Block, backend::StateBackendFor<B, Block>>, Error> {
BuiltBlock<Block, backend::StateBackendFor<B, Block>>,
ApiErrorFor<A, Block>
> {
let header = self.api.finalize_block_with_context( let header = self.api.finalize_block_with_context(
&self.block_id, ExecutionContext::BlockConstruction &self.block_id, ExecutionContext::BlockConstruction
)?; )?;
@@ -227,7 +222,7 @@ where
pub fn create_inherents( pub fn create_inherents(
&mut self, &mut self,
inherent_data: sp_inherents::InherentData, inherent_data: sp_inherents::InherentData,
) -> Result<Vec<Block::Extrinsic>, ApiErrorFor<A, Block>> { ) -> Result<Vec<Block::Extrinsic>, Error> {
let block_id = self.block_id; let block_id = self.block_id;
self.api.execute_in_transaction(move |api| { self.api.execute_in_transaction(move |api| {
// `create_inherents` should not change any state, to ensure this we always rollback // `create_inherents` should not change any state, to ensure this we always rollback
@@ -237,7 +232,7 @@ where
ExecutionContext::BlockConstruction, ExecutionContext::BlockConstruction,
inherent_data inherent_data
)) ))
}) }).map_err(|e| Error::Application(Box::new(e)))
} }
} }
+7 -7
View File
@@ -98,9 +98,9 @@ pub fn slot_duration<A, B, C>(client: &C) -> CResult<SlotDuration> where
A: Codec, A: Codec,
B: BlockT, B: BlockT,
C: AuxStore + ProvideRuntimeApi<B>, C: AuxStore + ProvideRuntimeApi<B>,
C::Api: AuraApi<B, A, Error = sp_blockchain::Error>, C::Api: AuraApi<B, A>,
{ {
SlotDuration::get_or_compute(client, |a, b| a.slot_duration(b)) SlotDuration::get_or_compute(client, |a, b| a.slot_duration(b).map_err(Into::into))
} }
/// Get slot author for given block along with authorities. /// Get slot author for given block along with authorities.
@@ -515,7 +515,7 @@ impl<C, P, CAW> AuraVerifier<C, P, CAW> where
inherent_data: InherentData, inherent_data: InherentData,
timestamp_now: u64, timestamp_now: u64,
) -> Result<(), Error<B>> where ) -> Result<(), Error<B>> where
C: ProvideRuntimeApi<B>, C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>, C: ProvideRuntimeApi<B>, C::Api: BlockBuilderApi<B>,
CAW: CanAuthorWith<B>, CAW: CanAuthorWith<B>,
{ {
const MAX_TIMESTAMP_DRIFT_SECS: u64 = 60; const MAX_TIMESTAMP_DRIFT_SECS: u64 = 60;
@@ -534,7 +534,7 @@ impl<C, P, CAW> AuraVerifier<C, P, CAW> where
&block_id, &block_id,
block, block,
inherent_data, inherent_data,
).map_err(Error::Client)?; ).map_err(|e| Error::Client(e.into()))?;
if !inherent_res.ok() { if !inherent_res.ok() {
inherent_res inherent_res
@@ -578,7 +578,7 @@ impl<B: BlockT, C, P, CAW> Verifier<B> for AuraVerifier<C, P, CAW> where
sc_client_api::backend::AuxStore + sc_client_api::backend::AuxStore +
ProvideCache<B> + ProvideCache<B> +
BlockOf, BlockOf,
C::Api: BlockBuilderApi<B> + AuraApi<B, AuthorityId<P>> + ApiExt<B, Error = sp_blockchain::Error>, C::Api: BlockBuilderApi<B> + AuraApi<B, AuthorityId<P>> + ApiExt<B>,
DigestItemFor<B>: CompatibleDigestItem<P>, DigestItemFor<B>: CompatibleDigestItem<P>,
P: Pair + Send + Sync + 'static, P: Pair + Send + Sync + 'static,
P::Public: Send + Sync + Hash + Eq + Clone + Decode + Encode + Debug + 'static, P::Public: Send + Sync + Hash + Eq + Clone + Decode + Encode + Debug + 'static,
@@ -624,7 +624,7 @@ impl<B: BlockT, C, P, CAW> Verifier<B> for AuraVerifier<C, P, CAW> where
// skip the inherents verification if the runtime API is old. // skip the inherents verification if the runtime API is old.
if self.client if self.client
.runtime_api() .runtime_api()
.has_api_with::<dyn BlockBuilderApi<B, Error = ()>, _>( .has_api_with::<dyn BlockBuilderApi<B>, _>(
&BlockId::Hash(parent_hash), &BlockId::Hash(parent_hash),
|v| v >= 2, |v| v >= 2,
) )
@@ -842,7 +842,7 @@ pub fn import_queue<B, I, C, P, S, CAW>(
can_author_with: CAW, can_author_with: CAW,
) -> Result<DefaultImportQueue<B, C>, sp_consensus::Error> where ) -> Result<DefaultImportQueue<B, C>, sp_consensus::Error> where
B: BlockT, B: BlockT,
C::Api: BlockBuilderApi<B> + AuraApi<B, AuthorityId<P>> + ApiExt<B, Error = sp_blockchain::Error>, C::Api: BlockBuilderApi<B> + AuraApi<B, AuthorityId<P>> + ApiExt<B>,
C: 'static + ProvideRuntimeApi<B> + BlockOf + ProvideCache<B> + Send + Sync + AuxStore + HeaderBackend<B>, C: 'static + ProvideRuntimeApi<B> + BlockOf + ProvideCache<B> + Send + Sync + AuxStore + HeaderBackend<B>,
I: BlockImport<B, Error=ConsensusError, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync + 'static, I: BlockImport<B, Error=ConsensusError, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync + 'static,
DigestItemFor<B>: CompatibleDigestItem<P>, DigestItemFor<B>: CompatibleDigestItem<P>,
+12 -11
View File
@@ -273,6 +273,8 @@ pub enum Error<B: BlockT> {
CheckInherents(String), CheckInherents(String),
/// Client error /// Client error
Client(sp_blockchain::Error), Client(sp_blockchain::Error),
/// Runtime Api error.
RuntimeApi(sp_api::ApiError),
/// Runtime error /// Runtime error
Runtime(sp_inherents::Error), Runtime(sp_inherents::Error),
/// Fork tree error /// Fork tree error
@@ -310,14 +312,14 @@ impl Config {
/// Either fetch the slot duration from disk or compute it from the genesis /// Either fetch the slot duration from disk or compute it from the genesis
/// state. /// state.
pub fn get_or_compute<B: BlockT, C>(client: &C) -> ClientResult<Self> where pub fn get_or_compute<B: BlockT, C>(client: &C) -> ClientResult<Self> where
C: AuxStore + ProvideRuntimeApi<B>, C::Api: BabeApi<B, Error = sp_blockchain::Error>, C: AuxStore + ProvideRuntimeApi<B>, C::Api: BabeApi<B>,
{ {
trace!(target: "babe", "Getting slot duration"); trace!(target: "babe", "Getting slot duration");
match sc_consensus_slots::SlotDuration::get_or_compute(client, |a, b| { match sc_consensus_slots::SlotDuration::get_or_compute(client, |a, b| {
let has_api_v1 = a.has_api_with::<dyn BabeApi<B, Error = sp_blockchain::Error>, _>( let has_api_v1 = a.has_api_with::<dyn BabeApi<B>, _>(
&b, |v| v == 1, &b, |v| v == 1,
)?; )?;
let has_api_v2 = a.has_api_with::<dyn BabeApi<B, Error = sp_blockchain::Error>, _>( let has_api_v2 = a.has_api_with::<dyn BabeApi<B>, _>(
&b, |v| v == 2, &b, |v| v == 2,
)?; )?;
@@ -326,7 +328,7 @@ impl Config {
Ok(a.configuration_before_version_2(b)?.into()) Ok(a.configuration_before_version_2(b)?.into())
} }
} else if has_api_v2 { } else if has_api_v2 {
a.configuration(b) a.configuration(b).map_err(Into::into)
} else { } else {
Err(sp_blockchain::Error::VersionInvalid( Err(sp_blockchain::Error::VersionInvalid(
"Unsupported or invalid BabeApi version".to_string() "Unsupported or invalid BabeApi version".to_string()
@@ -846,8 +848,7 @@ impl<Block, Client, SelectChain, CAW> BabeVerifier<Block, Client, SelectChain, C
where where
Block: BlockT, Block: BlockT,
Client: AuxStore + HeaderBackend<Block> + HeaderMetadata<Block> + ProvideRuntimeApi<Block>, Client: AuxStore + HeaderBackend<Block> + HeaderMetadata<Block> + ProvideRuntimeApi<Block>,
Client::Api: BlockBuilderApi<Block, Error = sp_blockchain::Error> Client::Api: BlockBuilderApi<Block> + BabeApi<Block>,
+ BabeApi<Block, Error = sp_blockchain::Error>,
SelectChain: sp_consensus::SelectChain<Block>, SelectChain: sp_consensus::SelectChain<Block>,
CAW: CanAuthorWith<Block>, CAW: CanAuthorWith<Block>,
{ {
@@ -871,7 +872,7 @@ where
&block_id, &block_id,
block, block,
inherent_data, inherent_data,
).map_err(Error::Client)?; ).map_err(Error::RuntimeApi)?;
if !inherent_res.ok() { if !inherent_res.ok() {
inherent_res inherent_res
@@ -934,7 +935,7 @@ where
self.client self.client
.runtime_api() .runtime_api()
.generate_key_ownership_proof(block_id, slot, equivocation_proof.offender.clone()) .generate_key_ownership_proof(block_id, slot, equivocation_proof.offender.clone())
.map_err(Error::Client) .map_err(Error::RuntimeApi)
}; };
let parent_id = BlockId::Hash(*header.parent_hash()); let parent_id = BlockId::Hash(*header.parent_hash());
@@ -957,7 +958,7 @@ where
equivocation_proof, equivocation_proof,
key_owner_proof, key_owner_proof,
) )
.map_err(Error::Client)?; .map_err(Error::RuntimeApi)?;
info!(target: "babe", "Submitted equivocation report for author {:?}", author); info!(target: "babe", "Submitted equivocation report for author {:?}", author);
@@ -971,7 +972,7 @@ where
Block: BlockT, Block: BlockT,
Client: HeaderMetadata<Block, Error = sp_blockchain::Error> + HeaderBackend<Block> + ProvideRuntimeApi<Block> Client: HeaderMetadata<Block, Error = sp_blockchain::Error> + HeaderBackend<Block> + ProvideRuntimeApi<Block>
+ Send + Sync + AuxStore + ProvideCache<Block>, + Send + Sync + AuxStore + ProvideCache<Block>,
Client::Api: BlockBuilderApi<Block, Error = sp_blockchain::Error> + BabeApi<Block, Error = sp_blockchain::Error>, Client::Api: BlockBuilderApi<Block> + BabeApi<Block>,
SelectChain: sp_consensus::SelectChain<Block>, SelectChain: sp_consensus::SelectChain<Block>,
CAW: CanAuthorWith<Block> + Send + Sync, CAW: CanAuthorWith<Block> + Send + Sync,
{ {
@@ -1498,7 +1499,7 @@ pub fn import_queue<Block: BlockT, Client, SelectChain, Inner, CAW>(
+ Send + Sync + 'static, + Send + Sync + 'static,
Client: ProvideRuntimeApi<Block> + ProvideCache<Block> + Send + Sync + AuxStore + 'static, Client: ProvideRuntimeApi<Block> + ProvideCache<Block> + Send + Sync + AuxStore + 'static,
Client: HeaderBackend<Block> + HeaderMetadata<Block, Error = sp_blockchain::Error>, Client: HeaderBackend<Block> + HeaderMetadata<Block, Error = sp_blockchain::Error>,
Client::Api: BlockBuilderApi<Block> + BabeApi<Block> + ApiExt<Block, Error = sp_blockchain::Error>, Client::Api: BlockBuilderApi<Block> + BabeApi<Block> + ApiExt<Block>,
SelectChain: sp_consensus::SelectChain<Block> + 'static, SelectChain: sp_consensus::SelectChain<Block> + 'static,
CAW: CanAuthorWith<Block> + Send + Sync + 'static, CAW: CanAuthorWith<Block> + Send + Sync + 'static,
{ {
@@ -73,7 +73,7 @@ impl<B, C> BabeConsensusDataProvider<B, C>
where where
B: BlockT, B: BlockT,
C: AuxStore + HeaderBackend<B> + ProvideRuntimeApi<B> + HeaderMetadata<B, Error = sp_blockchain::Error>, C: AuxStore + HeaderBackend<B> + ProvideRuntimeApi<B> + HeaderMetadata<B, Error = sp_blockchain::Error>,
C::Api: BabeApi<B, Error = sp_blockchain::Error>, C::Api: BabeApi<B>,
{ {
pub fn new( pub fn new(
client: Arc<C>, client: Arc<C>,
@@ -131,7 +131,7 @@ impl<B, C> ConsensusDataProvider<B> for BabeConsensusDataProvider<B, C>
where where
B: BlockT, B: BlockT,
C: AuxStore + HeaderBackend<B> + HeaderMetadata<B, Error = sp_blockchain::Error> + ProvideRuntimeApi<B>, C: AuxStore + HeaderBackend<B> + HeaderMetadata<B, Error = sp_blockchain::Error> + ProvideRuntimeApi<B>,
C::Api: BabeApi<B, Error = sp_blockchain::Error>, C::Api: BabeApi<B>,
{ {
type Transaction = TransactionFor<C, B>; type Transaction = TransactionFor<C, B>;
@@ -259,7 +259,7 @@ impl SlotTimestampProvider {
where where
B: BlockT, B: BlockT,
C: AuxStore + HeaderBackend<B> + ProvideRuntimeApi<B>, C: AuxStore + HeaderBackend<B> + ProvideRuntimeApi<B>,
C::Api: BabeApi<B, Error = sp_blockchain::Error>, C::Api: BabeApi<B>,
{ {
let slot_duration = Config::get_or_compute(&*client)?.slot_duration; let slot_duration = Config::get_or_compute(&*client)?.slot_duration;
let info = client.info(); let info = client.info();
+3 -3
View File
@@ -232,7 +232,7 @@ impl<B, I, C, S, Algorithm, CAW> PowBlockImport<B, I, C, S, Algorithm, CAW> wher
I: BlockImport<B, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync, I: BlockImport<B, Transaction = sp_api::TransactionFor<C, B>> + Send + Sync,
I::Error: Into<ConsensusError>, I::Error: Into<ConsensusError>,
C: ProvideRuntimeApi<B> + Send + Sync + HeaderBackend<B> + AuxStore + ProvideCache<B> + BlockOf, C: ProvideRuntimeApi<B> + Send + Sync + HeaderBackend<B> + AuxStore + ProvideCache<B> + BlockOf,
C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>, C::Api: BlockBuilderApi<B>,
Algorithm: PowAlgorithm<B>, Algorithm: PowAlgorithm<B>,
CAW: CanAuthorWith<B>, CAW: CanAuthorWith<B>,
{ {
@@ -284,7 +284,7 @@ impl<B, I, C, S, Algorithm, CAW> PowBlockImport<B, I, C, S, Algorithm, CAW> wher
&block_id, &block_id,
block, block,
inherent_data, inherent_data,
).map_err(Error::Client)?; ).map_err(|e| Error::Client(e.into()))?;
if !inherent_res.ok() { if !inherent_res.ok() {
inherent_res inherent_res
@@ -314,7 +314,7 @@ impl<B, I, C, S, Algorithm, CAW> BlockImport<B> for PowBlockImport<B, I, C, S, A
I::Error: Into<ConsensusError>, I::Error: Into<ConsensusError>,
S: SelectChain<B>, S: SelectChain<B>,
C: ProvideRuntimeApi<B> + Send + Sync + HeaderBackend<B> + AuxStore + ProvideCache<B> + BlockOf, C: ProvideRuntimeApi<B> + Send + Sync + HeaderBackend<B> + AuxStore + ProvideCache<B> + BlockOf,
C::Api: BlockBuilderApi<B, Error = sp_blockchain::Error>, C::Api: BlockBuilderApi<B>,
Algorithm: PowAlgorithm<B>, Algorithm: PowAlgorithm<B>,
Algorithm::Difficulty: 'static, Algorithm::Difficulty: 'static,
CAW: CanAuthorWith<B>, CAW: CanAuthorWith<B>,
@@ -37,8 +37,8 @@ pub enum Error {
#[error(transparent)] #[error(transparent)]
Wasmi(#[from] wasmi::Error), Wasmi(#[from] wasmi::Error),
#[error("API Error: {0}")] #[error("Error calling api function: {0}")]
ApiError(String), ApiError(Box<dyn std::error::Error + Send + Sync>),
#[error("Method not found: '{0}'")] #[error("Method not found: '{0}'")]
MethodNotFound(String), MethodNotFound(String),
@@ -456,7 +456,7 @@ impl<D: NativeExecutionDispatch + 'static> CodeExecutor for NativeExecutor<D> {
fn call< fn call<
R: Decode + Encode + PartialEq, R: Decode + Encode + PartialEq,
NC: FnOnce() -> result::Result<R, String> + UnwindSafe, NC: FnOnce() -> result::Result<R, Box<dyn std::error::Error + Send + Sync>> + UnwindSafe,
>( >(
&self, &self,
ext: &mut dyn Externalities, ext: &mut dyn Externalities,
@@ -514,7 +514,7 @@ impl<D: NativeExecutionDispatch + 'static> CodeExecutor for NativeExecutor<D> {
let res = with_externalities_safe(&mut **ext, move || (call)()) let res = with_externalities_safe(&mut **ext, move || (call)())
.and_then(|r| r .and_then(|r| r
.map(NativeOrEncoded::Native) .map(NativeOrEncoded::Native)
.map_err(|s| Error::ApiError(s)) .map_err(Error::ApiError)
); );
Ok(res) Ok(res)
@@ -414,7 +414,7 @@ mod tests {
authoring_version: 1, authoring_version: 1,
spec_version: 1, spec_version: 1,
impl_version: 1, impl_version: 1,
apis: sp_api::create_apis_vec!([(Core::<Block, Error = ()>::ID, 1)]), apis: sp_api::create_apis_vec!([(Core::<Block>::ID, 1)]),
}; };
let version = decode_version(&old_runtime_version.encode()).unwrap(); let version = decode_version(&old_runtime_version.encode()).unwrap();
@@ -429,7 +429,7 @@ mod tests {
authoring_version: 1, authoring_version: 1,
spec_version: 1, spec_version: 1,
impl_version: 1, impl_version: 1,
apis: sp_api::create_apis_vec!([(Core::<Block, Error = ()>::ID, 3)]), apis: sp_api::create_apis_vec!([(Core::<Block>::ID, 3)]),
}; };
decode_version(&old_runtime_version.encode()).unwrap_err(); decode_version(&old_runtime_version.encode()).unwrap_err();
@@ -443,7 +443,7 @@ mod tests {
authoring_version: 1, authoring_version: 1,
spec_version: 1, spec_version: 1,
impl_version: 1, impl_version: 1,
apis: sp_api::create_apis_vec!([(Core::<Block, Error = ()>::ID, 3)]), apis: sp_api::create_apis_vec!([(Core::<Block>::ID, 3)]),
transaction_version: 3, transaction_version: 3,
}; };
@@ -59,4 +59,3 @@ sp-state-machine = { version = "0.9.0", path = "../../primitives/state-machine"
sp-tracing = { version = "3.0.0", path = "../../primitives/tracing" } sp-tracing = { version = "3.0.0", path = "../../primitives/tracing" }
tokio = { version = "0.2", features = ["rt-core"] } tokio = { version = "0.2", features = ["rt-core"] }
tempfile = "3.1.0" tempfile = "3.1.0"
sp-api = { version = "3.0.0", path = "../../primitives/api" }
@@ -480,7 +480,7 @@ where
Block: BlockT, Block: BlockT,
BE: Backend<Block>, BE: Backend<Block>,
C: crate::ClientForGrandpa<Block, BE>, C: crate::ClientForGrandpa<Block, BE>,
C::Api: GrandpaApi<Block, Error = sp_blockchain::Error>, C::Api: GrandpaApi<Block>,
N: NetworkT<Block>, N: NetworkT<Block>,
SC: SelectChain<Block> + 'static, SC: SelectChain<Block> + 'static,
{ {
@@ -549,7 +549,7 @@ where
authority_set.set_id, authority_set.set_id,
equivocation.offender().clone(), equivocation.offender().clone(),
) )
.map_err(Error::Client)? .map_err(Error::RuntimeApi)?
{ {
Some(proof) => proof, Some(proof) => proof,
None => { None => {
@@ -571,7 +571,7 @@ where
equivocation_proof, equivocation_proof,
key_owner_proof, key_owner_proof,
) )
.map_err(Error::Client)?; .map_err(Error::RuntimeApi)?;
Ok(()) Ok(())
} }
@@ -726,7 +726,7 @@ where
Block: 'static, Block: 'static,
B: Backend<Block>, B: Backend<Block>,
C: crate::ClientForGrandpa<Block, B> + 'static, C: crate::ClientForGrandpa<Block, B> + 'static,
C::Api: GrandpaApi<Block, Error = sp_blockchain::Error>, C::Api: GrandpaApi<Block>,
N: NetworkT<Block> + 'static + Send + Sync, N: NetworkT<Block> + 'static + Send + Sync,
SC: SelectChain<Block> + 'static, SC: SelectChain<Block> + 'static,
VR: VotingRule<Block, C>, VR: VotingRule<Block, C>,
@@ -663,6 +663,7 @@ where
Error::Safety(error) => ConsensusError::ClientImport(error), Error::Safety(error) => ConsensusError::ClientImport(error),
Error::Signing(error) => ConsensusError::ClientImport(error), Error::Signing(error) => ConsensusError::ClientImport(error),
Error::Timer(error) => ConsensusError::ClientImport(error.to_string()), Error::Timer(error) => ConsensusError::ClientImport(error.to_string()),
Error::RuntimeApi(error) => ConsensusError::ClientImport(error.to_string()),
}); });
}, },
Ok(_) => { Ok(_) => {
+5 -3
View File
@@ -295,6 +295,8 @@ pub enum Error {
Safety(String), Safety(String),
/// A timer failed to fire. /// A timer failed to fire.
Timer(io::Error), Timer(io::Error),
/// A runtime api request failed.
RuntimeApi(sp_api::ApiError),
} }
impl From<GrandpaError> for Error { impl From<GrandpaError> for Error {
@@ -698,7 +700,7 @@ where
NumberFor<Block>: BlockNumberOps, NumberFor<Block>: BlockNumberOps,
DigestFor<Block>: Encode, DigestFor<Block>: Encode,
C: ClientForGrandpa<Block, BE> + 'static, C: ClientForGrandpa<Block, BE> + 'static,
C::Api: GrandpaApi<Block, Error = sp_blockchain::Error>, C::Api: GrandpaApi<Block>,
{ {
let GrandpaParams { let GrandpaParams {
mut config, mut config,
@@ -824,7 +826,7 @@ where
Block: BlockT, Block: BlockT,
B: Backend<Block> + 'static, B: Backend<Block> + 'static,
C: ClientForGrandpa<Block, B> + 'static, C: ClientForGrandpa<Block, B> + 'static,
C::Api: GrandpaApi<Block, Error = sp_blockchain::Error>, C::Api: GrandpaApi<Block>,
N: NetworkT<Block> + Sync, N: NetworkT<Block> + Sync,
NumberFor<Block>: BlockNumberOps, NumberFor<Block>: BlockNumberOps,
SC: SelectChain<Block> + 'static, SC: SelectChain<Block> + 'static,
@@ -1042,7 +1044,7 @@ where
NumberFor<Block>: BlockNumberOps, NumberFor<Block>: BlockNumberOps,
SC: SelectChain<Block> + 'static, SC: SelectChain<Block> + 'static,
C: ClientForGrandpa<Block, B> + 'static, C: ClientForGrandpa<Block, B> + 'static,
C::Api: GrandpaApi<Block, Error = sp_blockchain::Error>, C::Api: GrandpaApi<Block>,
VR: VotingRule<Block, C> + Clone + 'static, VR: VotingRule<Block, C> + Clone + 'static,
{ {
type Output = Result<(), Error>; type Output = Result<(), Error>;
@@ -174,8 +174,6 @@ impl ProvideRuntimeApi<Block> for TestApi {
sp_api::mock_impl_runtime_apis! { sp_api::mock_impl_runtime_apis! {
impl GrandpaApi<Block> for RuntimeApi { impl GrandpaApi<Block> for RuntimeApi {
type Error = sp_blockchain::Error;
fn grandpa_authorities(&self) -> AuthorityList { fn grandpa_authorities(&self) -> AuthorityList {
self.inner.genesis_authorities.clone() self.inner.genesis_authorities.clone()
} }
+1 -1
View File
@@ -104,7 +104,7 @@ impl<Block, B, Local> CallExecutor<Block> for
Result<NativeOrEncoded<R>, Self::Error> Result<NativeOrEncoded<R>, Self::Error>
) -> Result<NativeOrEncoded<R>, Self::Error>, ) -> Result<NativeOrEncoded<R>, Self::Error>,
R: Encode + Decode + PartialEq, R: Encode + Decode + PartialEq,
NC: FnOnce() -> result::Result<R, String> + UnwindSafe, NC: FnOnce() -> result::Result<R, sp_api::ApiError> + UnwindSafe,
>( >(
&self, &self,
initialize_block_fn: IB, initialize_block_fn: IB,
+2 -2
View File
@@ -132,10 +132,10 @@ impl<Client, Storage, Block> OffchainWorkers<
) -> impl Future<Output = ()> { ) -> impl Future<Output = ()> {
let runtime = self.client.runtime_api(); let runtime = self.client.runtime_api();
let at = BlockId::hash(header.hash()); let at = BlockId::hash(header.hash());
let has_api_v1 = runtime.has_api_with::<dyn OffchainWorkerApi<Block, Error = ()>, _>( let has_api_v1 = runtime.has_api_with::<dyn OffchainWorkerApi<Block>, _>(
&at, |v| v == 1 &at, |v| v == 1
); );
let has_api_v2 = runtime.has_api_with::<dyn OffchainWorkerApi<Block, Error = ()>, _>( let has_api_v2 = runtime.has_api_with::<dyn OffchainWorkerApi<Block>, _>(
&at, |v| v == 2 &at, |v| v == 2
); );
let version = match (has_api_v1, has_api_v2) { let version = match (has_api_v1, has_api_v2) {
+3 -6
View File
@@ -24,12 +24,9 @@ mod tests;
use std::{sync::Arc, convert::TryInto}; use std::{sync::Arc, convert::TryInto};
use log::warn; use log::warn;
use sp_blockchain::{Error as ClientError, HeaderBackend}; use sp_blockchain::HeaderBackend;
use rpc::futures::{ use rpc::futures::{Sink, Future, future::result};
Sink, Future,
future::result,
};
use futures::{StreamExt as _, compat::Compat}; use futures::{StreamExt as _, compat::Compat};
use futures::future::{ready, FutureExt, TryFutureExt}; use futures::future::{ready, FutureExt, TryFutureExt};
use sc_rpc_api::DenyUnsafe; use sc_rpc_api::DenyUnsafe;
@@ -93,7 +90,7 @@ impl<P, Client> AuthorApi<TxHash<P>, BlockHash<P>> for Author<P, Client>
where where
P: TransactionPool + Sync + Send + 'static, P: TransactionPool + Sync + Send + 'static,
Client: HeaderBackend<P::Block> + ProvideRuntimeApi<P::Block> + Send + Sync + 'static, Client: HeaderBackend<P::Block> + ProvideRuntimeApi<P::Block> + Send + Sync + 'static,
Client::Api: SessionKeys<P::Block, Error = ClientError>, Client::Api: SessionKeys<P::Block>,
{ {
type Metadata = crate::Metadata; type Metadata = crate::Metadata;
+2 -3
View File
@@ -178,9 +178,8 @@ pub fn new_full<BE, Block: BlockT, Client>(
BE: Backend<Block> + 'static, BE: Backend<Block> + 'static,
Client: ExecutorProvider<Block> + StorageProvider<Block, BE> + ProofProvider<Block> + HeaderBackend<Block> Client: ExecutorProvider<Block> + StorageProvider<Block, BE> + ProofProvider<Block> + HeaderBackend<Block>
+ HeaderMetadata<Block, Error = sp_blockchain::Error> + BlockchainEvents<Block> + HeaderMetadata<Block, Error = sp_blockchain::Error> + BlockchainEvents<Block>
+ CallApiAt<Block, Error = sp_blockchain::Error> + CallApiAt<Block> + ProvideRuntimeApi<Block> + Send + Sync + 'static,
+ ProvideRuntimeApi<Block> + Send + Sync + 'static, Client::Api: Metadata<Block>,
Client::Api: Metadata<Block, Error = sp_blockchain::Error>,
{ {
let child_backend = Box::new( let child_backend = Box::new(
self::state_full::FullState::new(client.clone(), subscriptions.clone()) self::state_full::FullState::new(client.clone(), subscriptions.clone())
+16 -10
View File
@@ -223,9 +223,9 @@ impl<BE, Block, Client> StateBackend<Block, Client> for FullState<BE, Block, Cli
BE: Backend<Block> + 'static, BE: Backend<Block> + 'static,
Client: ExecutorProvider<Block> + StorageProvider<Block, BE> + ProofProvider<Block> + HeaderBackend<Block> Client: ExecutorProvider<Block> + StorageProvider<Block, BE> + ProofProvider<Block> + HeaderBackend<Block>
+ HeaderMetadata<Block, Error = sp_blockchain::Error> + BlockchainEvents<Block> + HeaderMetadata<Block, Error = sp_blockchain::Error> + BlockchainEvents<Block>
+ CallApiAt<Block, Error = sp_blockchain::Error> + ProvideRuntimeApi<Block> + CallApiAt<Block> + ProvideRuntimeApi<Block>
+ Send + Sync + 'static, + Send + Sync + 'static,
Client::Api: Metadata<Block, Error = sp_blockchain::Error>, Client::Api: Metadata<Block>,
{ {
fn call( fn call(
&self, &self,
@@ -344,17 +344,23 @@ impl<BE, Block, Client> StateBackend<Block, Client> for FullState<BE, Block, Cli
fn metadata(&self, block: Option<Block::Hash>) -> FutureResult<Bytes> { fn metadata(&self, block: Option<Block::Hash>) -> FutureResult<Bytes> {
Box::new(result( Box::new(result(
self.block_or_best(block) self.block_or_best(block)
.map_err(client_err)
.and_then(|block| .and_then(|block|
self.client.runtime_api().metadata(&BlockId::Hash(block)).map(Into::into) self.client.runtime_api().metadata(&BlockId::Hash(block))
) .map(Into::into)
.map_err(client_err))) .map_err(|e| Error::Client(Box::new(e))))
))
} }
fn runtime_version(&self, block: Option<Block::Hash>) -> FutureResult<RuntimeVersion> { fn runtime_version(&self, block: Option<Block::Hash>) -> FutureResult<RuntimeVersion> {
Box::new(result( Box::new(result(
self.block_or_best(block) self.block_or_best(block)
.and_then(|block| self.client.runtime_version_at(&BlockId::Hash(block))) .map_err(client_err)
.map_err(client_err))) .and_then(|block|
self.client.runtime_version_at(&BlockId::Hash(block))
.map_err(|e| Error::Client(Box::new(e)))
)
))
} }
fn query_storage( fn query_storage(
@@ -432,7 +438,7 @@ impl<BE, Block, Client> StateBackend<Block, Client> for FullState<BE, Block, Cli
let info = client.info(); let info = client.info();
let version = client let version = client
.runtime_version_at(&BlockId::hash(info.best_hash)) .runtime_version_at(&BlockId::hash(info.best_hash))
.map_err(client_err) .map_err(|e| Error::Client(Box::new(e)))
.map_err(Into::into); .map_err(Into::into);
if previous_version != version { if previous_version != version {
previous_version = version.clone(); previous_version = version.clone();
@@ -528,9 +534,9 @@ impl<BE, Block, Client> ChildStateBackend<Block, Client> for FullState<BE, Block
BE: Backend<Block> + 'static, BE: Backend<Block> + 'static,
Client: ExecutorProvider<Block> + StorageProvider<Block, BE> + HeaderBackend<Block> Client: ExecutorProvider<Block> + StorageProvider<Block, BE> + HeaderBackend<Block>
+ HeaderMetadata<Block, Error = sp_blockchain::Error> + BlockchainEvents<Block> + HeaderMetadata<Block, Error = sp_blockchain::Error> + BlockchainEvents<Block>
+ CallApiAt<Block, Error = sp_blockchain::Error> + ProvideRuntimeApi<Block> + CallApiAt<Block> + ProvideRuntimeApi<Block>
+ Send + Sync + 'static, + Send + Sync + 'static,
Client::Api: Metadata<Block, Error = sp_blockchain::Error>, Client::Api: Metadata<Block>,
{ {
fn storage_keys( fn storage_keys(
&self, &self,
+4 -5
View File
@@ -542,14 +542,13 @@ pub fn spawn_tasks<TBl, TBackend, TExPool, TRpc, TCl>(
TCl: ProvideRuntimeApi<TBl> + HeaderMetadata<TBl, Error=sp_blockchain::Error> + Chain<TBl> + TCl: ProvideRuntimeApi<TBl> + HeaderMetadata<TBl, Error=sp_blockchain::Error> + Chain<TBl> +
BlockBackend<TBl> + BlockIdTo<TBl, Error=sp_blockchain::Error> + ProofProvider<TBl> + BlockBackend<TBl> + BlockIdTo<TBl, Error=sp_blockchain::Error> + ProofProvider<TBl> +
HeaderBackend<TBl> + BlockchainEvents<TBl> + ExecutorProvider<TBl> + UsageProvider<TBl> + HeaderBackend<TBl> + BlockchainEvents<TBl> + ExecutorProvider<TBl> + UsageProvider<TBl> +
StorageProvider<TBl, TBackend> + CallApiAt<TBl, Error=sp_blockchain::Error> + StorageProvider<TBl, TBackend> + CallApiAt<TBl> +
Send + 'static, Send + 'static,
<TCl as ProvideRuntimeApi<TBl>>::Api: <TCl as ProvideRuntimeApi<TBl>>::Api:
sp_api::Metadata<TBl> + sp_api::Metadata<TBl> +
sc_offchain::OffchainWorkerApi<TBl> + sc_offchain::OffchainWorkerApi<TBl> +
sp_transaction_pool::runtime_api::TaggedTransactionQueue<TBl> + sp_transaction_pool::runtime_api::TaggedTransactionQueue<TBl> +
sp_session::SessionKeys<TBl> + sp_session::SessionKeys<TBl> +
sp_api::ApiErrorExt<Error = sp_blockchain::Error> +
sp_api::ApiExt<TBl, StateBackend = TBackend::State>, sp_api::ApiExt<TBl, StateBackend = TBackend::State>,
TBl: BlockT, TBl: BlockT,
TBackend: 'static + sc_client_api::backend::Backend<TBl> + Send, TBackend: 'static + sc_client_api::backend::Backend<TBl> + Send,
@@ -578,7 +577,7 @@ pub fn spawn_tasks<TBl, TBackend, TExPool, TRpc, TCl>(
client.clone(), client.clone(),
&BlockId::Hash(chain_info.best_hash), &BlockId::Hash(chain_info.best_hash),
config.dev_key_seed.clone().map(|s| vec![s]).unwrap_or_default(), config.dev_key_seed.clone().map(|s| vec![s]).unwrap_or_default(),
)?; ).map_err(|e| Error::Application(Box::new(e)))?;
let telemetry_connection_notifier = init_telemetry( let telemetry_connection_notifier = init_telemetry(
&mut config, &mut config,
@@ -729,14 +728,14 @@ fn gen_handler<TBl, TBackend, TExPool, TRpc, TCl>(
TBl: BlockT, TBl: BlockT,
TCl: ProvideRuntimeApi<TBl> + BlockchainEvents<TBl> + HeaderBackend<TBl> + TCl: ProvideRuntimeApi<TBl> + BlockchainEvents<TBl> + HeaderBackend<TBl> +
HeaderMetadata<TBl, Error=sp_blockchain::Error> + ExecutorProvider<TBl> + HeaderMetadata<TBl, Error=sp_blockchain::Error> + ExecutorProvider<TBl> +
CallApiAt<TBl, Error=sp_blockchain::Error> + ProofProvider<TBl> + CallApiAt<TBl> + ProofProvider<TBl> +
StorageProvider<TBl, TBackend> + BlockBackend<TBl> + Send + Sync + 'static, StorageProvider<TBl, TBackend> + BlockBackend<TBl> + Send + Sync + 'static,
TExPool: MaintainedTransactionPool<Block=TBl, Hash = <TBl as BlockT>::Hash> + 'static, TExPool: MaintainedTransactionPool<Block=TBl, Hash = <TBl as BlockT>::Hash> + 'static,
TBackend: sc_client_api::backend::Backend<TBl> + 'static, TBackend: sc_client_api::backend::Backend<TBl> + 'static,
TRpc: sc_rpc::RpcExtension<sc_rpc::Metadata>, TRpc: sc_rpc::RpcExtension<sc_rpc::Metadata>,
<TCl as ProvideRuntimeApi<TBl>>::Api: <TCl as ProvideRuntimeApi<TBl>>::Api:
sp_session::SessionKeys<TBl> + sp_session::SessionKeys<TBl> +
sp_api::Metadata<TBl, Error = sp_blockchain::Error>, sp_api::Metadata<TBl>,
{ {
use sc_rpc::{chain, state, author, system, offchain}; use sc_rpc::{chain, state, author, system, offchain};
@@ -161,7 +161,7 @@ where
Result<NativeOrEncoded<R>, Self::Error> Result<NativeOrEncoded<R>, Self::Error>
) -> Result<NativeOrEncoded<R>, Self::Error>, ) -> Result<NativeOrEncoded<R>, Self::Error>,
R: Encode + Decode + PartialEq, R: Encode + Decode + PartialEq,
NC: FnOnce() -> result::Result<R, String> + UnwindSafe, NC: FnOnce() -> result::Result<R, sp_api::ApiError> + UnwindSafe,
>( >(
&self, &self,
initialize_block_fn: IB, initialize_block_fn: IB,
@@ -226,7 +226,10 @@ where
); );
// TODO: https://github.com/paritytech/substrate/issues/4455 // TODO: https://github.com/paritytech/substrate/issues/4455
// .with_storage_transaction_cache(storage_transaction_cache.as_mut().map(|c| &mut **c)) // .with_storage_transaction_cache(storage_transaction_cache.as_mut().map(|c| &mut **c))
state_machine.execute_using_consensus_failure_handler(execution_manager, native_call) state_machine.execute_using_consensus_failure_handler(
execution_manager,
native_call.map(|n| || (n)().map_err(|e| Box::new(e) as Box<_>)),
)
}, },
None => { None => {
let state_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&state); let state_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&state);
@@ -245,7 +248,10 @@ where
&runtime_code, &runtime_code,
self.spawn_handle.clone(), self.spawn_handle.clone(),
).with_storage_transaction_cache(storage_transaction_cache.as_mut().map(|c| &mut **c)); ).with_storage_transaction_cache(storage_transaction_cache.as_mut().map(|c| &mut **c));
state_machine.execute_using_consensus_failure_handler(execution_manager, native_call) state_machine.execute_using_consensus_failure_handler(
execution_manager,
native_call.map(|n| || (n)().map_err(|e| Box::new(e) as Box<_>)),
)
} }
}.map_err(Into::into) }.map_err(Into::into)
} }
+20 -16
View File
@@ -604,7 +604,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
new_cache: HashMap<CacheKeyId, Vec<u8>>, new_cache: HashMap<CacheKeyId, Vec<u8>>,
) -> sp_blockchain::Result<ImportResult> where ) -> sp_blockchain::Result<ImportResult> where
Self: ProvideRuntimeApi<Block>, Self: ProvideRuntimeApi<Block>,
<Self as ProvideRuntimeApi<Block>>::Api: CoreApi<Block, Error = Error> + <Self as ProvideRuntimeApi<Block>>::Api: CoreApi<Block> +
ApiExt<Block, StateBackend = B::State>, ApiExt<Block, StateBackend = B::State>,
{ {
let BlockImportParams { let BlockImportParams {
@@ -696,7 +696,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
import_existing: bool, import_existing: bool,
) -> sp_blockchain::Result<ImportResult> where ) -> sp_blockchain::Result<ImportResult> where
Self: ProvideRuntimeApi<Block>, Self: ProvideRuntimeApi<Block>,
<Self as ProvideRuntimeApi<Block>>::Api: CoreApi<Block, Error = Error> + <Self as ProvideRuntimeApi<Block>>::Api: CoreApi<Block> +
ApiExt<Block, StateBackend = B::State>, ApiExt<Block, StateBackend = B::State>,
{ {
let parent_hash = import_headers.post().parent_hash().clone(); let parent_hash = import_headers.post().parent_hash().clone();
@@ -838,7 +838,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
) -> sp_blockchain::Result<Option<ImportResult>> ) -> sp_blockchain::Result<Option<ImportResult>>
where where
Self: ProvideRuntimeApi<Block>, Self: ProvideRuntimeApi<Block>,
<Self as ProvideRuntimeApi<Block>>::Api: CoreApi<Block, Error = Error> + <Self as ProvideRuntimeApi<Block>>::Api: CoreApi<Block> +
ApiExt<Block, StateBackend = B::State>, ApiExt<Block, StateBackend = B::State>,
{ {
let parent_hash = import_block.header.parent_hash(); let parent_hash = import_block.header.parent_hash();
@@ -1272,7 +1272,7 @@ impl<B, E, Block, RA> BlockBuilderProvider<B, Block, Self> for Client<B, E, Bloc
Block: BlockT, Block: BlockT,
Self: ChainHeaderBackend<Block> + ProvideRuntimeApi<Block>, Self: ChainHeaderBackend<Block> + ProvideRuntimeApi<Block>,
<Self as ProvideRuntimeApi<Block>>::Api: ApiExt<Block, StateBackend = backend::StateBackendFor<B, Block>> <Self as ProvideRuntimeApi<Block>>::Api: ApiExt<Block, StateBackend = backend::StateBackendFor<B, Block>>
+ BlockBuilderApi<Block, Error = Error>, + BlockBuilderApi<Block>,
{ {
fn new_block_at<R: Into<RecordProof>>( fn new_block_at<R: Into<RecordProof>>(
&self, &self,
@@ -1628,18 +1628,17 @@ impl<B, E, Block, RA> CallApiAt<Block> for Client<B, E, Block, RA> where
E: CallExecutor<Block, Backend = B> + Send + Sync, E: CallExecutor<Block, Backend = B> + Send + Sync,
Block: BlockT, Block: BlockT,
{ {
type Error = Error;
type StateBackend = B::State; type StateBackend = B::State;
fn call_api_at< fn call_api_at<
'a, 'a,
R: Encode + Decode + PartialEq, R: Encode + Decode + PartialEq,
NC: FnOnce() -> result::Result<R, String> + UnwindSafe, NC: FnOnce() -> result::Result<R, sp_api::ApiError> + UnwindSafe,
C: CoreApi<Block, Error = Error>, C: CoreApi<Block>,
>( >(
&self, &self,
params: CallApiAtParams<'a, Block, C, NC, B::State>, params: CallApiAtParams<'a, Block, C, NC, B::State>,
) -> sp_blockchain::Result<NativeOrEncoded<R>> { ) -> Result<NativeOrEncoded<R>, sp_api::ApiError> {
let core_api = params.core_api; let core_api = params.core_api;
let at = params.at; let at = params.at;
@@ -1649,7 +1648,9 @@ impl<B, E, Block, RA> CallApiAt<Block> for Client<B, E, Block, RA> where
); );
self.executor.contextual_call::<_, fn(_,_) -> _,_,_>( self.executor.contextual_call::<_, fn(_,_) -> _,_,_>(
|| core_api.initialize_block(at, &self.prepare_environment_block(at)?), || core_api
.initialize_block(at, &self.prepare_environment_block(at)?)
.map_err(Error::RuntimeApiError),
at, at,
params.function, params.function,
&params.arguments, &params.arguments,
@@ -1660,11 +1661,14 @@ impl<B, E, Block, RA> CallApiAt<Block> for Client<B, E, Block, RA> where
params.native_call, params.native_call,
params.recorder, params.recorder,
Some(extensions), Some(extensions),
) ).map_err(Into::into)
} }
fn runtime_version_at(&self, at: &BlockId<Block>) -> sp_blockchain::Result<RuntimeVersion> { fn runtime_version_at(
self.runtime_version_at(at) &self,
at: &BlockId<Block>,
) -> Result<RuntimeVersion, sp_api::ApiError> {
self.runtime_version_at(at).map_err(Into::into)
} }
} }
@@ -1676,7 +1680,7 @@ impl<B, E, Block, RA> sp_consensus::BlockImport<Block> for &Client<B, E, Block,
E: CallExecutor<Block> + Send + Sync, E: CallExecutor<Block> + Send + Sync,
Block: BlockT, Block: BlockT,
Client<B, E, Block, RA>: ProvideRuntimeApi<Block>, Client<B, E, Block, RA>: ProvideRuntimeApi<Block>,
<Client<B, E, Block, RA> as ProvideRuntimeApi<Block>>::Api: CoreApi<Block, Error = Error> + <Client<B, E, Block, RA> as ProvideRuntimeApi<Block>>::Api: CoreApi<Block> +
ApiExt<Block, StateBackend = B::State>, ApiExt<Block, StateBackend = B::State>,
{ {
type Error = ConsensusError; type Error = ConsensusError;
@@ -1776,7 +1780,7 @@ impl<B, E, Block, RA> sp_consensus::BlockImport<Block> for Client<B, E, Block, R
E: CallExecutor<Block> + Send + Sync, E: CallExecutor<Block> + Send + Sync,
Block: BlockT, Block: BlockT,
Self: ProvideRuntimeApi<Block>, Self: ProvideRuntimeApi<Block>,
<Self as ProvideRuntimeApi<Block>>::Api: CoreApi<Block, Error = Error> + <Self as ProvideRuntimeApi<Block>>::Api: CoreApi<Block> +
ApiExt<Block, StateBackend = B::State>, ApiExt<Block, StateBackend = B::State>,
{ {
type Error = ConsensusError; type Error = ConsensusError;
@@ -1935,7 +1939,7 @@ impl<B, E, Block, RA> backend::AuxStore for Client<B, E, Block, RA>
E: CallExecutor<Block>, E: CallExecutor<Block>,
Block: BlockT, Block: BlockT,
Self: ProvideRuntimeApi<Block>, Self: ProvideRuntimeApi<Block>,
<Self as ProvideRuntimeApi<Block>>::Api: CoreApi<Block, Error = Error>, <Self as ProvideRuntimeApi<Block>>::Api: CoreApi<Block>,
{ {
/// Insert auxiliary data into key-value store. /// Insert auxiliary data into key-value store.
fn insert_aux< fn insert_aux<
@@ -1965,7 +1969,7 @@ impl<B, E, Block, RA> backend::AuxStore for &Client<B, E, Block, RA>
E: CallExecutor<Block>, E: CallExecutor<Block>,
Block: BlockT, Block: BlockT,
Client<B, E, Block, RA>: ProvideRuntimeApi<Block>, Client<B, E, Block, RA>: ProvideRuntimeApi<Block>,
<Client<B, E, Block, RA> as ProvideRuntimeApi<Block>>::Api: CoreApi<Block, Error = Error>, <Client<B, E, Block, RA> as ProvideRuntimeApi<Block>>::Api: CoreApi<Block>,
{ {
fn insert_aux< fn insert_aux<
'a, 'a,
@@ -215,7 +215,7 @@ impl CallExecutor<Block> for DummyCallExecutor {
Result<NativeOrEncoded<R>, Self::Error> Result<NativeOrEncoded<R>, Self::Error>
) -> Result<NativeOrEncoded<R>, Self::Error>, ) -> Result<NativeOrEncoded<R>, Self::Error>,
R: Encode + Decode + PartialEq, R: Encode + Decode + PartialEq,
NC: FnOnce() -> Result<R, String> + UnwindSafe, NC: FnOnce() -> Result<R, sp_api::ApiError> + UnwindSafe,
>( >(
&self, &self,
_initialize_block_fn: IB, _initialize_block_fn: IB,
@@ -1327,7 +1327,9 @@ fn doesnt_import_blocks_that_revert_finality() {
let import_err = client.import(BlockOrigin::Own, b3).err().unwrap(); let import_err = client.import(BlockOrigin::Own, b3).err().unwrap();
let expected_err = ConsensusError::ClientImport( let expected_err = ConsensusError::ClientImport(
sp_blockchain::Error::NotInFinalizedChain.to_string() sp_blockchain::Error::RuntimeApiError(
sp_api::ApiError::Application(Box::new(sp_blockchain::Error::NotInFinalizedChain))
).to_string()
); );
assert_eq!( assert_eq!(
+1 -4
View File
@@ -84,7 +84,6 @@ where
Client: ProvideRuntimeApi<Block> + BlockBackend<Block> + BlockIdTo<Block>, Client: ProvideRuntimeApi<Block> + BlockBackend<Block> + BlockIdTo<Block>,
Client: Send + Sync + 'static, Client: Send + Sync + 'static,
Client::Api: TaggedTransactionQueue<Block>, Client::Api: TaggedTransactionQueue<Block>,
sp_api::ApiErrorFor<Client, Block>: Send + std::fmt::Display,
{ {
type Block = Block; type Block = Block;
type Error = error::Error; type Error = error::Error;
@@ -166,14 +165,13 @@ where
Client: ProvideRuntimeApi<Block> + BlockBackend<Block> + BlockIdTo<Block>, Client: ProvideRuntimeApi<Block> + BlockBackend<Block> + BlockIdTo<Block>,
Client: Send + Sync + 'static, Client: Send + Sync + 'static,
Client::Api: TaggedTransactionQueue<Block>, Client::Api: TaggedTransactionQueue<Block>,
sp_api::ApiErrorFor<Client, Block>: Send + std::fmt::Display,
{ {
sp_tracing::within_span!(sp_tracing::Level::TRACE, "validate_transaction"; sp_tracing::within_span!(sp_tracing::Level::TRACE, "validate_transaction";
{ {
let runtime_api = client.runtime_api(); let runtime_api = client.runtime_api();
let has_v2 = sp_tracing::within_span! { sp_tracing::Level::TRACE, "check_version"; let has_v2 = sp_tracing::within_span! { sp_tracing::Level::TRACE, "check_version";
runtime_api runtime_api
.has_api_with::<dyn TaggedTransactionQueue<Block, Error=()>, _>(&at, |v| v >= 2) .has_api_with::<dyn TaggedTransactionQueue<Block>, _>(&at, |v| v >= 2)
.unwrap_or_default() .unwrap_or_default()
}; };
@@ -198,7 +196,6 @@ where
Client: ProvideRuntimeApi<Block> + BlockBackend<Block> + BlockIdTo<Block>, Client: ProvideRuntimeApi<Block> + BlockBackend<Block> + BlockIdTo<Block>,
Client: Send + Sync + 'static, Client: Send + Sync + 'static,
Client::Api: TaggedTransactionQueue<Block>, Client::Api: TaggedTransactionQueue<Block>,
sp_api::ApiErrorFor<Client, Block>: Send + std::fmt::Display,
{ {
/// Validates a transaction by calling into the runtime, same as /// Validates a transaction by calling into the runtime, same as
/// `validate_transaction` but blocks the current thread when performing /// `validate_transaction` but blocks the current thread when performing
@@ -360,7 +360,6 @@ where
+ sp_runtime::traits::BlockIdTo<Block>, + sp_runtime::traits::BlockIdTo<Block>,
Client: sc_client_api::ExecutorProvider<Block> + Send + Sync + 'static, Client: sc_client_api::ExecutorProvider<Block> + Send + Sync + 'static,
Client::Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>, Client::Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>,
sp_api::ApiErrorFor<Client, Block>: Send + std::fmt::Display,
{ {
/// Create new basic transaction pool for a full node with the provided api. /// Create new basic transaction pool for a full node with the provided api.
pub fn new_full( pub fn new_full(
@@ -391,7 +390,6 @@ where
+ sp_runtime::traits::BlockIdTo<Block>, + sp_runtime::traits::BlockIdTo<Block>,
Client: Send + Sync + 'static, Client: Send + Sync + 'static,
Client::Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>, Client::Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>,
sp_api::ApiErrorFor<Client, Block>: Send + std::fmt::Display,
{ {
type Block = Block; type Block = Block;
type Hash = sc_transaction_graph::ExtrinsicHash<FullChainApi<Client, Block>>; type Hash = sc_transaction_graph::ExtrinsicHash<FullChainApi<Client, Block>>;
@@ -187,14 +187,15 @@ fn generate_native_call_generators(decl: &ItemTrait) -> Result<TokenStream> {
result.push(quote!( result.push(quote!(
#[cfg(any(feature = "std", test))] #[cfg(any(feature = "std", test))]
fn convert_between_block_types fn convert_between_block_types
<I: #crate_::Encode, R: #crate_::Decode>( <I: #crate_::Encode, R: #crate_::Decode, F: FnOnce(#crate_::codec::Error) -> #crate_::ApiError>(
input: &I, error_desc: &'static str, input: &I,
) -> std::result::Result<R, String> map_error: F,
) -> std::result::Result<R, #crate_::ApiError>
{ {
<R as #crate_::DecodeLimit>::decode_with_depth_limit( <R as #crate_::DecodeLimit>::decode_with_depth_limit(
#crate_::MAX_EXTRINSIC_DEPTH, #crate_::MAX_EXTRINSIC_DEPTH,
&mut &#crate_::Encode::encode(input)[..], &mut &#crate_::Encode::encode(input)[..],
).map_err(|e| format!("{} {}", error_desc, e)) ).map_err(map_error)
} }
)); ));
@@ -202,19 +203,26 @@ fn generate_native_call_generators(decl: &ItemTrait) -> Result<TokenStream> {
for fn_ in fns { for fn_ in fns {
let params = extract_parameter_names_types_and_borrows(&fn_, AllowSelfRefInParameters::No)?; let params = extract_parameter_names_types_and_borrows(&fn_, AllowSelfRefInParameters::No)?;
let trait_fn_name = &fn_.ident; let trait_fn_name = &fn_.ident;
let function_name_str = fn_.ident.to_string();
let fn_name = generate_native_call_generator_fn_name(&fn_.ident); let fn_name = generate_native_call_generator_fn_name(&fn_.ident);
let output = return_type_replace_block_with_node_block(fn_.output.clone()); let output = return_type_replace_block_with_node_block(fn_.output.clone());
let output_ty = return_type_extract_type(&output); let output_ty = return_type_extract_type(&output);
let output = quote!( std::result::Result<#output_ty, String> ); let output = quote!( std::result::Result<#output_ty, #crate_::ApiError> );
// Every type that is using the `Block` generic parameter, we need to encode/decode, // Every type that is using the `Block` generic parameter, we need to encode/decode,
// to make it compatible between the runtime/node. // to make it compatible between the runtime/node.
let conversions = params.iter().filter(|v| type_is_using_block(&v.1)).map(|(n, t, _)| { let conversions = params.iter().filter(|v| type_is_using_block(&v.1)).map(|(n, t, _)| {
let name_str = format!( let param_name = quote!(#n).to_string();
"Could not convert parameter `{}` between node and runtime:", quote!(#n)
);
quote!( quote!(
let #n: #t = convert_between_block_types(&#n, #name_str)?; let #n: #t = convert_between_block_types(
&#n,
|e| #crate_::ApiError::FailedToConvertParameter {
function: #function_name_str,
parameter: #param_name,
error: e,
},
)?;
) )
}); });
// Same as for the input types, we need to check if we also need to convert the output, // Same as for the input types, we need to check if we also need to convert the output,
@@ -223,7 +231,10 @@ fn generate_native_call_generators(decl: &ItemTrait) -> Result<TokenStream> {
quote!( quote!(
convert_between_block_types( convert_between_block_types(
&res, &res,
"Could not convert return value from runtime to node!" |e| #crate_::ApiError::FailedToConvertReturnValue {
function: #function_name_str,
error: e,
},
) )
) )
} else { } else {
@@ -399,10 +410,10 @@ fn generate_call_api_at_calls(decl: &ItemTrait) -> Result<TokenStream> {
#[cfg(any(feature = "std", test))] #[cfg(any(feature = "std", test))]
pub fn #fn_name< pub fn #fn_name<
R: #crate_::Encode + #crate_::Decode + PartialEq, R: #crate_::Encode + #crate_::Decode + PartialEq,
NC: FnOnce() -> std::result::Result<R, String> + std::panic::UnwindSafe, NC: FnOnce() -> std::result::Result<R, #crate_::ApiError> + std::panic::UnwindSafe,
Block: #crate_::BlockT, Block: #crate_::BlockT,
T: #crate_::CallApiAt<Block>, T: #crate_::CallApiAt<Block>,
C: #crate_::Core<Block, Error = T::Error>, C: #crate_::Core<Block>,
>( >(
call_runtime_at: &T, call_runtime_at: &T,
core_api: &C, core_api: &C,
@@ -416,7 +427,7 @@ fn generate_call_api_at_calls(decl: &ItemTrait) -> Result<TokenStream> {
native_call: Option<NC>, native_call: Option<NC>,
context: #crate_::ExecutionContext, context: #crate_::ExecutionContext,
recorder: &Option<#crate_::ProofRecorder<Block>>, recorder: &Option<#crate_::ProofRecorder<Block>>,
) -> std::result::Result<#crate_::NativeOrEncoded<R>, T::Error> { ) -> std::result::Result<#crate_::NativeOrEncoded<R>, #crate_::ApiError> {
let version = call_runtime_at.runtime_version_at(at)?; let version = call_runtime_at.runtime_version_at(at)?;
use #crate_::InitializeBlock; use #crate_::InitializeBlock;
let initialize_block = if #skip_initialize_block { let initialize_block = if #skip_initialize_block {
@@ -621,7 +632,7 @@ impl<'a> ToClientSideDecl<'a> {
context: #crate_::ExecutionContext, context: #crate_::ExecutionContext,
params: Option<( #( #param_types ),* )>, params: Option<( #( #param_types ),* )>,
params_encoded: Vec<u8>, params_encoded: Vec<u8>,
) -> std::result::Result<#crate_::NativeOrEncoded<#ret_type>, Self::Error>; ) -> std::result::Result<#crate_::NativeOrEncoded<#ret_type>, #crate_::ApiError>;
} }
) )
} }
@@ -647,7 +658,7 @@ impl<'a> ToClientSideDecl<'a> {
let params2 = params.clone(); let params2 = params.clone();
let ret_type = return_type_extract_type(&method.sig.output); let ret_type = return_type_extract_type(&method.sig.output);
fold_fn_decl_for_client_side(&mut method.sig, &self.block_id); fold_fn_decl_for_client_side(&mut method.sig, &self.block_id, &self.crate_);
let name_impl = generate_method_runtime_api_impl_name(&self.trait_, &method.sig.ident); let name_impl = generate_method_runtime_api_impl_name(&self.trait_, &method.sig.ident);
let crate_ = self.crate_; let crate_ = self.crate_;
@@ -705,7 +716,12 @@ impl<'a> ToClientSideDecl<'a> {
}, },
#crate_::NativeOrEncoded::Encoded(r) => { #crate_::NativeOrEncoded::Encoded(r) => {
<#ret_type as #crate_::Decode>::decode(&mut &r[..]) <#ret_type as #crate_::Decode>::decode(&mut &r[..])
.map_err(|err| { #crate_::ApiError::new(#function_name, err).into() }) .map_err(|err|
#crate_::ApiError::FailedToDecodeReturnValue {
function: #function_name,
error: err,
}
)
} }
} }
) )
@@ -728,12 +744,10 @@ impl<'a> Fold for ToClientSideDecl<'a> {
if is_core_trait { if is_core_trait {
// Add all the supertraits we want to have for `Core`. // Add all the supertraits we want to have for `Core`.
let crate_ = &self.crate_;
input.supertraits = parse_quote!( input.supertraits = parse_quote!(
'static 'static
+ Send + Send
+ Sync + Sync
+ #crate_::ApiErrorExt
); );
} else { } else {
// Add the `Core` runtime api as super trait. // Add the `Core` runtime api as super trait.
@@ -803,12 +817,12 @@ fn generate_runtime_info_impl(trait_: &ItemTrait, version: u64) -> TokenStream {
let bounds = &t.bounds; let bounds = &t.bounds;
quote! { #ident #colon_token #bounds } quote! { #ident #colon_token #bounds }
}).chain(std::iter::once(quote! { __Sr_Api_Error__ })); });
let ty_generics = trait_.generics.type_params().map(|t| { let ty_generics = trait_.generics.type_params().map(|t| {
let ident = &t.ident; let ident = &t.ident;
quote! { #ident } quote! { #ident }
}).chain(std::iter::once(quote! { Error = __Sr_Api_Error__ })); });
quote!( quote!(
#[cfg(any(feature = "std", test))] #[cfg(any(feature = "std", test))]
@@ -233,16 +233,6 @@ fn generate_runtime_api_base_structures() -> Result<TokenStream> {
C::StateBackend: #crate_::StateBackend<#crate_::HashFor<Block>>, C::StateBackend: #crate_::StateBackend<#crate_::HashFor<Block>>,
{} {}
#[cfg(any(feature = "std", test))]
impl<Block: #crate_::BlockT, C: #crate_::CallApiAt<Block>> #crate_::ApiErrorExt
for RuntimeApiImpl<Block, C>
where
// Rust bug: https://github.com/rust-lang/rust/issues/24159
C::StateBackend: #crate_::StateBackend<#crate_::HashFor<Block>>,
{
type Error = C::Error;
}
#[cfg(any(feature = "std", test))] #[cfg(any(feature = "std", test))]
impl<Block: #crate_::BlockT, C: #crate_::CallApiAt<Block>> #crate_::ApiExt<Block> for impl<Block: #crate_::BlockT, C: #crate_::CallApiAt<Block>> #crate_::ApiExt<Block> for
RuntimeApiImpl<Block, C> RuntimeApiImpl<Block, C>
@@ -269,16 +259,20 @@ fn generate_runtime_api_base_structures() -> Result<TokenStream> {
fn has_api<A: #crate_::RuntimeApiInfo + ?Sized>( fn has_api<A: #crate_::RuntimeApiInfo + ?Sized>(
&self, &self,
at: &#crate_::BlockId<Block>, at: &#crate_::BlockId<Block>,
) -> std::result::Result<bool, C::Error> where Self: Sized { ) -> std::result::Result<bool, #crate_::ApiError> where Self: Sized {
self.call.runtime_version_at(at).map(|v| v.has_api_with(&A::ID, |v| v == A::VERSION)) self.call
.runtime_version_at(at)
.map(|v| v.has_api_with(&A::ID, |v| v == A::VERSION))
} }
fn has_api_with<A: #crate_::RuntimeApiInfo + ?Sized, P: Fn(u32) -> bool>( fn has_api_with<A: #crate_::RuntimeApiInfo + ?Sized, P: Fn(u32) -> bool>(
&self, &self,
at: &#crate_::BlockId<Block>, at: &#crate_::BlockId<Block>,
pred: P, pred: P,
) -> std::result::Result<bool, C::Error> where Self: Sized { ) -> std::result::Result<bool, #crate_::ApiError> where Self: Sized {
self.call.runtime_version_at(at).map(|v| v.has_api_with(&A::ID, pred)) self.call
.runtime_version_at(at)
.map(|v| v.has_api_with(&A::ID, pred))
} }
fn record_proof(&mut self) { fn record_proof(&mut self) {
@@ -306,7 +300,7 @@ fn generate_runtime_api_base_structures() -> Result<TokenStream> {
>>, >>,
parent_hash: Block::Hash, parent_hash: Block::Hash,
) -> std::result::Result< ) -> std::result::Result<
#crate_::StorageChanges<Self::StateBackend, Block>, #crate_::StorageChanges<C::StateBackend, Block>,
String String
> where Self: Sized { > where Self: Sized {
self.initialized_block.borrow_mut().take(); self.initialized_block.borrow_mut().take();
@@ -513,7 +507,7 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> {
// Generate the correct return type. // Generate the correct return type.
input.sig.output = parse_quote!( input.sig.output = parse_quote!(
-> std::result::Result<#crate_::NativeOrEncoded<#ret_type>, RuntimeApiImplCall::Error> -> std::result::Result<#crate_::NativeOrEncoded<#ret_type>, #crate_::ApiError>
); );
// Generate the new method implementation that calls into the runtime. // Generate the new method implementation that calls into the runtime.
@@ -554,7 +548,7 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> {
) )
}; };
let mut input = fold::fold_impl_item_method(self, input); let mut input = fold::fold_impl_item_method(self, input);
// We need to set the block, after we modified the rest of the ast, otherwise we would // We need to set the block, after we modified the rest of the ast, otherwise we would
// modify our generated block as well. // modify our generated block as well.
input.block = block; input.block = block;
@@ -27,7 +27,7 @@ use proc_macro2::{Span, TokenStream};
use quote::{quote, quote_spanned}; use quote::{quote, quote_spanned};
use syn::{ use syn::{
spanned::Spanned, parse_macro_input, Ident, Type, ItemImpl, ImplItem, TypePath, parse_quote, spanned::Spanned, parse_macro_input, Ident, Type, ItemImpl, TypePath, parse_quote,
parse::{Parse, ParseStream, Result, Error}, fold::{self, Fold}, Attribute, Pat, parse::{Parse, ParseStream, Result, Error}, fold::{self, Fold}, Attribute, Pat,
}; };
@@ -61,29 +61,14 @@ impl Parse for RuntimeApiImpls {
} }
} }
/// Implement the `ApiExt` trait, `ApiErrorExt` trait and the `Core` runtime api. /// Implement the `ApiExt` trait and the `Core` runtime api.
fn implement_common_api_traits( fn implement_common_api_traits(
error_type: Option<Type>,
block_type: TypePath, block_type: TypePath,
self_ty: Type, self_ty: Type,
) -> Result<TokenStream> { ) -> Result<TokenStream> {
let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID);
let error_type = error_type
.map(|e| quote!(#e))
.unwrap_or_else(|| quote!( #crate_::ApiError ) );
// Quote using the span from `error_type` to generate nice error messages when the type is
// not implementing a trait or similar.
let api_error_ext = quote_spanned! { error_type.span() =>
impl #crate_::ApiErrorExt for #self_ty {
type Error = #error_type;
}
};
Ok(quote!( Ok(quote!(
#api_error_ext
impl #crate_::ApiExt<#block_type> for #self_ty { impl #crate_::ApiExt<#block_type> for #self_ty {
type StateBackend = #crate_::InMemoryBackend<#crate_::HashFor<#block_type>>; type StateBackend = #crate_::InMemoryBackend<#crate_::HashFor<#block_type>>;
@@ -97,7 +82,7 @@ fn implement_common_api_traits(
fn has_api<A: #crate_::RuntimeApiInfo + ?Sized>( fn has_api<A: #crate_::RuntimeApiInfo + ?Sized>(
&self, &self,
_: &#crate_::BlockId<#block_type>, _: &#crate_::BlockId<#block_type>,
) -> std::result::Result<bool, #error_type> where Self: Sized { ) -> std::result::Result<bool, #crate_::ApiError> where Self: Sized {
Ok(true) Ok(true)
} }
@@ -105,7 +90,7 @@ fn implement_common_api_traits(
&self, &self,
_: &#crate_::BlockId<#block_type>, _: &#crate_::BlockId<#block_type>,
pred: P, pred: P,
) -> std::result::Result<bool, #error_type> where Self: Sized { ) -> std::result::Result<bool, #crate_::ApiError> where Self: Sized {
Ok(pred(A::VERSION)) Ok(pred(A::VERSION))
} }
@@ -140,7 +125,7 @@ fn implement_common_api_traits(
_: #crate_::ExecutionContext, _: #crate_::ExecutionContext,
_: Option<()>, _: Option<()>,
_: Vec<u8>, _: Vec<u8>,
) -> std::result::Result<#crate_::NativeOrEncoded<#crate_::RuntimeVersion>, #error_type> { ) -> std::result::Result<#crate_::NativeOrEncoded<#crate_::RuntimeVersion>, #crate_::ApiError> {
unimplemented!("Not required for testing!") unimplemented!("Not required for testing!")
} }
@@ -150,7 +135,7 @@ fn implement_common_api_traits(
_: #crate_::ExecutionContext, _: #crate_::ExecutionContext,
_: Option<#block_type>, _: Option<#block_type>,
_: Vec<u8>, _: Vec<u8>,
) -> std::result::Result<#crate_::NativeOrEncoded<()>, #error_type> { ) -> std::result::Result<#crate_::NativeOrEncoded<()>, #crate_::ApiError> {
unimplemented!("Not required for testing!") unimplemented!("Not required for testing!")
} }
@@ -160,7 +145,7 @@ fn implement_common_api_traits(
_: #crate_::ExecutionContext, _: #crate_::ExecutionContext,
_: Option<&<#block_type as #crate_::BlockT>::Header>, _: Option<&<#block_type as #crate_::BlockT>::Header>,
_: Vec<u8>, _: Vec<u8>,
) -> std::result::Result<#crate_::NativeOrEncoded<()>, #error_type> { ) -> std::result::Result<#crate_::NativeOrEncoded<()>, #crate_::ApiError> {
unimplemented!("Not required for testing!") unimplemented!("Not required for testing!")
} }
} }
@@ -230,9 +215,6 @@ struct FoldRuntimeApiImpl<'a> {
block_type: &'a TypePath, block_type: &'a TypePath,
/// The identifier of the trait being implemented. /// The identifier of the trait being implemented.
impl_trait: &'a Ident, impl_trait: &'a Ident,
/// Stores the error type that is being found in the trait implementation as associated type
/// with the name `Error`.
error_type: &'a mut Option<Type>,
} }
impl<'a> Fold for FoldRuntimeApiImpl<'a> { impl<'a> Fold for FoldRuntimeApiImpl<'a> {
@@ -300,7 +282,7 @@ impl<'a> Fold for FoldRuntimeApiImpl<'a> {
// Generate the correct return type. // Generate the correct return type.
input.sig.output = parse_quote!( input.sig.output = parse_quote!(
-> std::result::Result<#crate_::NativeOrEncoded<#ret_type>, Self::Error> -> std::result::Result<#crate_::NativeOrEncoded<#ret_type>, #crate_::ApiError>
); );
} }
@@ -336,51 +318,12 @@ impl<'a> Fold for FoldRuntimeApiImpl<'a> {
input.block = block; input.block = block;
input input
} }
fn fold_impl_item(&mut self, input: ImplItem) -> ImplItem {
match input {
ImplItem::Type(ty) => {
if ty.ident == "Error" {
if let Some(error_type) = self.error_type {
if *error_type != ty.ty {
let mut error = Error::new(
ty.span(),
"Error type can not change between runtime apis",
);
let error_first = Error::new(
error_type.span(),
"First error type was declared here."
);
error.combine(error_first);
ImplItem::Verbatim(error.to_compile_error())
} else {
ImplItem::Verbatim(Default::default())
}
} else {
*self.error_type = Some(ty.ty);
ImplItem::Verbatim(Default::default())
}
} else {
let error = Error::new(
ty.span(),
"Only associated type with name `Error` is allowed",
);
ImplItem::Verbatim(error.to_compile_error())
}
},
o => fold::fold_impl_item(self, o),
}
}
} }
/// Result of [`generate_runtime_api_impls`]. /// Result of [`generate_runtime_api_impls`].
struct GeneratedRuntimeApiImpls { struct GeneratedRuntimeApiImpls {
/// All the runtime api implementations. /// All the runtime api implementations.
impls: TokenStream, impls: TokenStream,
/// The error type that should be used by the runtime apis.
error_type: Option<Type>,
/// The block type that is being used by the runtime apis. /// The block type that is being used by the runtime apis.
block_type: TypePath, block_type: TypePath,
/// The type the traits are implemented for. /// The type the traits are implemented for.
@@ -393,7 +336,6 @@ struct GeneratedRuntimeApiImpls {
/// extracts the error type, self type and the block type. /// extracts the error type, self type and the block type.
fn generate_runtime_api_impls(impls: &[ItemImpl]) -> Result<GeneratedRuntimeApiImpls> { fn generate_runtime_api_impls(impls: &[ItemImpl]) -> Result<GeneratedRuntimeApiImpls> {
let mut result = Vec::with_capacity(impls.len()); let mut result = Vec::with_capacity(impls.len());
let mut error_type = None;
let mut global_block_type: Option<TypePath> = None; let mut global_block_type: Option<TypePath> = None;
let mut self_ty: Option<Box<Type>> = None; let mut self_ty: Option<Box<Type>> = None;
@@ -451,7 +393,6 @@ fn generate_runtime_api_impls(impls: &[ItemImpl]) -> Result<GeneratedRuntimeApiI
let mut visitor = FoldRuntimeApiImpl { let mut visitor = FoldRuntimeApiImpl {
block_type, block_type,
impl_trait: &impl_trait.ident, impl_trait: &impl_trait.ident,
error_type: &mut error_type,
}; };
result.push(visitor.fold_item_impl(impl_.clone())); result.push(visitor.fold_item_impl(impl_.clone()));
@@ -459,7 +400,6 @@ fn generate_runtime_api_impls(impls: &[ItemImpl]) -> Result<GeneratedRuntimeApiI
Ok(GeneratedRuntimeApiImpls { Ok(GeneratedRuntimeApiImpls {
impls: quote!( #( #result )* ), impls: quote!( #( #result )* ),
error_type,
block_type: global_block_type.expect("There is a least one runtime api; qed"), block_type: global_block_type.expect("There is a least one runtime api; qed"),
self_ty: *self_ty.expect("There is at least one runtime api; qed"), self_ty: *self_ty.expect("There is at least one runtime api; qed"),
}) })
@@ -475,9 +415,9 @@ pub fn mock_impl_runtime_apis_impl(input: proc_macro::TokenStream) -> proc_macro
fn mock_impl_runtime_apis_impl_inner(api_impls: &[ItemImpl]) -> Result<TokenStream> { fn mock_impl_runtime_apis_impl_inner(api_impls: &[ItemImpl]) -> Result<TokenStream> {
let hidden_includes = generate_hidden_includes(HIDDEN_INCLUDES_ID); let hidden_includes = generate_hidden_includes(HIDDEN_INCLUDES_ID);
let GeneratedRuntimeApiImpls { impls, error_type, block_type, self_ty } = let GeneratedRuntimeApiImpls { impls, block_type, self_ty } =
generate_runtime_api_impls(api_impls)?; generate_runtime_api_impls(api_impls)?;
let api_traits = implement_common_api_traits(error_type, block_type, self_ty)?; let api_traits = implement_common_api_traits(block_type, self_ty)?;
Ok(quote!( Ok(quote!(
#hidden_includes #hidden_includes
@@ -99,6 +99,7 @@ pub fn replace_wild_card_parameter_names(input: &mut Signature) {
pub fn fold_fn_decl_for_client_side( pub fn fold_fn_decl_for_client_side(
input: &mut Signature, input: &mut Signature,
block_id: &TokenStream, block_id: &TokenStream,
crate_: &TokenStream,
) { ) {
replace_wild_card_parameter_names(input); replace_wild_card_parameter_names(input);
@@ -109,7 +110,7 @@ pub fn fold_fn_decl_for_client_side(
// Wrap the output in a `Result` // Wrap the output in a `Result`
input.output = { input.output = {
let ty = return_type_extract_type(&input.output); let ty = return_type_extract_type(&input.output);
parse_quote!( -> std::result::Result<#ty, Self::Error> ) parse_quote!( -> std::result::Result<#ty, #crate_::ApiError> )
}; };
} }
+42 -60
View File
@@ -67,7 +67,7 @@ pub use sp_std::{slice, mem};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use sp_std::result; use sp_std::result;
#[doc(hidden)] #[doc(hidden)]
pub use codec::{Encode, Decode, DecodeLimit}; pub use codec::{Encode, Decode, DecodeLimit, self};
use sp_core::OpaqueMetadata; use sp_core::OpaqueMetadata;
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::{panic::UnwindSafe, cell::RefCell}; use std::{panic::UnwindSafe, cell::RefCell};
@@ -246,8 +246,8 @@ pub use sp_api_proc_macro::impl_runtime_apis;
/// and the error type can be specified as associated type. If no error type is specified [`String`] /// and the error type can be specified as associated type. If no error type is specified [`String`]
/// is used as error type. /// is used as error type.
/// ///
/// Besides implementing the given traits, the [`Core`](sp_api::Core), [`ApiExt`](sp_api::ApiExt) /// Besides implementing the given traits, the [`Core`](sp_api::Core) and [`ApiExt`](sp_api::ApiExt)
/// and [`ApiErrorExt`](sp_api::ApiErrorExt) are implemented automatically. /// are implemented automatically.
/// ///
/// # Example /// # Example
/// ///
@@ -284,11 +284,6 @@ pub use sp_api_proc_macro::impl_runtime_apis;
/// } /// }
/// ///
/// impl BlockBuilder<Block> for MockApi { /// impl BlockBuilder<Block> for MockApi {
/// /// Sets the error type that is being used by the mock implementation.
/// /// The error type is used by all runtime apis. It is only required to
/// /// be specified in one trait implementation.
/// type Error = sp_api::ApiError;
///
/// fn build_block() -> Block { /// fn build_block() -> Block {
/// unimplemented!("Not Required in tests") /// unimplemented!("Not Required in tests")
/// } /// }
@@ -331,15 +326,14 @@ pub use sp_api_proc_macro::impl_runtime_apis;
/// ///
/// sp_api::mock_impl_runtime_apis! { /// sp_api::mock_impl_runtime_apis! {
/// impl Balance<Block> for MockApi { /// impl Balance<Block> for MockApi {
/// type Error = sp_api::ApiError;
/// #[advanced] /// #[advanced]
/// fn get_balance(&self, at: &BlockId<Block>) -> Result<NativeOrEncoded<u64>, Self::Error> { /// fn get_balance(&self, at: &BlockId<Block>) -> Result<NativeOrEncoded<u64>, sp_api::ApiError> {
/// println!("Being called at: {}", at); /// println!("Being called at: {}", at);
/// ///
/// Ok(self.balance.into()) /// Ok(self.balance.into())
/// } /// }
/// #[advanced] /// #[advanced]
/// fn set_balance(at: &BlockId<Block>, val: u64) -> Result<NativeOrEncoded<()>, Self::Error> { /// fn set_balance(at: &BlockId<Block>, val: u64) -> Result<NativeOrEncoded<()>, sp_api::ApiError> {
/// if let BlockId::Number(1) = at { /// if let BlockId::Number(1) = at {
/// println!("Being called to set balance to: {}", val); /// println!("Being called to set balance to: {}", val);
/// } /// }
@@ -393,46 +387,35 @@ pub trait ConstructRuntimeApi<Block: BlockT, C: CallApiAt<Block>> {
} }
/// An error describing which API call failed. /// An error describing which API call failed.
#[cfg_attr(feature = "std", derive(Debug, thiserror::Error, Eq, PartialEq))]
#[cfg_attr(feature = "std", error("Failed to execute API call {tag}"))]
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub struct ApiError { #[derive(Debug, thiserror::Error)]
tag: &'static str, pub enum ApiError {
#[source] #[error("Failed to decode return value of {function}")]
error: codec::Error, FailedToDecodeReturnValue {
} function: &'static str,
#[source]
#[cfg(feature = "std")] error: codec::Error,
impl From<(&'static str, codec::Error)> for ApiError { },
fn from((tag, error): (&'static str, codec::Error)) -> Self { #[error("Failed to convert return value from runtime to node of {function}")]
Self { FailedToConvertReturnValue {
tag, function: &'static str,
error, #[source]
} error: codec::Error,
} },
} #[error("Failed to convert parameter `{parameter}` from node to runtime of {function}")]
FailedToConvertParameter {
#[cfg(feature = "std")] function: &'static str,
impl ApiError { parameter: &'static str,
pub fn new(tag: &'static str, error: codec::Error) -> Self { #[source]
Self { error: codec::Error,
tag, },
error, #[error(transparent)]
} Application(#[from] Box<dyn std::error::Error + Send + Sync>),
}
}
/// Extends the runtime api traits with an associated error type. This trait is given as super
/// trait to every runtime api trait.
#[cfg(feature = "std")]
pub trait ApiErrorExt {
/// Error type used by the runtime apis.
type Error: std::fmt::Debug + From<ApiError>;
} }
/// Extends the runtime api implementation with some common functionality. /// Extends the runtime api implementation with some common functionality.
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub trait ApiExt<Block: BlockT>: ApiErrorExt { pub trait ApiExt<Block: BlockT> {
/// The state backend that is used to store the block states. /// The state backend that is used to store the block states.
type StateBackend: StateBackend<HashFor<Block>>; type StateBackend: StateBackend<HashFor<Block>>;
@@ -450,14 +433,14 @@ pub trait ApiExt<Block: BlockT>: ApiErrorExt {
fn has_api<A: RuntimeApiInfo + ?Sized>( fn has_api<A: RuntimeApiInfo + ?Sized>(
&self, &self,
at: &BlockId<Block>, at: &BlockId<Block>,
) -> Result<bool, Self::Error> where Self: Sized; ) -> Result<bool, ApiError> where Self: Sized;
/// Check if the given api is implemented and the version passes a predicate. /// Check if the given api is implemented and the version passes a predicate.
fn has_api_with<A: RuntimeApiInfo + ?Sized, P: Fn(u32) -> bool>( fn has_api_with<A: RuntimeApiInfo + ?Sized, P: Fn(u32) -> bool>(
&self, &self,
at: &BlockId<Block>, at: &BlockId<Block>,
pred: P, pred: P,
) -> Result<bool, Self::Error> where Self: Sized; ) -> Result<bool, ApiError> where Self: Sized;
/// Start recording all accessed trie nodes for generating proofs. /// Start recording all accessed trie nodes for generating proofs.
fn record_proof(&mut self); fn record_proof(&mut self);
@@ -478,7 +461,10 @@ pub trait ApiExt<Block: BlockT>: ApiErrorExt {
backend: &Self::StateBackend, backend: &Self::StateBackend,
changes_trie_state: Option<&ChangesTrieState<HashFor<Block>, NumberFor<Block>>>, changes_trie_state: Option<&ChangesTrieState<HashFor<Block>, NumberFor<Block>>>,
parent_hash: Block::Hash, parent_hash: Block::Hash,
) -> Result<StorageChanges<Self::StateBackend, Block>, String> where Self: Sized; ) -> Result<
StorageChanges<Self::StateBackend, Block>,
String
> where Self: Sized;
} }
/// Before calling any runtime api function, the runtime need to be initialized /// Before calling any runtime api function, the runtime need to be initialized
@@ -533,9 +519,6 @@ pub struct CallApiAtParams<'a, Block: BlockT, C, NC, Backend: StateBackend<HashF
/// Something that can call into the an api at a given block. /// Something that can call into the an api at a given block.
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub trait CallApiAt<Block: BlockT> { pub trait CallApiAt<Block: BlockT> {
/// Error type used by the implementation.
type Error: std::fmt::Debug + From<ApiError>;
/// The state backend that is used to store the block states. /// The state backend that is used to store the block states.
type StateBackend: StateBackend<HashFor<Block>>; type StateBackend: StateBackend<HashFor<Block>>;
@@ -544,15 +527,18 @@ pub trait CallApiAt<Block: BlockT> {
fn call_api_at< fn call_api_at<
'a, 'a,
R: Encode + Decode + PartialEq, R: Encode + Decode + PartialEq,
NC: FnOnce() -> result::Result<R, String> + UnwindSafe, NC: FnOnce() -> result::Result<R, ApiError> + UnwindSafe,
C: Core<Block, Error = Self::Error>, C: Core<Block>,
>( >(
&self, &self,
params: CallApiAtParams<'a, Block, C, NC, Self::StateBackend>, params: CallApiAtParams<'a, Block, C, NC, Self::StateBackend>,
) -> Result<NativeOrEncoded<R>, Self::Error>; ) -> Result<NativeOrEncoded<R>, ApiError>;
/// Returns the runtime version at the given block. /// Returns the runtime version at the given block.
fn runtime_version_at(&self, at: &BlockId<Block>) -> Result<RuntimeVersion, Self::Error>; fn runtime_version_at(
&self,
at: &BlockId<Block>,
) -> Result<RuntimeVersion, ApiError>;
} }
/// Auxiliary wrapper that holds an api instance and binds it to the given lifetime. /// Auxiliary wrapper that holds an api instance and binds it to the given lifetime.
@@ -605,10 +591,6 @@ pub trait RuntimeApiInfo {
const VERSION: u32; const VERSION: u32;
} }
/// Extracts the `Api::Error` for a type that provides a runtime api.
#[cfg(feature = "std")]
pub type ApiErrorFor<T, Block> = <<T as ProvideRuntimeApi<Block>>::Api as ApiErrorExt>::Error;
#[derive(codec::Encode, codec::Decode)] #[derive(codec::Encode, codec::Decode)]
pub struct OldRuntimeVersion { pub struct OldRuntimeVersion {
pub spec_name: RuntimeString, pub spec_name: RuntimeString,
@@ -23,7 +23,6 @@ use sp_api::{
use sp_runtime::{traits::{GetNodeBlockType, Block as BlockT}, generic::BlockId}; use sp_runtime::{traits::{GetNodeBlockType, Block as BlockT}, generic::BlockId};
use sp_core::NativeOrEncoded; use sp_core::NativeOrEncoded;
use substrate_test_runtime_client::runtime::Block; use substrate_test_runtime_client::runtime::Block;
use sp_blockchain::Result;
/// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` /// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType`
/// trait are done by the `construct_runtime!` macro in a real runtime. /// trait are done by the `construct_runtime!` macro in a real runtime.
@@ -105,7 +104,7 @@ mock_impl_runtime_apis! {
#[advanced] #[advanced]
fn same_name(_: &BlockId<Block>) -> fn same_name(_: &BlockId<Block>) ->
std::result::Result< Result<
NativeOrEncoded<()>, NativeOrEncoded<()>,
ApiError ApiError
> >
@@ -115,7 +114,7 @@ mock_impl_runtime_apis! {
#[advanced] #[advanced]
fn wild_card(at: &BlockId<Block>, _: u32) -> fn wild_card(at: &BlockId<Block>, _: u32) ->
std::result::Result< Result<
NativeOrEncoded<()>, NativeOrEncoded<()>,
ApiError ApiError
> >
@@ -124,7 +123,7 @@ mock_impl_runtime_apis! {
// yeah // yeah
Ok(().into()) Ok(().into())
} else { } else {
Err(ApiError::new("MockApi", codec::Error::from("Ohh noooo"))) Err((Box::from("Test error") as Box<dyn std::error::Error + Send + Sync>).into())
} }
} }
} }
@@ -143,33 +142,33 @@ type TestClient = substrate_test_runtime_client::client::Client<
#[test] #[test]
fn test_client_side_function_signature() { fn test_client_side_function_signature() {
let _test: fn(&RuntimeApiImpl<Block, TestClient>, &BlockId<Block>, u64) -> Result<()> = let _test: fn(&RuntimeApiImpl<Block, TestClient>, &BlockId<Block>, u64) -> Result<(), ApiError> =
RuntimeApiImpl::<Block, TestClient>::test; RuntimeApiImpl::<Block, TestClient>::test;
let _something_with_block: let _something_with_block:
fn(&RuntimeApiImpl<Block, TestClient>, &BlockId<Block>, Block) -> Result<Block> = fn(&RuntimeApiImpl<Block, TestClient>, &BlockId<Block>, Block) -> Result<Block, ApiError> =
RuntimeApiImpl::<Block, TestClient>::something_with_block; RuntimeApiImpl::<Block, TestClient>::something_with_block;
#[allow(deprecated)] #[allow(deprecated)]
let _same_name_before_version_2: let _same_name_before_version_2:
fn(&RuntimeApiImpl<Block, TestClient>, &BlockId<Block>) -> Result<String> = fn(&RuntimeApiImpl<Block, TestClient>, &BlockId<Block>) -> Result<String, ApiError> =
RuntimeApiImpl::<Block, TestClient>::same_name_before_version_2; RuntimeApiImpl::<Block, TestClient>::same_name_before_version_2;
} }
#[test] #[test]
fn check_runtime_api_info() { fn check_runtime_api_info() {
assert_eq!(&Api::<Block, Error = ()>::ID, &runtime_decl_for_Api::ID); assert_eq!(&Api::<Block>::ID, &runtime_decl_for_Api::ID);
assert_eq!(Api::<Block, Error = ()>::VERSION, runtime_decl_for_Api::VERSION); assert_eq!(Api::<Block>::VERSION, runtime_decl_for_Api::VERSION);
assert_eq!(Api::<Block, Error = ()>::VERSION, 1); assert_eq!(Api::<Block>::VERSION, 1);
assert_eq!( assert_eq!(
ApiWithCustomVersion::<Block, Error = ()>::VERSION, ApiWithCustomVersion::<Block>::VERSION,
runtime_decl_for_ApiWithCustomVersion::VERSION, runtime_decl_for_ApiWithCustomVersion::VERSION,
); );
assert_eq!( assert_eq!(
&ApiWithCustomVersion::<Block, Error = ()>::ID, &ApiWithCustomVersion::<Block>::ID,
&runtime_decl_for_ApiWithCustomVersion::ID, &runtime_decl_for_ApiWithCustomVersion::ID,
); );
assert_eq!(ApiWithCustomVersion::<Block, Error = ()>::VERSION, 2); assert_eq!(ApiWithCustomVersion::<Block>::VERSION, 2);
} }
fn check_runtime_api_versions_contains<T: RuntimeApiInfo + ?Sized>() { fn check_runtime_api_versions_contains<T: RuntimeApiInfo + ?Sized>() {
@@ -178,9 +177,9 @@ fn check_runtime_api_versions_contains<T: RuntimeApiInfo + ?Sized>() {
#[test] #[test]
fn check_runtime_api_versions() { fn check_runtime_api_versions() {
check_runtime_api_versions_contains::<dyn Api<Block, Error = ()>>(); check_runtime_api_versions_contains::<dyn Api<Block>>();
check_runtime_api_versions_contains::<dyn ApiWithCustomVersion<Block, Error = ()>>(); check_runtime_api_versions_contains::<dyn ApiWithCustomVersion<Block>>();
check_runtime_api_versions_contains::<dyn sp_api::Core<Block, Error = ()>>(); check_runtime_api_versions_contains::<dyn sp_api::Core<Block>>();
} }
#[test] #[test]
@@ -188,9 +187,9 @@ fn mock_runtime_api_has_api() {
let mock = MockApi { block: None }; let mock = MockApi { block: None };
assert!( assert!(
mock.has_api::<dyn ApiWithCustomVersion<Block, Error = ()>>(&BlockId::Number(0)).unwrap(), mock.has_api::<dyn ApiWithCustomVersion<Block>>(&BlockId::Number(0)).unwrap(),
); );
assert!(mock.has_api::<dyn Api<Block, Error = ()>>(&BlockId::Number(0)).unwrap()); assert!(mock.has_api::<dyn Api<Block>>(&BlockId::Number(0)).unwrap());
} }
#[test] #[test]
@@ -209,7 +208,7 @@ fn mock_runtime_api_works_with_advanced() {
Api::<Block>::same_name(&mock, &BlockId::Number(0)).unwrap(); Api::<Block>::same_name(&mock, &BlockId::Number(0)).unwrap();
mock.wild_card(&BlockId::Number(1337), 1).unwrap(); mock.wild_card(&BlockId::Number(1337), 1).unwrap();
assert_eq!( assert_eq!(
ApiError::new("MockApi", ::codec::Error::from("Ohh noooo")), "Test error".to_string(),
mock.wild_card(&BlockId::Number(1336), 1).unwrap_err() mock.wild_card(&BlockId::Number(1336), 1).unwrap_err().to_string(),
); );
} }
@@ -50,10 +50,7 @@ fn calling_wasm_runtime_function() {
} }
#[test] #[test]
#[should_panic( #[should_panic(expected = "FailedToConvertParameter { function: \"fail_convert_parameter\"")]
expected =
"Could not convert parameter `param` between node and runtime: DecodeFails always fails"
)]
fn calling_native_runtime_function_with_non_decodable_parameter() { fn calling_native_runtime_function_with_non_decodable_parameter() {
let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::NativeWhenPossible).build(); let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::NativeWhenPossible).build();
let runtime_api = client.runtime_api(); let runtime_api = client.runtime_api();
@@ -62,7 +59,7 @@ fn calling_native_runtime_function_with_non_decodable_parameter() {
} }
#[test] #[test]
#[should_panic(expected = "Could not convert return value from runtime to node!")] #[should_panic(expected = "FailedToConvertReturnValue { function: \"fail_convert_return_value\"")]
fn calling_native_runtime_function_with_non_decodable_return_value() { fn calling_native_runtime_function_with_non_decodable_return_value() {
let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::NativeWhenPossible).build(); let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::NativeWhenPossible).build();
let runtime_api = client.runtime_api(); let runtime_api = client.runtime_api();
@@ -1,19 +0,0 @@
use substrate_test_runtime_client::runtime::Block;
sp_api::decl_runtime_apis! {
pub trait Api {
fn test(data: u64);
}
}
struct MockApi;
sp_api::mock_impl_runtime_apis! {
impl Api<Block> for MockApi {
type OtherData = u32;
fn test(data: u64) {}
}
}
fn main() {}
@@ -1,5 +0,0 @@
error: Only associated type with name `Error` is allowed
--> $DIR/mock_only_error_associated_type.rs:13:3
|
13 | type OtherData = u32;
| ^^^^
@@ -1,29 +0,0 @@
use substrate_test_runtime_client::runtime::Block;
sp_api::decl_runtime_apis! {
pub trait Api {
fn test(data: u64);
}
pub trait Api2 {
fn test(data: u64);
}
}
struct MockApi;
sp_api::mock_impl_runtime_apis! {
impl Api<Block> for MockApi {
type Error = u32;
fn test(data: u64) {}
}
impl Api2<Block> for MockApi {
type Error = u64;
fn test(data: u64) {}
}
}
fn main() {}
@@ -1,29 +0,0 @@
error: Error type can not change between runtime apis
--> $DIR/mock_only_one_error_type.rs:23:3
|
23 | type Error = u64;
| ^^^^
error: First error type was declared here.
--> $DIR/mock_only_one_error_type.rs:17:16
|
17 | type Error = u32;
| ^^^
error[E0277]: the trait bound `u32: From<sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ApiError>` is not satisfied
--> $DIR/mock_only_one_error_type.rs:17:16
|
17 | type Error = u32;
| ^^^ the trait `From<sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ApiError>` is not implemented for `u32`
|
::: $WORKSPACE/primitives/api/src/lib.rs
|
| type Error: std::fmt::Debug + From<ApiError>;
| -------------- required by this bound in `sp_api_hidden_includes_DECL_RUNTIME_APIS::sp_api::ApiErrorExt::Error`
|
= help: the following implementations were found:
<u32 as From<HttpError>>
<u32 as From<HttpRequestId>>
<u32 as From<HttpRequestStatus>>
<u32 as From<Ipv4Addr>>
and 18 others
+11 -3
View File
@@ -114,8 +114,8 @@ pub enum Error {
#[error("Error decoding call result of {0}")] #[error("Error decoding call result of {0}")]
CallResultDecode(&'static str, #[source] CodecError), CallResultDecode(&'static str, #[source] CodecError),
#[error(transparent)] #[error("Error at calling runtime api: {0}")]
RuntimeApiCodecError(#[from] ApiError), RuntimeApiError(#[from] ApiError),
#[error("Runtime :code missing in storage")] #[error("Runtime :code missing in storage")]
RuntimeCodeMissing, RuntimeCodeMissing,
@@ -153,7 +153,6 @@ pub enum Error {
#[error("Failed to get header for hash {0}")] #[error("Failed to get header for hash {0}")]
MissingHeader(String), MissingHeader(String),
#[error("State Database error: {0}")] #[error("State Database error: {0}")]
StateDatabase(String), StateDatabase(String),
@@ -183,6 +182,15 @@ impl From<Box<dyn sp_state_machine::Error>> for Error {
} }
} }
impl From<Error> for ApiError {
fn from(err: Error) -> ApiError {
match err {
Error::RuntimeApiError(err) => err,
e => ApiError::Application(Box::new(e)),
}
}
}
impl Error { impl Error {
/// Chain a blockchain error. /// Chain a blockchain error.
pub fn from_blockchain(e: Box<Error>) -> Self { pub fn from_blockchain(e: Box<Error>) -> Self {
+1 -1
View File
@@ -34,7 +34,7 @@ pub trait CodeExecutor: Sized + Send + Sync + CallInWasm + Clone + 'static {
/// or an execution error) together with a `bool`, which is true if native execution was used. /// or an execution error) together with a `bool`, which is true if native execution was used.
fn call< fn call<
R: codec::Codec + PartialEq, R: codec::Codec + PartialEq,
NC: FnOnce() -> Result<R, String> + UnwindSafe, NC: FnOnce() -> Result<R, Box<dyn std::error::Error + Send + Sync>> + UnwindSafe,
>( >(
&self, &self,
ext: &mut dyn Externalities, ext: &mut dyn Externalities,
+1 -1
View File
@@ -113,7 +113,7 @@ pub fn generate_initial_session_keys<Block, T>(
client: std::sync::Arc<T>, client: std::sync::Arc<T>,
at: &BlockId<Block>, at: &BlockId<Block>,
seeds: Vec<String>, seeds: Vec<String>,
) -> Result<(), sp_api::ApiErrorFor<T, Block>> ) -> Result<(), sp_api::ApiError>
where where
Block: BlockT, Block: BlockT,
T: ProvideRuntimeApi<Block>, T: ProvideRuntimeApi<Block>,
@@ -392,7 +392,7 @@ mod execution {
bool, bool,
) where ) where
R: Decode + Encode + PartialEq, R: Decode + Encode + PartialEq,
NC: FnOnce() -> result::Result<R, String> + UnwindSafe, NC: FnOnce() -> result::Result<R, Box<dyn std::error::Error + Send + Sync>> + UnwindSafe,
{ {
let mut cache = StorageTransactionCache::default(); let mut cache = StorageTransactionCache::default();
@@ -449,7 +449,7 @@ mod execution {
) -> CallResult<R, Exec::Error> ) -> CallResult<R, Exec::Error>
where where
R: Decode + Encode + PartialEq, R: Decode + Encode + PartialEq,
NC: FnOnce() -> result::Result<R, String> + UnwindSafe, NC: FnOnce() -> result::Result<R, Box<dyn std::error::Error + Send + Sync>> + UnwindSafe,
Handler: FnOnce( Handler: FnOnce(
CallResult<R, Exec::Error>, CallResult<R, Exec::Error>,
CallResult<R, Exec::Error>, CallResult<R, Exec::Error>,
@@ -485,7 +485,7 @@ mod execution {
) -> CallResult<R, Exec::Error> ) -> CallResult<R, Exec::Error>
where where
R: Decode + Encode + PartialEq, R: Decode + Encode + PartialEq,
NC: FnOnce() -> result::Result<R, String> + UnwindSafe, NC: FnOnce() -> result::Result<R, Box<dyn std::error::Error + Send + Sync>> + UnwindSafe,
{ {
self.overlay.start_transaction(); self.overlay.start_transaction();
let (result, was_native) = self.execute_aux( let (result, was_native) = self.execute_aux(
@@ -522,7 +522,7 @@ mod execution {
) -> Result<NativeOrEncoded<R>, Box<dyn Error>> ) -> Result<NativeOrEncoded<R>, Box<dyn Error>>
where where
R: Decode + Encode + PartialEq, R: Decode + Encode + PartialEq,
NC: FnOnce() -> result::Result<R, String> + UnwindSafe, NC: FnOnce() -> result::Result<R, Box<dyn std::error::Error + Send + Sync>> + UnwindSafe,
Handler: FnOnce( Handler: FnOnce(
CallResult<R, Exec::Error>, CallResult<R, Exec::Error>,
CallResult<R, Exec::Error>, CallResult<R, Exec::Error>,
@@ -869,7 +869,7 @@ mod tests {
map, traits::{Externalities, RuntimeCode}, testing::TaskExecutor, map, traits::{Externalities, RuntimeCode}, testing::TaskExecutor,
}; };
use sp_runtime::traits::BlakeTwo256; use sp_runtime::traits::BlakeTwo256;
use std::{result, collections::HashMap}; use std::{result, collections::HashMap, panic::UnwindSafe};
use codec::Decode; use codec::Decode;
use sp_core::{ use sp_core::{
storage::ChildInfo, NativeOrEncoded, NeverNativeValue, storage::ChildInfo, NativeOrEncoded, NeverNativeValue,
@@ -891,7 +891,7 @@ mod tests {
fn call< fn call<
R: Encode + Decode + PartialEq, R: Encode + Decode + PartialEq,
NC: FnOnce() -> result::Result<R, String>, NC: FnOnce() -> result::Result<R, Box<dyn std::error::Error + Send + Sync>> + UnwindSafe,
>( >(
&self, &self,
ext: &mut dyn Externalities, ext: &mut dyn Externalities,
@@ -43,7 +43,7 @@ pub trait BlockBuilderExt {
impl<'a, A, B> BlockBuilderExt for sc_block_builder::BlockBuilder<'a, substrate_test_runtime::Block, A, B> where impl<'a, A, B> BlockBuilderExt for sc_block_builder::BlockBuilder<'a, substrate_test_runtime::Block, A, B> where
A: ProvideRuntimeApi<substrate_test_runtime::Block> + 'a, A: ProvideRuntimeApi<substrate_test_runtime::Block> + 'a,
A::Api: BlockBuilderApi<substrate_test_runtime::Block, Error = sp_blockchain::Error> + A::Api: BlockBuilderApi<substrate_test_runtime::Block> +
ApiExt< ApiExt<
substrate_test_runtime::Block, substrate_test_runtime::Block,
StateBackend = backend::StateBackendFor<B, substrate_test_runtime::Block> StateBackend = backend::StateBackendFor<B, substrate_test_runtime::Block>