mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 23:21:02 +00:00
Authoring with WASM runtime
This commit is contained in:
+57
-56
@@ -18,47 +18,55 @@
|
||||
|
||||
use client::backend::LocalBackend;
|
||||
use client::block_builder::BlockBuilder as ClientBlockBuilder;
|
||||
use client::{Client, LocalCallExecutor};
|
||||
use client::{self, Client, LocalCallExecutor, CallExecutor};
|
||||
use codec::{Encode, Decode};
|
||||
use polkadot_executor::Executor as LocalDispatch;
|
||||
use substrate_executor::NativeExecutor;
|
||||
use state_machine;
|
||||
|
||||
use runtime::Address;
|
||||
use runtime_primitives::traits::AuxLookup;
|
||||
use primitives::{
|
||||
AccountId, Block, Header, BlockId, Hash, Index, InherentData,
|
||||
SessionKey, Timestamp, UncheckedExtrinsic,
|
||||
};
|
||||
use primitives::parachain::{DutyRoster, Id as ParaId};
|
||||
use substrate_primitives::{KeccakHasher, RlpCodec};
|
||||
use {BlockBuilder, PolkadotApi, LocalPolkadotApi, Error, ErrorKind, Result};
|
||||
|
||||
use {BlockBuilder, PolkadotApi, LocalPolkadotApi, ErrorKind, Error, Result};
|
||||
|
||||
// set up the necessary scaffolding to execute a set of calls to the runtime.
|
||||
// this creates a new block on top of the given ID and initialises it.
|
||||
macro_rules! with_runtime {
|
||||
($client: ident, $at: expr, $exec: expr) => {{
|
||||
let parent = $at;
|
||||
let header = Header {
|
||||
parent_hash: $client.block_hash_from_id(&parent)?
|
||||
.ok_or_else(|| ErrorKind::UnknownBlock(format!("{:?}", parent)))?,
|
||||
number: $client.block_number_from_id(&parent)?
|
||||
fn call<B, R>(client: &Client<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>, Block>, at: &BlockId, method: &'static str, input: &[u8]) -> Result<R>
|
||||
where
|
||||
R: Decode,
|
||||
B: LocalBackend<Block, KeccakHasher, RlpCodec>,
|
||||
{
|
||||
let parent = at;
|
||||
let header = Header {
|
||||
parent_hash: client.block_hash_from_id(&parent)?
|
||||
.ok_or_else(|| ErrorKind::UnknownBlock(format!("{:?}", parent)))?,
|
||||
number: client.block_number_from_id(&parent)?
|
||||
.ok_or_else(|| ErrorKind::UnknownBlock(format!("{:?}", parent)))? + 1,
|
||||
state_root: Default::default(),
|
||||
extrinsics_root: Default::default(),
|
||||
digest: Default::default(),
|
||||
};
|
||||
|
||||
$client.state_at(&parent).map_err(Error::from).and_then(|state| {
|
||||
let mut changes = Default::default();
|
||||
let mut ext = state_machine::Ext::new(&mut changes, &state);
|
||||
|
||||
::substrate_executor::with_native_environment(&mut ext, || {
|
||||
::runtime::Executive::initialise_block(&header);
|
||||
($exec)()
|
||||
}).map_err(Into::into)
|
||||
})
|
||||
}}
|
||||
state_root: Default::default(),
|
||||
extrinsics_root: Default::default(),
|
||||
digest: Default::default(),
|
||||
};
|
||||
client.state_at(&parent).map_err(Error::from).and_then(|state| {
|
||||
let mut overlay = Default::default();
|
||||
client.executor().call_at_state(
|
||||
&state,
|
||||
&mut overlay,
|
||||
"initialise_block",
|
||||
&header.encode(),
|
||||
state_machine::native_when_possible()
|
||||
)?;
|
||||
let (r, _) = client.executor().call_at_state(
|
||||
&state,
|
||||
&mut overlay,
|
||||
method,
|
||||
input,
|
||||
state_machine::native_when_possible()
|
||||
)?;
|
||||
Ok(R::decode(&mut &r[..])
|
||||
.ok_or_else(|| client::error::Error::from(client::error::ErrorKind::CallResultDecode(method)))?)
|
||||
})
|
||||
}
|
||||
|
||||
impl<B: LocalBackend<Block, KeccakHasher, RlpCodec>> BlockBuilder for ClientBlockBuilder<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>, Block, KeccakHasher, RlpCodec> {
|
||||
@@ -76,37 +84,29 @@ impl<B: LocalBackend<Block, KeccakHasher, RlpCodec>> PolkadotApi for Client<B, L
|
||||
type BlockBuilder = ClientBlockBuilder<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>, Block, KeccakHasher, RlpCodec>;
|
||||
|
||||
fn session_keys(&self, at: &BlockId) -> Result<Vec<SessionKey>> {
|
||||
with_runtime!(self, at, ::runtime::Consensus::authorities)
|
||||
Ok(self.authorities_at(at)?)
|
||||
}
|
||||
|
||||
fn validators(&self, at: &BlockId) -> Result<Vec<AccountId>> {
|
||||
with_runtime!(self, at, ::runtime::Session::validators)
|
||||
call(self, at, "validators", &[])
|
||||
}
|
||||
|
||||
fn random_seed(&self, at: &BlockId) -> Result<Hash> {
|
||||
with_runtime!(self, at, ::runtime::System::random_seed)
|
||||
call(self, at, "random_seed", &[])
|
||||
}
|
||||
|
||||
fn duty_roster(&self, at: &BlockId) -> Result<DutyRoster> {
|
||||
with_runtime!(self, at, ::runtime::Parachains::calculate_duty_roster)
|
||||
call(self, at, "duty_roster", &[])
|
||||
}
|
||||
|
||||
fn timestamp(&self, at: &BlockId) -> Result<Timestamp> {
|
||||
with_runtime!(self, at, ::runtime::Timestamp::get)
|
||||
call(self, at, "timestamp", &[])
|
||||
}
|
||||
|
||||
fn evaluate_block(&self, at: &BlockId, block: Block) -> Result<bool> {
|
||||
use substrate_executor::error::ErrorKind as ExecErrorKind;
|
||||
use codec::{Decode, Encode};
|
||||
use runtime::Block as RuntimeBlock;
|
||||
|
||||
let encoded = block.encode();
|
||||
let runtime_block = match RuntimeBlock::decode(&mut &encoded[..]) {
|
||||
Some(x) => x,
|
||||
None => return Ok(false),
|
||||
};
|
||||
|
||||
let res = with_runtime!(self, at, || ::runtime::Executive::execute_block(runtime_block));
|
||||
let res: Result<()> = call(self, at, "execute_block", &encoded);
|
||||
match res {
|
||||
Ok(()) => Ok(true),
|
||||
Err(err) => match err.kind() {
|
||||
@@ -117,23 +117,31 @@ impl<B: LocalBackend<Block, KeccakHasher, RlpCodec>> PolkadotApi for Client<B, L
|
||||
}
|
||||
|
||||
fn index(&self, at: &BlockId, account: AccountId) -> Result<Index> {
|
||||
with_runtime!(self, at, || ::runtime::System::account_nonce(account))
|
||||
account.using_encoded(|encoded| {
|
||||
call(self, at, "account_nonce", encoded)
|
||||
})
|
||||
}
|
||||
|
||||
fn lookup(&self, at: &BlockId, address: Address) -> Result<Option<AccountId>> {
|
||||
with_runtime!(self, at, || <::runtime::Staking as AuxLookup>::lookup(address).ok())
|
||||
address.using_encoded(|encoded| {
|
||||
call(self, at, "lookup_address", encoded)
|
||||
})
|
||||
}
|
||||
|
||||
fn active_parachains(&self, at: &BlockId) -> Result<Vec<ParaId>> {
|
||||
with_runtime!(self, at, ::runtime::Parachains::active_parachains)
|
||||
call(self, at, "active_parachains", &[])
|
||||
}
|
||||
|
||||
fn parachain_code(&self, at: &BlockId, parachain: ParaId) -> Result<Option<Vec<u8>>> {
|
||||
with_runtime!(self, at, || ::runtime::Parachains::parachain_code(parachain))
|
||||
parachain.using_encoded(|encoded| {
|
||||
call(self, at, "parachain_code", encoded)
|
||||
})
|
||||
}
|
||||
|
||||
fn parachain_head(&self, at: &BlockId, parachain: ParaId) -> Result<Option<Vec<u8>>> {
|
||||
with_runtime!(self, at, || ::runtime::Parachains::parachain_head(parachain))
|
||||
parachain.using_encoded(|encoded| {
|
||||
call(self, at, "parachain_head", encoded)
|
||||
})
|
||||
}
|
||||
|
||||
fn build_block(&self, at: &BlockId, inherent_data: InherentData) -> Result<Self::BlockBuilder> {
|
||||
@@ -146,15 +154,8 @@ impl<B: LocalBackend<Block, KeccakHasher, RlpCodec>> PolkadotApi for Client<B, L
|
||||
}
|
||||
|
||||
fn inherent_extrinsics(&self, at: &BlockId, inherent_data: InherentData) -> Result<Vec<UncheckedExtrinsic>> {
|
||||
use codec::{Encode, Decode};
|
||||
|
||||
with_runtime!(self, at, || {
|
||||
let extrinsics = ::runtime::inherent_extrinsics(inherent_data);
|
||||
extrinsics.into_iter()
|
||||
.map(|x| x.encode()) // get encoded representation
|
||||
.map(|x| Decode::decode(&mut &x[..])) // get byte-vec equivalent to extrinsic
|
||||
.map(|x| x.expect("UncheckedExtrinsic has encoded representation equivalent to Vec<u8>; qed"))
|
||||
.collect()
|
||||
inherent_data.using_encoded(|encoded| {
|
||||
call(self, at, "inherent_extrinsics", encoded)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user