mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-12 13:25:41 +00:00
Additional runtime tests for the test-runtime (#69)
* Remove rustc dependency from ed25519 and refactor a little. * Runtime support provides more extensive test-key functionality. * Additional APIs for ed25519 stuff. * Extensive test for test-runtime. * Fixes for the new test key API. * Additional convenience for tests * Take advantage of more convenient API. * Redo formating. * Remove old test identities. * Remove boilerplate, add test. * Refactor out unneeded code. * Clean up algo for determining authorities. * Remove unneeded API. * Make `to_*` consume * Only export keyring when testing * Fix build & warning * Extract Keyring into separate library. * Add tests for Keyring and a trait-based API. * Address grumbles.
This commit is contained in:
committed by
Robert Habermeier
parent
72fa8f3fe2
commit
f344e15bf8
@@ -17,3 +17,4 @@ substrate-runtime-support = { path = "../runtime-support" }
|
||||
substrate-serializer = { path = "../serializer" }
|
||||
substrate-state-machine = { path = "../state-machine" }
|
||||
substrate-test-runtime = { path = "../test-runtime" }
|
||||
substrate-keyring = { path = "../../substrate/keyring" }
|
||||
|
||||
@@ -21,7 +21,7 @@ use error;
|
||||
use primitives::block;
|
||||
use blockchain::{self, BlockId};
|
||||
|
||||
/// Block insertion transction. Keeps hold if the inseted block state and data.
|
||||
/// Block insertion transction. Keeps hold if the inserted block state and data.
|
||||
pub trait BlockImportOperation {
|
||||
/// Associated state backend type.
|
||||
type State: state_machine::backend::Backend;
|
||||
|
||||
@@ -45,6 +45,18 @@ error_chain! {
|
||||
description("Blockchain error"),
|
||||
display("Blockchain: {}", e),
|
||||
}
|
||||
|
||||
/// Invalid state data.
|
||||
AuthLen {
|
||||
description("authority count state error"),
|
||||
display("Current state of blockchain has invalid authority count value"),
|
||||
}
|
||||
|
||||
/// Invalid state data.
|
||||
Auth(i: u32) {
|
||||
description("authority value state error"),
|
||||
display("Current state of blockchain has invalid authority value for index {}", i),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,49 +40,23 @@ pub fn construct_genesis_block(storage: &HashMap<Vec<u8>, Vec<u8>>) -> Block {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use codec::{Slicable, Joiner};
|
||||
use runtime_support::{one, two, Hashable};
|
||||
use runtime_support::Hashable;
|
||||
use keyring::Keyring;
|
||||
use test_runtime::genesismap::{GenesisConfig, additional_storage_with_genesis};
|
||||
use executor::{NativeExecutionDispatch, NativeExecutor, WasmExecutor, with_native_environment,
|
||||
error};
|
||||
use state_machine::{execute, Externalities, OverlayedChanges};
|
||||
use executor::WasmExecutor;
|
||||
use state_machine::{execute, OverlayedChanges};
|
||||
use state_machine::backend::InMemory;
|
||||
use test_runtime::{self, AccountId, Hash, Block, BlockNumber, Header, Digest, Transaction,
|
||||
use test_runtime::{self, Hash, Block, BlockNumber, Header, Digest, Transaction,
|
||||
UncheckedTransaction};
|
||||
use ed25519::Pair;
|
||||
use ed25519::{Public, Pair};
|
||||
|
||||
/// A null struct which implements `NativeExecutionDispatch` feeding in the hard-coded runtime.
|
||||
pub struct LocalNativeExecutionDispatch;
|
||||
|
||||
impl NativeExecutionDispatch for LocalNativeExecutionDispatch {
|
||||
fn native_equivalent() -> &'static [u8] {
|
||||
// WARNING!!! This assumes that the runtime was built *before* the main project. Until we
|
||||
// get a proper build script, this must be strictly adhered to or things will go wrong.
|
||||
include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm")
|
||||
}
|
||||
|
||||
fn dispatch(ext: &mut Externalities, method: &str, data: &[u8]) -> error::Result<Vec<u8>> {
|
||||
with_native_environment(ext, move || test_runtime::apis::dispatch(method, data))?
|
||||
.ok_or_else(|| error::ErrorKind::MethodNotFound(method.to_owned()).into())
|
||||
}
|
||||
}
|
||||
|
||||
fn executor() -> NativeExecutor<LocalNativeExecutionDispatch> {
|
||||
NativeExecutor { _dummy: Default::default() }
|
||||
}
|
||||
|
||||
fn secret_for(who: &AccountId) -> Option<Pair> {
|
||||
match who {
|
||||
x if *x == one() => Some(Pair::from_seed(b"12345678901234567890123456789012")),
|
||||
x if *x == two() => Some("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60".into()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
native_executor_instance!(Executor, test_runtime::api::dispatch, include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm"));
|
||||
|
||||
fn construct_block(backend: &InMemory, number: BlockNumber, parent_hash: Hash, state_root: Hash, txs: Vec<Transaction>) -> (Vec<u8>, Hash) {
|
||||
use triehash::ordered_trie_root;
|
||||
|
||||
let transactions = txs.into_iter().map(|tx| {
|
||||
let signature = secret_for(&tx.from).unwrap()
|
||||
let signature = Pair::from(Keyring::from_public(Public::from_raw(tx.from)).unwrap())
|
||||
.sign(&tx.encode());
|
||||
|
||||
UncheckedTransaction { tx, signature }
|
||||
@@ -105,7 +79,7 @@ mod tests {
|
||||
let ret_data = execute(
|
||||
backend,
|
||||
&mut overlay,
|
||||
&executor(),
|
||||
&Executor::new(),
|
||||
"execute_transaction",
|
||||
&vec![].and(&header).and(tx)
|
||||
).unwrap();
|
||||
@@ -115,7 +89,7 @@ mod tests {
|
||||
let ret_data = execute(
|
||||
backend,
|
||||
&mut overlay,
|
||||
&executor(),
|
||||
&Executor::new(),
|
||||
"finalise_block",
|
||||
&vec![].and(&header)
|
||||
).unwrap();
|
||||
@@ -131,8 +105,8 @@ mod tests {
|
||||
genesis_hash,
|
||||
hex!("25e5b37074063ab75c889326246640729b40d0c86932edc527bc80db0e04fe5c").into(),
|
||||
vec![Transaction {
|
||||
from: one(),
|
||||
to: two(),
|
||||
from: Keyring::One.to_raw_public(),
|
||||
to: Keyring::Two.to_raw_public(),
|
||||
amount: 69,
|
||||
nonce: 0,
|
||||
}]
|
||||
@@ -142,20 +116,29 @@ mod tests {
|
||||
#[test]
|
||||
fn construct_genesis_should_work() {
|
||||
let mut storage = GenesisConfig::new_simple(
|
||||
vec![one(), two()], 1000
|
||||
vec![Keyring::One.to_raw_public(), Keyring::Two.to_raw_public()], 1000
|
||||
).genesis_map();
|
||||
let block = construct_genesis_block(&storage);
|
||||
let genesis_hash = block.header.blake2_256().into();
|
||||
storage.extend(additional_storage_with_genesis(&block).into_iter());
|
||||
|
||||
let mut overlay = OverlayedChanges::default();
|
||||
let backend = InMemory::from(storage);
|
||||
let (b1data, _b1hash) = block1(genesis_hash, &backend);
|
||||
|
||||
let mut overlay = OverlayedChanges::default();
|
||||
let _ = execute(
|
||||
&backend,
|
||||
&mut overlay,
|
||||
&executor(),
|
||||
&Executor::new(),
|
||||
"execute_block",
|
||||
&b1data
|
||||
).unwrap();
|
||||
|
||||
let mut overlay = OverlayedChanges::default();
|
||||
let _ = execute(
|
||||
&backend,
|
||||
&mut overlay,
|
||||
&WasmExecutor,
|
||||
"execute_block",
|
||||
&b1data
|
||||
).unwrap();
|
||||
@@ -165,42 +148,20 @@ mod tests {
|
||||
#[should_panic]
|
||||
fn construct_genesis_with_bad_transaction_should_panic() {
|
||||
let mut storage = GenesisConfig::new_simple(
|
||||
vec![one(), two()], 68
|
||||
vec![Keyring::One.to_raw_public(), Keyring::Two.to_raw_public()], 68
|
||||
).genesis_map();
|
||||
let block = construct_genesis_block(&storage);
|
||||
let genesis_hash = block.header.blake2_256().into();
|
||||
storage.extend(additional_storage_with_genesis(&block).into_iter());
|
||||
|
||||
let mut overlay = OverlayedChanges::default();
|
||||
let backend = InMemory::from(storage);
|
||||
let (b1data, _b1hash) = block1(genesis_hash, &backend);
|
||||
|
||||
let _ = execute(
|
||||
&backend,
|
||||
&mut overlay,
|
||||
&executor(),
|
||||
"execute_block",
|
||||
&b1data
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn construct_genesis_should_work_under_wasm() {
|
||||
let mut storage = GenesisConfig::new_simple(
|
||||
vec![one(), two()], 1000
|
||||
).genesis_map();
|
||||
let block = construct_genesis_block(&storage);
|
||||
let genesis_hash = block.header.blake2_256().into();
|
||||
storage.extend(additional_storage_with_genesis(&block).into_iter());
|
||||
|
||||
let mut overlay = OverlayedChanges::default();
|
||||
let backend = InMemory::from(storage);
|
||||
let (b1data, _b1hash) = block1(genesis_hash, &backend);
|
||||
|
||||
let _ = execute(
|
||||
&backend,
|
||||
&mut overlay,
|
||||
&WasmExecutor,
|
||||
&Executor::new(),
|
||||
"execute_block",
|
||||
&b1data
|
||||
).unwrap();
|
||||
|
||||
@@ -22,10 +22,11 @@ extern crate substrate_primitives as primitives;
|
||||
extern crate substrate_state_machine as state_machine;
|
||||
extern crate substrate_serializer as ser;
|
||||
extern crate substrate_codec as codec;
|
||||
extern crate substrate_executor as executor;
|
||||
#[cfg(test)] #[macro_use] extern crate substrate_executor as executor;
|
||||
extern crate ed25519;
|
||||
#[cfg(test)] extern crate substrate_runtime_support as runtime_support;
|
||||
#[cfg(test)] extern crate substrate_test_runtime as test_runtime;
|
||||
#[cfg(test)] extern crate substrate_keyring as keyring;
|
||||
|
||||
extern crate triehash;
|
||||
extern crate parking_lot;
|
||||
@@ -42,8 +43,9 @@ pub mod genesis;
|
||||
pub use blockchain::Info as ChainInfo;
|
||||
pub use blockchain::BlockId;
|
||||
|
||||
use primitives::block;
|
||||
use primitives::{block, AuthorityId};
|
||||
use primitives::storage::{StorageKey, StorageData};
|
||||
use codec::{KeyedVec, Slicable};
|
||||
|
||||
use blockchain::Backend as BlockchainBackend;
|
||||
use backend::BlockImportOperation;
|
||||
@@ -162,7 +164,18 @@ impl<B, E> Client<B, E> where
|
||||
|
||||
/// Get the code at a given block.
|
||||
pub fn code_at(&self, id: &BlockId) -> error::Result<Vec<u8>> {
|
||||
self.storage(id, &StorageKey(b":code:".to_vec())).map(|data| data.0)
|
||||
self.storage(id, &StorageKey(b":code".to_vec())).map(|data| data.0)
|
||||
}
|
||||
|
||||
/// Get the current set of authorities from storage.
|
||||
pub fn authorities_at(&self, id: &BlockId) -> error::Result<Vec<AuthorityId>> {
|
||||
let state = self.state_at(id)?;
|
||||
(0..u32::decode(&mut state.storage(b":auth:len")?).ok_or(error::ErrorKind::AuthLen)?)
|
||||
.map(|i| state.storage(&i.to_keyed_vec(b":auth:"))
|
||||
.map_err(|_| error::ErrorKind::Backend)
|
||||
.and_then(|mut s| AuthorityId::decode(&mut s).ok_or(error::ErrorKind::Auth(i)))
|
||||
.map_err(Into::into)
|
||||
).collect()
|
||||
}
|
||||
|
||||
/// Execute a call to a contract on top of state in a block of given hash.
|
||||
@@ -235,3 +248,37 @@ impl<B, E> Client<B, E> where
|
||||
self.backend.blockchain().body(*id)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use codec::Slicable;
|
||||
use keyring::Keyring;
|
||||
use test_runtime::genesismap::{GenesisConfig, additional_storage_with_genesis};
|
||||
use test_runtime;
|
||||
|
||||
native_executor_instance!(Executor, test_runtime::api::dispatch, include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm"));
|
||||
|
||||
#[test]
|
||||
fn authorities_call_works() {
|
||||
let genesis_config = GenesisConfig::new_simple(vec![
|
||||
Keyring::Alice.to_raw_public(),
|
||||
Keyring::Bob.to_raw_public(),
|
||||
Keyring::Charlie.to_raw_public()
|
||||
], 1000);
|
||||
|
||||
let prepare_genesis = || {
|
||||
let mut storage = genesis_config.genesis_map();
|
||||
let block = genesis::construct_genesis_block(&storage);
|
||||
storage.extend(additional_storage_with_genesis(&block));
|
||||
(primitives::block::Header::decode(&mut block.header.encode().as_ref()).expect("to_vec() always gives a valid serialisation; qed"), storage.into_iter().collect())
|
||||
};
|
||||
let client = new_in_mem(Executor::new(), prepare_genesis).unwrap();
|
||||
|
||||
assert_eq!(client.authorities_at(&BlockId::Number(0)).unwrap(), vec![
|
||||
Keyring::Alice.to_raw_public(),
|
||||
Keyring::Bob.to_raw_public(),
|
||||
Keyring::Charlie.to_raw_public()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user