mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-29 21:57:55 +00:00
c5e68a7b9b
* Genric over hasher * WIP start adding NodeCodec * Add codec to TrieBackend * Typechecks * Fix error type * Cleanup * Tests build (and fail) * Fix tests: don't use MemoryDB::default() * Lockfile * Address grumbles * Teach environmental! about generics * Add Finder artifacts * whitespace * Add a toy impl of Hasher and plug it in to Externalities * Use `uint` and `fixed-hash` from `parity-common` Remove unused U512 Add test to ensure H256 impls heapsizeof * lock file updates * Make hashes Encodable/Decodable * lock file updates * Impl FromIterator for TestExternalities so we can collect() and use map! * Use rustc-hex from crates Use rlp from master so dependencies do not mess up the scope * Fix tests in runtime-io * lockfile shenanigans * Add a BlakeHasher impl * Use BlakeHasher in runtime-io * lockfile updates * ws * Add a Blake2/RLP-flavoured NodeCodec * Use Blake-flavoured Hasher and NodeCodec * lockfile * Implement PartialEq and Default for TestExternalities * Add note about limitations of environmental! * Make it compile, but this is probably broken * Derive Debug so tests in executor can work * Make executor use BlakeHasher * ws * WIP make client generic * typechecks * cleanup * client tests pass * Fix client/db * cleanup * Fix network * Fix rpc * Fix service * Make TestExternalities work better au lieu d'un HashMap * Fix tests in council * Fix tests in contract * Fix tests in council * Fix democracy * Add comment about odd-looking reexports in tests * Don't need to load branch * Fix staking * Fix session * Some polkadot fixes and lockfile * Fix executive * fixup lockfile * Fix polkadot/api * Fix polkadot/service * Fix polkadot/runtime tests * Fix tests in test-runtime * Test fixes * Fix missing component in the `std` feature * Use PhantomData and Result from core * Fix paths Use core * load heapsize on wasm * implement `HeapSizeOf` for wasm * Add toy impl of `blake2_256` for no_std * lockfile * Use kvdb* from parity-common and fix errors * rebuilt lockfile * Add dummy impl of `on_advance_round` for rhododendron::Context * Fix build after merge * Add HeapSizeOf bound where needed * Sort out dependencies for no_std * Add HeapSizeOf bound where needed * use temp branch pending PR merges * Remove unneeded tests * Lock file and wasm artifacts * lockfile * Use magic commit for libp2p * Cleanup * Implement blake2_256 for no_std * Back on parity-common master * missing type params * Update Cargo.lock * whitespace * Rename concrete Rlp node codec "RlpCodec" and use everywhere Implement a Keccak-flavoured Rlp NodeCodec and use everywhere Add a KeccakHasher * Switch to use KeccakHasher * Lock file and runtimes * fixup lockfile * Fix outstanding issue using concrete types (thanks @gnunicorn) * Cleanup * More cleanup * Comment out Blake2 Hasher * implement ext_keccak256 * Address todo: FetchChecker is generic * all tests passing
264 lines
8.5 KiB
Rust
264 lines
8.5 KiB
Rust
// Copyright 2017 Parity Technologies (UK) Ltd.
|
|
// This file is part of Polkadot.
|
|
|
|
// Polkadot is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
|
|
// Polkadot is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
//! Strongly typed API for full Polkadot client.
|
|
|
|
use client::backend::LocalBackend;
|
|
use client::block_builder::BlockBuilder as ClientBlockBuilder;
|
|
use client::{Client, LocalCallExecutor};
|
|
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, 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)?
|
|
.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)
|
|
})
|
|
}}
|
|
}
|
|
|
|
impl<B: LocalBackend<Block, KeccakHasher, RlpCodec>> BlockBuilder for ClientBlockBuilder<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>, Block, KeccakHasher, RlpCodec> {
|
|
fn push_extrinsic(&mut self, extrinsic: UncheckedExtrinsic) -> Result<()> {
|
|
self.push(extrinsic).map_err(Into::into)
|
|
}
|
|
|
|
/// Bake the block with provided extrinsics.
|
|
fn bake(self) -> Result<Block> {
|
|
ClientBlockBuilder::bake(self).map_err(Into::into)
|
|
}
|
|
}
|
|
|
|
impl<B: LocalBackend<Block, KeccakHasher, RlpCodec>> PolkadotApi for Client<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>, Block> {
|
|
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)
|
|
}
|
|
|
|
fn validators(&self, at: &BlockId) -> Result<Vec<AccountId>> {
|
|
with_runtime!(self, at, ::runtime::Session::validators)
|
|
}
|
|
|
|
fn random_seed(&self, at: &BlockId) -> Result<Hash> {
|
|
with_runtime!(self, at, ::runtime::System::random_seed)
|
|
}
|
|
|
|
fn duty_roster(&self, at: &BlockId) -> Result<DutyRoster> {
|
|
with_runtime!(self, at, ::runtime::Parachains::calculate_duty_roster)
|
|
}
|
|
|
|
fn timestamp(&self, at: &BlockId) -> Result<Timestamp> {
|
|
with_runtime!(self, at, ::runtime::Timestamp::get)
|
|
}
|
|
|
|
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));
|
|
match res {
|
|
Ok(()) => Ok(true),
|
|
Err(err) => match err.kind() {
|
|
&ErrorKind::Executor(ExecErrorKind::Runtime) => Ok(false),
|
|
_ => Err(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
fn index(&self, at: &BlockId, account: AccountId) -> Result<Index> {
|
|
with_runtime!(self, at, || ::runtime::System::account_nonce(account))
|
|
}
|
|
|
|
fn lookup(&self, at: &BlockId, address: Address) -> Result<Option<AccountId>> {
|
|
with_runtime!(self, at, || <::runtime::Staking as AuxLookup>::lookup(address).ok())
|
|
}
|
|
|
|
fn active_parachains(&self, at: &BlockId) -> Result<Vec<ParaId>> {
|
|
with_runtime!(self, at, ::runtime::Parachains::active_parachains)
|
|
}
|
|
|
|
fn parachain_code(&self, at: &BlockId, parachain: ParaId) -> Result<Option<Vec<u8>>> {
|
|
with_runtime!(self, at, || ::runtime::Parachains::parachain_code(parachain))
|
|
}
|
|
|
|
fn parachain_head(&self, at: &BlockId, parachain: ParaId) -> Result<Option<Vec<u8>>> {
|
|
with_runtime!(self, at, || ::runtime::Parachains::parachain_head(parachain))
|
|
}
|
|
|
|
fn build_block(&self, at: &BlockId, inherent_data: InherentData) -> Result<Self::BlockBuilder> {
|
|
let mut block_builder = self.new_block_at(at)?;
|
|
for inherent in self.inherent_extrinsics(at, inherent_data)? {
|
|
block_builder.push(inherent)?;
|
|
}
|
|
|
|
Ok(block_builder)
|
|
}
|
|
|
|
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()
|
|
})
|
|
}
|
|
}
|
|
|
|
impl<B: LocalBackend<Block, KeccakHasher, RlpCodec>> LocalPolkadotApi for Client<B, LocalCallExecutor<B, NativeExecutor<LocalDispatch>>, Block>
|
|
{}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use keyring::Keyring;
|
|
use client::LocalCallExecutor;
|
|
use client::in_mem::Backend as InMemory;
|
|
use substrate_executor::NativeExecutionDispatch;
|
|
use runtime::{GenesisConfig, ConsensusConfig, SessionConfig};
|
|
|
|
fn validators() -> Vec<AccountId> {
|
|
vec![
|
|
Keyring::One.to_raw_public().into(),
|
|
Keyring::Two.to_raw_public().into(),
|
|
]
|
|
}
|
|
|
|
fn session_keys() -> Vec<SessionKey> {
|
|
vec![
|
|
Keyring::One.to_raw_public().into(),
|
|
Keyring::Two.to_raw_public().into(),
|
|
]
|
|
}
|
|
|
|
fn client() -> Client<InMemory<Block, KeccakHasher, RlpCodec>, LocalCallExecutor<InMemory<Block, KeccakHasher, RlpCodec>, NativeExecutor<LocalDispatch>>, Block> {
|
|
let genesis_config = GenesisConfig {
|
|
consensus: Some(ConsensusConfig {
|
|
code: LocalDispatch::native_equivalent().to_vec(),
|
|
authorities: session_keys(),
|
|
}),
|
|
system: None,
|
|
session: Some(SessionConfig {
|
|
validators: validators(),
|
|
session_length: 100,
|
|
broken_percent_late: 100,
|
|
}),
|
|
council: Some(Default::default()),
|
|
democracy: Some(Default::default()),
|
|
parachains: Some(Default::default()),
|
|
staking: Some(Default::default()),
|
|
timestamp: Some(Default::default()),
|
|
};
|
|
|
|
::client::new_in_mem(LocalDispatch::with_heap_pages(8), genesis_config).unwrap()
|
|
}
|
|
|
|
#[test]
|
|
fn gets_session_and_validator_keys() {
|
|
let client = client();
|
|
let id = BlockId::number(0);
|
|
assert_eq!(client.session_keys(&id).unwrap(), session_keys());
|
|
assert_eq!(client.validators(&id).unwrap(), validators());
|
|
}
|
|
|
|
#[test]
|
|
fn build_block_implicit_succeeds() {
|
|
let client = client();
|
|
|
|
let id = BlockId::number(0);
|
|
let block_builder = client.build_block(&id, InherentData {
|
|
timestamp: 1_000_000,
|
|
parachain_heads: Vec::new(),
|
|
offline_indices: Vec::new(),
|
|
}).unwrap();
|
|
let block = block_builder.bake().unwrap();
|
|
|
|
assert_eq!(block.header.number, 1);
|
|
assert!(block.header.extrinsics_root != Default::default());
|
|
}
|
|
|
|
#[test]
|
|
fn build_block_with_inherent_succeeds() {
|
|
let client = client();
|
|
|
|
let id = BlockId::number(0);
|
|
let inherent = client.inherent_extrinsics(&id, InherentData {
|
|
timestamp: 1_000_000,
|
|
parachain_heads: Vec::new(),
|
|
offline_indices: Vec::new(),
|
|
}).unwrap();
|
|
|
|
let mut block_builder = client.new_block_at(&id).unwrap();
|
|
for extrinsic in inherent {
|
|
block_builder.push(extrinsic).unwrap();
|
|
}
|
|
|
|
let block = block_builder.bake().unwrap();
|
|
|
|
assert_eq!(block.header.number, 1);
|
|
assert!(block.header.extrinsics_root != Default::default());
|
|
}
|
|
|
|
#[test]
|
|
fn gets_random_seed_with_genesis() {
|
|
let client = client();
|
|
|
|
let id = BlockId::number(0);
|
|
assert!(client.random_seed(&id).is_ok());
|
|
}
|
|
}
|