mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 15:51:12 +00:00
Genesis block builder and test.
This commit is contained in:
Generated
+2
@@ -964,9 +964,11 @@ name = "polkadot-client"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"native-runtime 0.1.0",
|
||||
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"polkadot-executor 0.1.0",
|
||||
"polkadot-primitives 0.1.0",
|
||||
"polkadot-serializer 0.1.0",
|
||||
"polkadot-state-machine 0.1.0",
|
||||
|
||||
@@ -10,5 +10,7 @@ parking_lot = "0.4"
|
||||
polkadot-primitives = { path = "../primitives", version = "0.1" }
|
||||
polkadot-state-machine = { path = "../state_machine", version = "0.1" }
|
||||
polkadot-serializer = { path = "../serializer" }
|
||||
polkadot-executor = { path = "../executor" }
|
||||
native-runtime = { path = "../native-runtime" }
|
||||
triehash = "0.1"
|
||||
hex-literal = "0.1"
|
||||
|
||||
@@ -35,3 +35,87 @@ pub fn construct_genesis_block(storage: &HashMap<Vec<u8>, Vec<u8>>) -> Block {
|
||||
transactions: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use native_runtime::codec::{Slicable, Joiner};
|
||||
use native_runtime::support::{one, two, Hashable};
|
||||
use native_runtime::runtime::genesismap::{GenesisConfig, additional_storage_with_genesis};
|
||||
use native_runtime::primitives::{AccountID, Hash, BlockNumber, Transaction,
|
||||
UncheckedTransaction, Digest, Function};
|
||||
use state_machine::execute;
|
||||
use state_machine::OverlayedChanges;
|
||||
use state_machine::backend::InMemory;
|
||||
use polkadot_executor::executor;
|
||||
use primitives::contract::CallData;
|
||||
use primitives::ed25519::Pair;
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
fn construct_block(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(|transaction| {
|
||||
let signature = secret_for(&transaction.signed).unwrap()
|
||||
.sign(&transaction.to_vec())
|
||||
.inner();
|
||||
UncheckedTransaction { transaction, signature }
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
let transaction_root = ordered_trie_root(transactions.iter().map(Slicable::to_vec)).0;
|
||||
|
||||
let header = Header {
|
||||
parent_hash,
|
||||
number,
|
||||
state_root,
|
||||
transaction_root,
|
||||
digest: Digest { logs: vec![], },
|
||||
};
|
||||
let hash = header.blake2_256();
|
||||
|
||||
(Block { header, transactions }.to_vec(), hash)
|
||||
}
|
||||
|
||||
fn block1(genesis_hash: Hash) -> (Vec<u8>, Hash) {
|
||||
construct_block(
|
||||
1,
|
||||
genesis_hash,
|
||||
hex!("25e5b37074063ab75c889326246640729b40d0c86932edc527bc80db0e04fe5c"),
|
||||
vec![Transaction {
|
||||
signed: one(),
|
||||
nonce: 0,
|
||||
function: Function::StakingTransfer,
|
||||
input_data: vec![].join(&two()).join(&69u64),
|
||||
}]
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn construct_genesis_should_work() {
|
||||
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();
|
||||
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);
|
||||
|
||||
let _ = execute(
|
||||
&backend,
|
||||
&mut overlay,
|
||||
&executor(),
|
||||
"execute_block",
|
||||
&CallData(b1data)
|
||||
).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,12 +21,14 @@
|
||||
extern crate polkadot_primitives as primitives;
|
||||
extern crate polkadot_state_machine as state_machine;
|
||||
extern crate polkadot_serializer as ser;
|
||||
extern crate polkadot_executor;
|
||||
extern crate native_runtime;
|
||||
|
||||
extern crate triehash;
|
||||
extern crate parking_lot;
|
||||
#[macro_use] extern crate error_chain;
|
||||
#[macro_use] extern crate log;
|
||||
#[macro_use] extern crate hex_literal;
|
||||
|
||||
pub mod error;
|
||||
pub mod blockchain;
|
||||
|
||||
@@ -64,7 +64,6 @@ pub struct InMemory {
|
||||
inner: MemoryState, // keeps all the state in memory.
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl InMemory {
|
||||
/// Create a new instance from a given storage map.
|
||||
pub fn from(storage: ::std::collections::HashMap<Vec<u8>, Vec<u8>>) -> Self {
|
||||
|
||||
@@ -33,13 +33,14 @@ extern crate byteorder;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
|
||||
use primitives::contract::{CallData};
|
||||
use primitives::contract::CallData;
|
||||
|
||||
pub mod backend;
|
||||
mod ext;
|
||||
mod testing;
|
||||
|
||||
pub use testing::TestExternalities;
|
||||
pub use ext::Ext;
|
||||
|
||||
/// Updates to be committed to the state.
|
||||
pub enum Update {
|
||||
@@ -151,12 +152,17 @@ pub trait Externalities {
|
||||
|
||||
/// Get the current set of authorities from storage.
|
||||
fn authorities(&self) -> Result<Vec<&[u8]>, ExternalitiesError> {
|
||||
(0..self.storage(b"con:aut:len")?.into_iter()
|
||||
(0..self.storage(b":aut:len")?.into_iter()
|
||||
.rev()
|
||||
.fold(0, |acc, &i| (acc << 8) + (i as u32)))
|
||||
.map(|i| self.storage(&to_keyed_vec(i, b"con:aut:".to_vec())))
|
||||
.map(|i| self.storage(&to_keyed_vec(i, b":aut:".to_vec())))
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Get the runtime code.
|
||||
fn code(&self) -> Result<&[u8], ExternalitiesError> {
|
||||
self.storage(b":code")
|
||||
}
|
||||
}
|
||||
|
||||
/// Code execution engine.
|
||||
@@ -195,6 +201,7 @@ pub fn execute<B: backend::Backend, Exec: CodeExecutor>(
|
||||
};
|
||||
// make a copy.
|
||||
let code = externalities.storage(b":code").unwrap_or(&[]).to_vec();
|
||||
use primitives::hexdisplay::HexDisplay;
|
||||
|
||||
exec.call(
|
||||
&mut externalities,
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
//! Conensus module for runtime; manages the authority set ready for the native code.
|
||||
|
||||
use runtime_std::prelude::*;
|
||||
use support::StorageVec;
|
||||
use support::storage::unhashed::StorageVec;
|
||||
use primitives::SessionKey;
|
||||
|
||||
struct AuthorityStorageVec {}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
use std::collections::HashMap;
|
||||
use runtime_std::twox_128;
|
||||
use codec::{KeyedVec, Slicable};
|
||||
use codec::{KeyedVec, Joiner};
|
||||
use support::Hashable;
|
||||
use primitives::{AccountID, BlockNumber, Block};
|
||||
use runtime::staking::Balance;
|
||||
@@ -31,7 +31,7 @@ pub struct GenesisConfig {
|
||||
pub block_time: u64,
|
||||
pub session_length: BlockNumber,
|
||||
pub sessions_per_era: BlockNumber,
|
||||
pub bonding_duration: u64,
|
||||
pub bonding_duration: BlockNumber,
|
||||
pub approval_ratio: u32,
|
||||
}
|
||||
|
||||
@@ -50,36 +50,42 @@ impl GenesisConfig {
|
||||
}
|
||||
|
||||
pub fn genesis_map(&self) -> HashMap<Vec<u8>, Vec<u8>> {
|
||||
let wasm_runtime = include_bytes!("../../../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm");
|
||||
let wasm_runtime = include_bytes!("../../../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm").to_vec();
|
||||
vec![
|
||||
(&b":code"[..], wasm_runtime.to_vec()),
|
||||
(&b"gov:apr"[..], self.approval_ratio.to_vec()),
|
||||
(&b"ses:len"[..], self.session_length.to_vec()),
|
||||
(&b"ses:val:len"[..], (self.validators.len() as u32).to_vec()),
|
||||
(&b"con:aut:len"[..], (self.authorities.len() as u32).to_vec()),
|
||||
(&b"sta:wil:len"[..], 0u32.to_vec()),
|
||||
(&b"sta:spe"[..], self.sessions_per_era.to_vec()),
|
||||
(&b"sta:vac"[..], (self.validators.len() as u32).to_vec()),
|
||||
(&b"sta:era"[..], 0u64.to_vec()),
|
||||
(&b"gov:apr"[..], vec![].join(&self.approval_ratio)),
|
||||
(&b"ses:len"[..], vec![].join(&self.session_length)),
|
||||
(&b"ses:val:len"[..], vec![].join(&(self.validators.len() as u32))),
|
||||
(&b"sta:wil:len"[..], vec![].join(&0u32)),
|
||||
(&b"sta:spe"[..], vec![].join(&self.sessions_per_era)),
|
||||
(&b"sta:vac"[..], vec![].join(&(self.validators.len() as u32))),
|
||||
(&b"sta:era"[..], vec![].join(&0u64)),
|
||||
].into_iter()
|
||||
.map(|(k, v)| (k.to_vec(), v))
|
||||
.map(|(k, v)| (k.into(), v))
|
||||
.chain(self.validators.iter()
|
||||
.enumerate()
|
||||
.map(|(i, account)| ((i as u32).to_keyed_vec(b"ses:val:"), account.to_vec()))
|
||||
.map(|(i, account)| ((i as u32).to_keyed_vec(b"ses:val:"), vec![].join(account)))
|
||||
).chain(self.authorities.iter()
|
||||
.enumerate()
|
||||
.map(|(i, account)| ((i as u32).to_keyed_vec(b"con:aut:"), account.to_vec()))
|
||||
.map(|(i, account)| ((i as u32).to_keyed_vec(b"con:aut:"), vec![].join(account)))
|
||||
).chain(self.balances.iter()
|
||||
.map(|&(account, balance)| (account.to_keyed_vec(b"sta:bal:"), balance.to_vec()))
|
||||
.map(|&(account, balance)| (account.to_keyed_vec(b"sta:bal:"), vec![].join(&balance)))
|
||||
)
|
||||
.map(|(k, v)| (twox_128(&k[..])[..].to_vec(), v.to_vec()))
|
||||
.chain(vec![
|
||||
(b":code"[..].into(), wasm_runtime),
|
||||
(b"con:aut:len"[..].into(), vec![].join(&(self.authorities.len() as u32))),
|
||||
].into_iter())
|
||||
.chain(self.authorities.iter()
|
||||
.enumerate()
|
||||
.map(|(i, account)| ((i as u32).to_keyed_vec(b"con:aut:"), vec![].join(account)))
|
||||
)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn additional_storage_with_genesis(genesis_block: &[u8]) -> Result<HashMap<Vec<u8>, Vec<u8>>, ()> {
|
||||
let h = Block::from_slice(genesis_block).ok_or(())?.header.blake2_256();
|
||||
Ok(map![
|
||||
twox_128(&0u64.to_keyed_vec(b"sys:old:")).to_vec() => h.to_vec()
|
||||
])
|
||||
pub fn additional_storage_with_genesis(genesis_block: &Block) -> HashMap<Vec<u8>, Vec<u8>> {
|
||||
use codec::Slicable;
|
||||
map![
|
||||
twox_128(&0u64.to_keyed_vec(b"sys:old:")).to_vec() => genesis_block.header.blake2_256().to_vec()
|
||||
]
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ pub mod privileged {
|
||||
|
||||
/// Set the new code.
|
||||
pub fn set_code(new: &[u8]) {
|
||||
storage::put_raw(CODE, new);
|
||||
storage::unhashed::put_raw(b":code", new);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -142,6 +142,130 @@ pub trait StorageVec {
|
||||
}
|
||||
}
|
||||
|
||||
pub mod unhashed {
|
||||
use super::{runtime_std, Slicable, KeyedVec, Vec};
|
||||
|
||||
/// Return the value of the item in storage under `key`, or `None` if there is no explicit entry.
|
||||
pub fn get<T: Slicable + Sized>(key: &[u8]) -> Option<T> {
|
||||
Slicable::set_as_slice(&|out, offset|
|
||||
runtime_std::read_storage(key, out, offset) >= out.len()
|
||||
)
|
||||
}
|
||||
|
||||
/// Return the value of the item in storage under `key`, or the type's default if there is no
|
||||
/// explicit entry.
|
||||
pub fn get_or_default<T: Slicable + Sized + Default>(key: &[u8]) -> T {
|
||||
get(key).unwrap_or_else(Default::default)
|
||||
}
|
||||
|
||||
/// Return the value of the item in storage under `key`, or `default_value` if there is no
|
||||
/// explicit entry.
|
||||
pub fn get_or<T: Slicable + Sized>(key: &[u8], default_value: T) -> T {
|
||||
get(key).unwrap_or(default_value)
|
||||
}
|
||||
|
||||
/// Return the value of the item in storage under `key`, or `default_value()` if there is no
|
||||
/// explicit entry.
|
||||
pub fn get_or_else<T: Slicable + Sized, F: FnOnce() -> T>(key: &[u8], default_value: F) -> T {
|
||||
get(key).unwrap_or_else(default_value)
|
||||
}
|
||||
|
||||
/// Please `value` in storage under `key`.
|
||||
pub fn put<T: Slicable>(key: &[u8], value: &T) {
|
||||
value.as_slice_then(|slice| runtime_std::set_storage(key, slice));
|
||||
}
|
||||
|
||||
/// Please `value` in storage under `key`.
|
||||
pub fn place<T: Slicable>(key: &[u8], value: T) {
|
||||
value.as_slice_then(|slice| runtime_std::set_storage(key, slice));
|
||||
}
|
||||
|
||||
/// Remove `key` from storage, returning its value if it had an explicit entry or `None` otherwise.
|
||||
pub fn take<T: Slicable + Sized>(key: &[u8]) -> Option<T> {
|
||||
let r = get(key);
|
||||
if r.is_some() {
|
||||
kill(key);
|
||||
}
|
||||
r
|
||||
}
|
||||
|
||||
/// Remove `key` from storage, returning its value, or, if there was no explicit entry in storage,
|
||||
/// the default for its type.
|
||||
pub fn take_or_default<T: Slicable + Sized + Default>(key: &[u8]) -> T {
|
||||
take(key).unwrap_or_else(Default::default)
|
||||
}
|
||||
|
||||
/// Return the value of the item in storage under `key`, or `default_value` if there is no
|
||||
/// explicit entry. Ensure there is no explicit entry on return.
|
||||
pub fn take_or<T: Slicable + Sized>(key: &[u8], default_value: T) -> T {
|
||||
take(key).unwrap_or(default_value)
|
||||
}
|
||||
|
||||
/// Return the value of the item in storage under `key`, or `default_value()` if there is no
|
||||
/// explicit entry. Ensure there is no explicit entry on return.
|
||||
pub fn take_or_else<T: Slicable + Sized, F: FnOnce() -> T>(key: &[u8], default_value: F) -> T {
|
||||
take(key).unwrap_or_else(default_value)
|
||||
}
|
||||
|
||||
/// Check to see if `key` has an explicit entry in storage.
|
||||
pub fn exists(key: &[u8]) -> bool {
|
||||
let mut x = [0u8; 1];
|
||||
runtime_std::read_storage(key, &mut x[..], 0) >= 1
|
||||
}
|
||||
|
||||
/// Ensure `key` has no explicit entry in storage.
|
||||
pub fn kill(key: &[u8]) {
|
||||
runtime_std::set_storage(key, b"");
|
||||
}
|
||||
|
||||
/// Get a Vec of bytes from storage.
|
||||
pub fn get_raw(key: &[u8]) -> Vec<u8> {
|
||||
runtime_std::storage(key)
|
||||
}
|
||||
|
||||
/// Put a raw byte slice into storage.
|
||||
pub fn put_raw(key: &[u8], value: &[u8]) {
|
||||
runtime_std::set_storage(key, value)
|
||||
}
|
||||
|
||||
/// A trait to conveniently store a vector of storable data.
|
||||
// TODO: add iterator support
|
||||
pub trait StorageVec {
|
||||
type Item: Default + Sized + Slicable;
|
||||
const PREFIX: &'static [u8];
|
||||
|
||||
/// Get the current set of items.
|
||||
fn items() -> Vec<Self::Item> {
|
||||
(0..Self::count()).into_iter().map(Self::item).collect()
|
||||
}
|
||||
|
||||
/// Set the current set of items.
|
||||
fn set_items(items: &[Self::Item]) {
|
||||
Self::set_count(items.len() as u32);
|
||||
items.iter().enumerate().for_each(|(v, ref i)| Self::set_item(v as u32, i));
|
||||
}
|
||||
|
||||
fn set_item(index: u32, item: &Self::Item) {
|
||||
if index < Self::count() {
|
||||
put(&index.to_keyed_vec(Self::PREFIX), item);
|
||||
}
|
||||
}
|
||||
|
||||
fn item(index: u32) -> Self::Item {
|
||||
get_or_default(&index.to_keyed_vec(Self::PREFIX))
|
||||
}
|
||||
|
||||
fn set_count(count: u32) {
|
||||
(count..Self::count()).for_each(|i| Self::set_item(i, &Self::Item::default()));
|
||||
put(&b"len".to_keyed_vec(Self::PREFIX), &count);
|
||||
}
|
||||
|
||||
fn count() -> u32 {
|
||||
get_or_default(&b"len".to_keyed_vec(Self::PREFIX))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
BIN
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user