Make runtime api calls native when possible (#1302)

* Add simple benchmark for the runtime api

* Make the executor support native calls

* Some documentation

* Hide behind `feature = "std"`

* Rework the native calls

* Make all tests compile again

* Make every parameter using the Block serialized/deserialized in the native call

* Forward `UnwindSafe` requirement

* Remove debug stuff

* Add some documentation

* Fixes warnings

* Fixes errors after master rebase

* Fixes compilation after master rebase

* Fixes compilation after rebase
This commit is contained in:
Bastian Köcher
2019-01-21 14:32:53 +01:00
committed by Gav Wood
parent f0dbcf5401
commit 010e63116f
37 changed files with 1152 additions and 363 deletions
+39 -23
View File
@@ -16,25 +16,29 @@
//! Substrate Client
use std::{marker::PhantomData, collections::{HashSet, BTreeMap}, sync::Arc};
use std::{marker::PhantomData, collections::{HashSet, BTreeMap}, sync::Arc, panic::UnwindSafe};
use crate::error::Error;
use futures::sync::mpsc;
use parking_lot::{Mutex, RwLock};
use primitives::NativeOrEncoded;
use runtime_primitives::{
Justification,
generic::{BlockId, SignedBlock},
};
use consensus::{Error as ConsensusError, ErrorKind as ConsensusErrorKind, ImportBlock, ImportResult, BlockOrigin, ForkChoiceStrategy};
use consensus::{
Error as ConsensusError, ErrorKind as ConsensusErrorKind, ImportBlock, ImportResult,
BlockOrigin, ForkChoiceStrategy
};
use runtime_primitives::traits::{
Block as BlockT, Header as HeaderT, Zero, As, NumberFor, CurrentHeight, BlockNumberToHash,
ApiRef, ProvideRuntimeApi, Digest, DigestItem, AuthorityIdFor
};
use runtime_primitives::BuildStorage;
use crate::runtime_api::{Core as CoreAPI, CallRuntimeAt, ConstructRuntimeApi};
use primitives::{Blake2Hasher, H256, ChangesTrieConfiguration, convert_hash};
use crate::runtime_api::{CallRuntimeAt, ConstructRuntimeApi};
use primitives::{Blake2Hasher, H256, ChangesTrieConfiguration, convert_hash, NeverNativeValue};
use primitives::storage::{StorageKey, StorageData};
use primitives::storage::well_known_keys;
use codec::Decode;
use codec::{Encode, Decode};
use state_machine::{
DBValue, Backend as StateBackend, CodeExecutor, ChangesTrieAnchorBlockId,
ExecutionStrategy, ExecutionManager, prove_read,
@@ -557,7 +561,9 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
&self
) -> error::Result<block_builder::BlockBuilder<Block, InherentData, Self>> where
E: Clone + Send + Sync,
RA: BlockBuilderAPI<Block, InherentData>
RA: Send + Sync,
Self: ProvideRuntimeApi,
<Self as ProvideRuntimeApi>::Api: BlockBuilderAPI<Block, InherentData>
{
block_builder::BlockBuilder::new(self)
}
@@ -567,7 +573,9 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
&self, parent: &BlockId<Block>
) -> error::Result<block_builder::BlockBuilder<Block, InherentData, Self>> where
E: Clone + Send + Sync,
RA: BlockBuilderAPI<Block, InherentData>
RA: Send + Sync,
Self: ProvideRuntimeApi,
<Self as ProvideRuntimeApi>::Api: BlockBuilderAPI<Block, InherentData>
{
block_builder::BlockBuilder::at_block(parent, &self)
}
@@ -615,7 +623,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
let (storage_update, changes_update, storage_changes) = match transaction.state()? {
Some(transaction_state) => {
let mut overlay = Default::default();
let r = self.executor.call_at_state(
let r = self.executor.call_at_state::<_, _, NeverNativeValue, fn() -> NeverNativeValue>(
transaction_state,
&mut overlay,
"Core_execute_block",
@@ -638,6 +646,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
wasm_result
}),
},
None,
);
let (_, storage_update, changes_update) = r?;
overlay.commit_prospective();
@@ -1017,30 +1026,29 @@ impl<B, E, Block, RA> ProvideRuntimeApi for Client<B, E, Block, RA> where
B: backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Clone + Send + Sync,
Block: BlockT<Hash=H256>,
RA: CoreAPI<Block>
RA: ConstructRuntimeApi<Block, Self>
{
type Api = RA;
type Api = <RA as ConstructRuntimeApi<Block, Self>>::RuntimeApi;
fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api> {
Self::Api::construct_runtime_api(self)
RA::construct_runtime_api(self)
}
}
impl<B, E, Block, RA> CallRuntimeAt<Block> for Client<B, E, Block, RA> where
B: backend::Backend<Block, Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher> + Clone + Send + Sync,
Block: BlockT<Hash=H256>,
RA: CoreAPI<Block>, // not strictly necessary at the moment
// but we want to bound to make sure the API is actually available.
Block: BlockT<Hash=H256>
{
fn call_api_at(
fn call_api_at<R: Encode + Decode + PartialEq, NC: FnOnce() -> R + UnwindSafe>(
&self,
at: &BlockId<Block>,
function: &'static str,
args: Vec<u8>,
changes: &mut OverlayedChanges,
initialised_block: &mut Option<BlockId<Block>>,
) -> error::Result<Vec<u8>> {
native_call: Option<NC>,
) -> error::Result<NativeOrEncoded<R>> {
let execution_manager = match self.api_execution_strategy {
ExecutionStrategy::NativeWhenPossible => ExecutionManager::NativeWhenPossible,
ExecutionStrategy::AlwaysWasm => ExecutionManager::AlwaysWasm,
@@ -1053,8 +1061,16 @@ impl<B, E, Block, RA> CallRuntimeAt<Block> for Client<B, E, Block, RA> where
}),
};
self.executor.contextual_call(at, function, &args, changes, initialised_block,
|| self.prepare_environment_block(at), execution_manager)
self.executor.contextual_call(
at,
function,
&args,
changes,
initialised_block,
|| self.prepare_environment_block(at),
execution_manager,
native_call,
)
}
fn runtime_version_at(&self, at: &BlockId<Block>) -> error::Result<RuntimeVersion> {
@@ -1268,7 +1284,7 @@ pub(crate) mod tests {
use consensus::BlockOrigin;
use test_client::client::{backend::Backend as TestBackend, runtime_api::ApiExt};
use test_client::BlockBuilderExt;
use test_client::runtime::{self, Block, Transfer, RuntimeApi, test_api::TestAPI};
use test_client::runtime::{self, Block, Transfer, RuntimeApi, TestAPI};
/// Returns tuple, consisting of:
/// 1) test client pre-filled with blocks changing balances;
@@ -1350,14 +1366,14 @@ pub(crate) mod tests {
assert_eq!(
client.runtime_api().balance_of(
&BlockId::Number(client.info().unwrap().chain.best_number),
&Keyring::Alice.to_raw_public().into()
Keyring::Alice.to_raw_public().into()
).unwrap(),
1000
);
assert_eq!(
client.runtime_api().balance_of(
&BlockId::Number(client.info().unwrap().chain.best_number),
&Keyring::Ferdie.to_raw_public().into()
Keyring::Ferdie.to_raw_public().into()
).unwrap(),
0
);
@@ -1417,14 +1433,14 @@ pub(crate) mod tests {
assert_eq!(
client.runtime_api().balance_of(
&BlockId::Number(client.info().unwrap().chain.best_number),
&Keyring::Alice.to_raw_public().into()
Keyring::Alice.to_raw_public().into()
).unwrap(),
958
);
assert_eq!(
client.runtime_api().balance_of(
&BlockId::Number(client.info().unwrap().chain.best_number),
&Keyring::Ferdie.to_raw_public().into()
Keyring::Ferdie.to_raw_public().into()
).unwrap(),
42
);