From 1f183d688a8621ec638c851e710fc9ae99928835 Mon Sep 17 00:00:00 2001 From: Gav Date: Mon, 8 Jan 2018 17:13:44 +0100 Subject: [PATCH 001/112] Introduce basic skeleton for Polkador runtime. --- substrate/executor/src/wasm_executor.rs | 28 ++- substrate/runtime/polkadot/src/lib.rs | 228 +++++++++++++++++++++--- substrate/runtime/support/src/lib.rs | 87 ++++----- substrate/runtime/test/src/lib.rs | 53 +++++- 4 files changed, 311 insertions(+), 85 deletions(-) diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index f52b2cbf71..4c3ed5b791 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -76,7 +76,7 @@ impl WritePrimitive for MemoryInstance { } impl_function_executor!(this: FunctionExecutor<'e, E>, - ext_print(utf8_data: *const u8, utf8_len: i32) => { + ext_print(utf8_data: *const u8, utf8_len: u32) => { if let Ok(utf8) = this.memory.get(utf8_data, utf8_len as usize) { if let Ok(message) = String::from_utf8(utf8) { println!("Runtime: {}", message); @@ -96,7 +96,7 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, println!("memmove {} from {}, {} bytes", dest, src, count); dest }, - ext_memset(dest: *mut u8, val: i32, count: usize) -> *mut u8 => { + ext_memset(dest: *mut u8, val: u32, count: usize) -> *mut u8 => { let _ = this.memory.clear(dest as usize, val as u8, count as usize); println!("memset {} with {}, {} bytes", dest, val, count); dest @@ -110,12 +110,12 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, this.heap.deallocate(addr); println!("free {}", addr) }, - ext_set_storage(key_data: *const u8, key_len: i32, value_data: *const u8, value_len: i32) => { + ext_set_storage(key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32) => { if let (Ok(key), Ok(value)) = (this.memory.get(key_data, key_len as usize), this.memory.get(value_data, value_len as usize)) { this.ext.set_storage(key, value); } }, - ext_get_allocated_storage(key_data: *const u8, key_len: i32, written_out: *mut i32) -> *mut u8 => { + ext_get_allocated_storage(key_data: *const u8, key_len: u32, written_out: *mut u32) -> *mut u8 => { let (offset, written) = if let Ok(key) = this.memory.get(key_data, key_len as usize) { if let Ok(value) = this.ext.storage(&key) { let offset = this.heap.allocate(value.len() as u32) as u32; @@ -126,6 +126,18 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, this.memory.write_primitive(written_out, written); offset as u32 + }, + ext_get_storage_into(key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32) -> u32 => { + if let Ok(key) = this.memory.get(key_data, key_len as usize) { + if let Ok(value) = this.ext.storage(&key) { + let written = ::std::cmp::min(value_len as usize, value.len()); + let _ = this.memory.set(value_data, &value[0..written]); + written as u32 + } else { 0 } + } else { 0 } + }, + ext_deposit_log(_log_data: *const u8, _log_len: u32) { + unimplemented!() } => <'e, E: Externalities + 'e> ); @@ -163,8 +175,8 @@ impl CodeExecutor for WasmExecutor { let returned = program .params_with_external("env", &mut fec) .map(|p| p - .add_argument(I32(offset as i32)) - .add_argument(I32(size as i32))) + .add_argument(I32(offset as u32)) + .add_argument(I32(size as u32))) .and_then(|p| module.execute_export(method, p)) .map_err(|_| -> Error { ErrorKind::Runtime.into() })?; @@ -221,8 +233,8 @@ mod tests { let returned = program .params_with_external("env", &mut fec) .map(|p| p - .add_argument(I32(offset as i32)) - .add_argument(I32(size as i32))) + .add_argument(I32(offset as u32)) + .add_argument(I32(size as u32))) .and_then(|p| module.execute_export("test_data_in", p)) .map_err(|_| -> Error { ErrorKind::Runtime.into() }).expect("function should be callable"); diff --git a/substrate/runtime/polkadot/src/lib.rs b/substrate/runtime/polkadot/src/lib.rs index ec3fabb89c..da82db8fa2 100644 --- a/substrate/runtime/polkadot/src/lib.rs +++ b/substrate/runtime/polkadot/src/lib.rs @@ -8,29 +8,215 @@ use alloc::vec::Vec; #[macro_use] extern crate runtime_support; -use runtime_support::{set_storage, code, set_code, storage, validators, set_validators, print}; +use runtime_support::{set_storage, storage, storage_into, print, Value20}; -impl_stub!(test_data_in); -fn test_data_in(input: Vec) -> Vec { - print(b"set_storage" as &[u8]); - set_storage(b"input", &input); +/// The hash of an ECDSA pub key which is used to identify an external transactor. +type AccountID = [u8; 32]; +/// The ECDSA pub key of an authority. This is what the external environment/consensus algorithm +/// refers to as a "authority". +type SessionKey = [u8; 65]; +type Balance = u64; +type ChainID = u64; +type Hash = [u8; 32]; +type BlockNumber = u64; +/// A proportion (rational number). +struct Proportion { nom: u64, denom: u64, }; +type Timestamp = u64; +type TxOrder = u64; +/// Statistics concerning consensus. +// TODO. +struct Statistics; +/// A report of bad behaviour. +// TODO. +struct Complaint; - print(b"code" as &[u8]); - set_storage(b"code", &code()); +/// The state of a parachain. +/*struct ParachainState { + head_data: Vec, + balance: Balance, + user_balances: HashMap, + balance_downloads: HashMap ), + egress_roots: Vec +}*/ +//struct CandidateReceipt; - print(b"set_code" as &[u8]); - set_code(&input); +// TODO: include RLP implementation +// TODO: add keccak256 (or some better hashing scheme) & ECDSA-recover (or some better sig scheme) - print(b"storage" as &[u8]); - let copy = storage(b"input"); - - print(b"validators" as &[u8]); - let mut v = validators(); - v.push(copy); - - print(b"set_validators" as &[u8]); - set_validators(&v.iter().map(Vec::as_slice).collect::>()); - - print(b"finished!" as &[u8]); - b"all ok!".to_vec() +impl_stub!(execute_block); +fn execute_block(_input: Vec) -> Vec { + // TODO: decode block and ensure valid + // TODO: iterate through transactions amd decode/dispatch them + // TODO: progress to next session if it's time + // TODO: progress to next era if it's time + Vec::new() +} + +impl_stub!(execute_transaction); +fn execute_transaction(tx: Vec) -> Vec { + environment::execute_transaction(&tx) +} + +/// The current relay chain identifier. +fn chain_id() -> ChainID { unimplemented!() } // TODO: retrieve from external + +mod environment { + /// The current block number being processed. Set by `execute_block`. + pub fn block_number() -> BlockNumber { unimplemented!() } + + /// Get the block hash of a given block. + pub fn block_hash(_number: BlockNumber) -> Hash { unimplemented!() } + + /// ? + fn set_digest(_preserialised_rlp_digest: &[u8]) { unimplemented!() } + + /// Get the current user's ID + pub fn current_user() -> AccountID { unimplemented!() } + + /// Execute a given transaction. + pub fn execute_transaction(_tx: &[u8]) -> Vec { + // TODO: decode data and ensure valid + // TODO: ensure signature valid and recover id + // TODO: ensure target_function valid + // TODO: decode parameters + // TODO: make call + // TODO: encode any return + Vec::new() + } + + /// Set the new code. + pub fn set_code(new: &[u8]) { + set_storage(b"\0code", new) + } + + /// ? + fn set_active_parachains(_data: &[u8]) { unimplemented!() } +} + +mod consensus { + fn value_vec(mut value: usize, initial: Vec) -> Vec { + let mut acc = initial; + while value > 0 { + acc.push(value as u8); + value /= 256; + } + acc + } + + fn set_authority(index: usize, authority: AccountID) { + set_storage(&value_vec(index, b"\0authority".to_vec()), &authority[..]); + } + + fn authority(index: usize) -> AccountID { + storage_into::(&value_vec(index, b"\0authority".to_vec())) + } + + fn set_authority_count(count: usize) { + (count..authority_count()).for_each(|i| set_authority(i, &[])); + set_storage(b"\0authority_count", &value_vec(count, Vec::new())); + } + + fn authority_count() -> usize { + storage(b"\0authority_count").into_iter().rev().fold(0, |acc, i| (acc << 8) + (i as usize)) + } + + /// Get the current set of authorities. These are the session keys. + pub fn authorities() -> Vec { + (0..authority_count()).into_iter().map(authority).map.collect() + } + + /// Set the current set of authorities' session keys. + /// + /// Called by `next_session` only. + fn set_authorities(authorities: &[AccountID]) { + set_authority_count(authorities.len()); + authorities.iter().enumerate().for_each(|(v, i)| set_authority(v, i)); + } + + /// Get the current set of validators. These are the long-term identifiers for the validators + /// and will be mapped to a session key with the most recent `set_next_session_key`. + pub fn validators() -> Vec { + unimplemented!() + } + + /// Set the current set of validators. + /// + /// Called by staking::next_era() only. + pub fn set_validators(_new: &[AccountID]) { + unimplemented!() + } + + /// Flush out any statistics. + pub fn flush_statistics() -> Statistics { unimplemented!() } + + /// Sets the session key of `_validator` to `_session`. This doesn't take effect until the next + /// session. + pub fn set_session_key(_validator: AccountID, _session: AccountID) { + unimplemented!() + } + + /// Move onto next session: register the new authority set. + pub fn next_session() { + // TODO: Call set_authorities(). + unimplemented!() + } +} + +mod staking { + /// The length of a staking era in blocks. + fn era_length() -> BlockNumber { unimplemented!() } + + /// The era has changed - enact new staking set. + /// + /// NOTE: This is always a session change. + fn next_era() { unimplemented!() } + + /// The balance of a given account. + fn balance(_who: AccountID) -> Balance { unimplemented!() } + + /// User-level function to move funds onto a parachain. Calls `parachains::credit_parachain`. + fn move_to_parachain(chain_id: ChainID, value: Balance) { unimplemented!() } + + /// System-level function to be called only by Parachains object when funds have left that + /// object and are to be credited here. + fn credit_staker(value: Balance) { unimplemented!() } + + /// Declare the desire to stake under the requirement that under flawless operation, each era + /// should return `minimum_era_return` on the amount staked. + /// + /// Effects will be felt at the beginning of the next era. + fn stake(minimum_era_return: Proportion) { unimplemented!() } + + /// Retract the desire to stake. + /// + /// Effects will be felt at the beginning of the next era. + fn unstake() { unimplemented!() } + + /// Report invalid behaviour by a staking participant. + fn complain(complaint: Complaint) { unimplemented!() } +} + +/* +mod parachains { + fn chain_ids(self) -> [ ChainID ]; + fn validation_function(self, chain_id: ChainID) -> Fn(consolidated_ingress: [ ( ChainID, bytes ) ], balance_downloads: [ ( AccountID, Balance ) ], block_data: bytes, previous_head_data: bytes) -> (head_data: bytes, egress_queues: [ [ bytes ] ], balance_uploads: [ ( AccountID, Balance ) ]); + fn validate_and_calculate_fees_function(self, chain_id: ChainID) -> Fn(egress_queues: [ [ bytes ] ], balance_uploads: [ ( AccountID, Balance ) ]) -> Balance; + fn balance(self, chain_id: ChainID, id: AccountID) -> Balance; + fn verify_and_consolidate_queues(self, unprocessed_ingress: [ [ [ bytes ] ] ]) -> [ (chain_id: ChainID, message: bytes) ]; + fn chain_state(self, chain_id: ChainID) -> ParachainState; + fn move_to_staking(mut self, chain_id: ChainID, value: Balance); + fn credit_parachain(mut self, chain_id: ChainID, value: Balance); + fn download(mut self, chain_id: ChainID, value: Balance, instruction: bytes); + fn update_heads(mut self, candidate_receipts: &[ ( ChainID, CandidateReceipt ) ]); +} + +mod authentication { + fn validate_signature(self, tx: Transaction) -> ( AccountID, TxOrder ); + fn nonce(self, id: AccountID) -> TxOrder; + fn authenticate(mut self, tx: Transaction) -> AccountID; +} +*/ +mod timestamp { + fn timestamp() -> Timestamp { unimplemented!() } + fn set_timestamp(Timestamp) { unimplemented!() } } diff --git a/substrate/runtime/support/src/lib.rs b/substrate/runtime/support/src/lib.rs index 472497d284..4430f7249f 100644 --- a/substrate/runtime/support/src/lib.rs +++ b/substrate/runtime/support/src/lib.rs @@ -17,70 +17,57 @@ pub fn panic_fmt() -> ! { } extern "C" { - fn ext_print(utf8_data: *const u8, utf8_len: i32); + fn ext_print(utf8_data: *const u8, utf8_len: u32); fn ext_print_num(value: u64); - fn ext_set_storage(key_data: *const u8, key_len: i32, value_data: *const u8, value_len: i32); - fn ext_get_allocated_storage(key_data: *const u8, key_len: i32, written_out: *mut i32) -> *mut u8; + fn ext_set_storage(key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32); + fn ext_get_allocated_storage(key_data: *const u8, key_len: u32, written_out: *mut u32) -> *mut u8; + fn ext_get_storage_into(key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32) -> u32; + fn ext_deposit_log(log_data: *const u8, log_len: u32); } pub fn storage(key: &[u8]) -> Vec { - let mut length: i32 = 0; + let mut length: u32 = 0; unsafe { - let ptr = ext_get_allocated_storage(&key[0], key.len() as i32, &mut length); + let ptr = ext_get_allocated_storage(&key[0], key.len() as u32, &mut length); Vec::from_raw_parts(ptr, length as usize, length as usize) } } +pub trait IsValue { + const value: usize; +} + +pub struct Value20; impl IsValue for Value20 { const value = 20usize; } +pub struct Value32; impl IsValue for Value32 { const value = 32usize; } +pub struct Value64; impl IsValue for Value64 { const value = 64usize; } +pub struct Value65; impl IsValue for Value65 { const value = 65usize; } + +pub fn storage_into(key: &[u8]) -> Option<[u8; T::value]> { + let mut result = [0u8; T::value]; + let written = unsafe { + ext_get_storage_into(&key[0], key.len() as u32, &result[0], result.len()) + }; + match written { + T::value => Some(result), + _ => None, + } +} + pub fn set_storage(key: &[u8], value: &[u8]) { unsafe { ext_set_storage( - &key[0] as *const u8, key.len() as i32, - &value[0] as *const u8, value.len() as i32 + &key[0] as *const u8, key.len() as u32, + &value[0] as *const u8, value.len() as u32 ); } } -pub fn code() -> Vec { - storage(b"\0code") -} - -pub fn set_code(new: &[u8]) { - set_storage(b"\0code", new) -} - -fn value_vec(mut value: usize, initial: Vec) -> Vec { - let mut acc = initial; - while value > 0 { - acc.push(value as u8); - value /= 256; +pub fn deposit_log(log: &[u8]) { + unsafe { + ext_deposit_log( + &log[0] as *const u8, log.len() as u32, + ) } - acc -} - -pub fn set_validator(index: usize, validator: &[u8]) { - set_storage(&value_vec(index, b"\0validator".to_vec()), validator); -} - -pub fn validator(index: usize) -> Vec { - storage(&value_vec(index, b"\0validator".to_vec())) -} - -pub fn set_validator_count(count: usize) { - (count..validator_count()).for_each(|i| set_validator(i, &[])); - set_storage(b"\0validator_count", &value_vec(count, Vec::new())); -} - -pub fn validator_count() -> usize { - storage(b"\0validator_count").into_iter().rev().fold(0, |acc, i| (acc << 8) + (i as usize)) -} - -pub fn validators() -> Vec> { - (0..validator_count()).into_iter().map(validator).collect() -} - -pub fn set_validators(validators: &[&[u8]]) { - set_validator_count(validators.len()); - validators.iter().enumerate().for_each(|(v, i)| set_validator(v, i)); } pub trait Printable { @@ -90,7 +77,7 @@ pub trait Printable { impl<'a> Printable for &'a [u8] { fn print(self) { unsafe { - ext_print(&self[0] as *const u8, self.len() as i32); + ext_print(&self[0] as *const u8, self.len() as u32); } } } @@ -109,12 +96,10 @@ pub fn print(value: T) { macro_rules! impl_stub { ($name:ident) => { pub mod _internal { - extern crate alloc; - #[no_mangle] pub fn $name(input_data: *mut u8, input_len: usize) -> u64 { let input = unsafe { - ::alloc::vec::Vec::from_raw_parts(input_data, input_len, input_len) + super::alloc::vec::Vec::from_raw_parts(input_data, input_len, input_len) }; let output = super::$name(input); diff --git a/substrate/runtime/test/src/lib.rs b/substrate/runtime/test/src/lib.rs index ec3fabb89c..550e06c05d 100644 --- a/substrate/runtime/test/src/lib.rs +++ b/substrate/runtime/test/src/lib.rs @@ -8,7 +8,50 @@ use alloc::vec::Vec; #[macro_use] extern crate runtime_support; -use runtime_support::{set_storage, code, set_code, storage, validators, set_validators, print}; +use runtime_support::{set_storage, storage, print}; + +pub fn code() -> Vec { + storage(b"\0code") +} + +pub fn set_code(new: &[u8]) { + set_storage(b"\0code", new) +} + +fn value_vec(mut value: usize, initial: Vec) -> Vec { + let mut acc = initial; + while value > 0 { + acc.push(value as u8); + value /= 256; + } + acc +} + +pub fn set_authority(index: usize, authority: &[u8]) { + set_storage(&value_vec(index, b"\0authority".to_vec()), authority); +} + +pub fn authority(index: usize) -> Vec { + storage(&value_vec(index, b"\0authority".to_vec())) +} + +pub fn set_authority_count(count: usize) { + (count..authority_count()).for_each(|i| set_authority(i, &[])); + set_storage(b"\0authority_count", &value_vec(count, Vec::new())); +} + +pub fn authority_count() -> usize { + storage(b"\0authority_count").into_iter().rev().fold(0, |acc, i| (acc << 8) + (i as usize)) +} + +pub fn authorities() -> Vec> { + (0..authority_count()).into_iter().map(authority).collect() +} + +pub fn set_authorities(authorities: &[&[u8]]) { + set_authority_count(authorities.len()); + authorities.iter().enumerate().for_each(|(v, i)| set_authority(v, i)); +} impl_stub!(test_data_in); fn test_data_in(input: Vec) -> Vec { @@ -24,12 +67,12 @@ fn test_data_in(input: Vec) -> Vec { print(b"storage" as &[u8]); let copy = storage(b"input"); - print(b"validators" as &[u8]); - let mut v = validators(); + print(b"authorities" as &[u8]); + let mut v = authorities(); v.push(copy); - print(b"set_validators" as &[u8]); - set_validators(&v.iter().map(Vec::as_slice).collect::>()); + print(b"set_authorities" as &[u8]); + set_authorities(&v.iter().map(Vec::as_slice).collect::>()); print(b"finished!" as &[u8]); b"all ok!".to_vec() From a9fe12eb690b0fb81ddef99d903b1d3a478aeb8d Mon Sep 17 00:00:00 2001 From: Gav Date: Mon, 8 Jan 2018 17:56:16 +0100 Subject: [PATCH 002/112] Clean up the runtime skeleton. --- substrate/runtime/polkadot/src/lib.rs | 172 ++++++++++++++++++-------- 1 file changed, 119 insertions(+), 53 deletions(-) diff --git a/substrate/runtime/polkadot/src/lib.rs b/substrate/runtime/polkadot/src/lib.rs index da82db8fa2..d2143f28cd 100644 --- a/substrate/runtime/polkadot/src/lib.rs +++ b/substrate/runtime/polkadot/src/lib.rs @@ -10,6 +10,37 @@ use alloc::vec::Vec; extern crate runtime_support; use runtime_support::{set_storage, storage, storage_into, print, Value20}; +/* +use std::sync::{rc, RefCell, Once, ONCE_INIT}; +use std::mem; + +#[derive(Clone)] +struct SingletonReader { + inner: Rc>, +} + +fn singleton() -> SingletonReader { + // Initialize it to a null value + static mut SINGLETON: *const SingletonReader = 0 as *const SingletonReader; + static ONCE: Once = ONCE_INIT; + + unsafe { + ONCE.call_once(|| { + // Make it + let singleton = SingletonReader { + inner: Rc::new(RefCell::new(Default::default())), + }; + + // Put it in the heap so it can outlive this call + SINGLETON = mem::transmute(Box::new(singleton)); + }); + + // Now we give out a copy of the data that is safe to use concurrently. + (*SINGLETON).clone() + } +} +*/ + /// The hash of an ECDSA pub key which is used to identify an external transactor. type AccountID = [u8; 32]; /// The ECDSA pub key of an authority. This is what the external environment/consensus algorithm @@ -23,42 +54,69 @@ type BlockNumber = u64; struct Proportion { nom: u64, denom: u64, }; type Timestamp = u64; type TxOrder = u64; -/// Statistics concerning consensus. -// TODO. -struct Statistics; -/// A report of bad behaviour. -// TODO. -struct Complaint; -/// The state of a parachain. -/*struct ParachainState { - head_data: Vec, - balance: Balance, - user_balances: HashMap, - balance_downloads: HashMap ), - egress_roots: Vec -}*/ -//struct CandidateReceipt; +struct Digest { + logs: Vec>, +} + +struct Header { + parent_hash: Hash, + number: BlockNumber, + state_root: Hash, + transaction_root: Hash, + digest: Digest, +} + +struct Transaction { + senders: Vec, + function_name: String, + input_data: Vec, + nonce: TxOrder, +} + +struct Block { + header: Header, + transactions: Vec, +} + +impl Header { + pub fn from_rlp(_rlp: &[u8]) -> Self { + unimplemented!() + } +} + +impl Transaction { + pub fn from_rlp(_rlp: &[u8]) -> Self { + unimplemented!() + } +} + +impl Block { + pub fn from_rlp(_rlp: &[u8]) -> Self { + unimplemented!() + } +} // TODO: include RLP implementation // TODO: add keccak256 (or some better hashing scheme) & ECDSA-recover (or some better sig scheme) impl_stub!(execute_block); fn execute_block(_input: Vec) -> Vec { - // TODO: decode block and ensure valid - // TODO: iterate through transactions amd decode/dispatch them - // TODO: progress to next session if it's time - // TODO: progress to next era if it's time - Vec::new() + let block = Block::from_rlp(&_input); + environment::execute_block(&block) } impl_stub!(execute_transaction); -fn execute_transaction(tx: Vec) -> Vec { +fn execute_transaction(_input: Vec) -> Vec { + let tx = Transaction::from_rlp(&_input); environment::execute_transaction(&tx) } /// The current relay chain identifier. -fn chain_id() -> ChainID { unimplemented!() } // TODO: retrieve from external +fn chain_id() -> ChainID { + // TODO: retrieve from external + unimplemented!() +} mod environment { /// The current block number being processed. Set by `execute_block`. @@ -67,19 +125,27 @@ mod environment { /// Get the block hash of a given block. pub fn block_hash(_number: BlockNumber) -> Hash { unimplemented!() } - /// ? - fn set_digest(_preserialised_rlp_digest: &[u8]) { unimplemented!() } - /// Get the current user's ID pub fn current_user() -> AccountID { unimplemented!() } + pub fn execute_block(_block: &Block) -> Vec { + // TODO: populate environment from header. + staking::pre_transactions(); + // TODO: go through each transaction and use execute_transaction to execute. + staking::post_transactions(); + // TODO: ensure digest in header is what we expect from transactions. + Vec::new() + } + /// Execute a given transaction. - pub fn execute_transaction(_tx: &[u8]) -> Vec { + pub fn execute_transaction(_tx: &Transaction) -> Vec { // TODO: decode data and ensure valid - // TODO: ensure signature valid and recover id + // TODO: ensure signature valid and recover id (use authentication::authenticate) // TODO: ensure target_function valid // TODO: decode parameters + // TODO: set `current_user` to the id // TODO: make call + // TODO: reset `current_user` // TODO: encode any return Vec::new() } @@ -89,8 +155,11 @@ mod environment { set_storage(b"\0code", new) } - /// ? - fn set_active_parachains(_data: &[u8]) { unimplemented!() } + /// Set the light-client digest for the header. + pub fn set_digest(_preserialised_rlp_digest: &[u8]) { + // TODO: Mention this to the external environment? + unimplemented!() + } } mod consensus { @@ -160,6 +229,14 @@ mod consensus { // TODO: Call set_authorities(). unimplemented!() } + + /// Hook to be called prior to transaction processing. + pub fn pre_transactions() {} + + /// Hook to be called after to transaction processing. + pub fn post_transactions() { + // TODO: check block number and call next_session if necessary. + } } mod staking { @@ -174,15 +251,10 @@ mod staking { /// The balance of a given account. fn balance(_who: AccountID) -> Balance { unimplemented!() } - /// User-level function to move funds onto a parachain. Calls `parachains::credit_parachain`. - fn move_to_parachain(chain_id: ChainID, value: Balance) { unimplemented!() } + /// Transfer some unlocked staking balance to another staker. + fn transfer_stake(_who: AccountID, dest: AccountID, value: Balance) { unimplemented!() } - /// System-level function to be called only by Parachains object when funds have left that - /// object and are to be credited here. - fn credit_staker(value: Balance) { unimplemented!() } - - /// Declare the desire to stake under the requirement that under flawless operation, each era - /// should return `minimum_era_return` on the amount staked. + /// Declare the desire to stake. /// /// Effects will be felt at the beginning of the next era. fn stake(minimum_era_return: Proportion) { unimplemented!() } @@ -192,22 +264,16 @@ mod staking { /// Effects will be felt at the beginning of the next era. fn unstake() { unimplemented!() } - /// Report invalid behaviour by a staking participant. - fn complain(complaint: Complaint) { unimplemented!() } -} + /// Hook to be called prior to transaction processing. + pub fn pre_transactions() { + conensus::pre_transactions(); + } -/* -mod parachains { - fn chain_ids(self) -> [ ChainID ]; - fn validation_function(self, chain_id: ChainID) -> Fn(consolidated_ingress: [ ( ChainID, bytes ) ], balance_downloads: [ ( AccountID, Balance ) ], block_data: bytes, previous_head_data: bytes) -> (head_data: bytes, egress_queues: [ [ bytes ] ], balance_uploads: [ ( AccountID, Balance ) ]); - fn validate_and_calculate_fees_function(self, chain_id: ChainID) -> Fn(egress_queues: [ [ bytes ] ], balance_uploads: [ ( AccountID, Balance ) ]) -> Balance; - fn balance(self, chain_id: ChainID, id: AccountID) -> Balance; - fn verify_and_consolidate_queues(self, unprocessed_ingress: [ [ [ bytes ] ] ]) -> [ (chain_id: ChainID, message: bytes) ]; - fn chain_state(self, chain_id: ChainID) -> ParachainState; - fn move_to_staking(mut self, chain_id: ChainID, value: Balance); - fn credit_parachain(mut self, chain_id: ChainID, value: Balance); - fn download(mut self, chain_id: ChainID, value: Balance, instruction: bytes); - fn update_heads(mut self, candidate_receipts: &[ ( ChainID, CandidateReceipt ) ]); + /// Hook to be called after to transaction processing. + pub fn post_transactions() { + // TODO: check block number and call next_era if necessary. + conensus::post_transactions(); + } } mod authentication { @@ -215,7 +281,7 @@ mod authentication { fn nonce(self, id: AccountID) -> TxOrder; fn authenticate(mut self, tx: Transaction) -> AccountID; } -*/ + mod timestamp { fn timestamp() -> Timestamp { unimplemented!() } fn set_timestamp(Timestamp) { unimplemented!() } From 5ab59bb171c43e09351cb17da0e043557ebd72f9 Mon Sep 17 00:00:00 2001 From: Gav Date: Mon, 8 Jan 2018 19:32:46 +0100 Subject: [PATCH 003/112] Make initial runtime skeleton compile. --- substrate/runtime/polkadot/src/lib.rs | 173 ++++++++++-------- substrate/runtime/support/src/lib.rs | 50 +++-- .../release/runtime_polkadot.compact.wasm | Bin 3042 -> 218 bytes .../release/runtime_polkadot.wasm | Bin 3130 -> 341 bytes .../release/runtime_test.compact.wasm | Bin 3042 -> 3392 bytes .../release/runtime_test.wasm | Bin 3130 -> 3480 bytes substrate/runtime/test/src/lib.rs | 2 +- 7 files changed, 123 insertions(+), 102 deletions(-) diff --git a/substrate/runtime/polkadot/src/lib.rs b/substrate/runtime/polkadot/src/lib.rs index d2143f28cd..4993b009b4 100644 --- a/substrate/runtime/polkadot/src/lib.rs +++ b/substrate/runtime/polkadot/src/lib.rs @@ -8,75 +8,54 @@ use alloc::vec::Vec; #[macro_use] extern crate runtime_support; -use runtime_support::{set_storage, storage, storage_into, print, Value20}; - -/* -use std::sync::{rc, RefCell, Once, ONCE_INIT}; -use std::mem; - -#[derive(Clone)] -struct SingletonReader { - inner: Rc>, -} - -fn singleton() -> SingletonReader { - // Initialize it to a null value - static mut SINGLETON: *const SingletonReader = 0 as *const SingletonReader; - static ONCE: Once = ONCE_INIT; - - unsafe { - ONCE.call_once(|| { - // Make it - let singleton = SingletonReader { - inner: Rc::new(RefCell::new(Default::default())), - }; - - // Put it in the heap so it can outlive this call - SINGLETON = mem::transmute(Box::new(singleton)); - }); - - // Now we give out a copy of the data that is safe to use concurrently. - (*SINGLETON).clone() - } -} -*/ +use runtime_support::{set_storage, storage, storage_into}; /// The hash of an ECDSA pub key which is used to identify an external transactor. -type AccountID = [u8; 32]; +pub type AccountID = [u8; 32]; /// The ECDSA pub key of an authority. This is what the external environment/consensus algorithm /// refers to as a "authority". -type SessionKey = [u8; 65]; -type Balance = u64; -type ChainID = u64; -type Hash = [u8; 32]; -type BlockNumber = u64; -/// A proportion (rational number). -struct Proportion { nom: u64, denom: u64, }; -type Timestamp = u64; -type TxOrder = u64; +pub type SessionKey = AccountID; +pub type Balance = u64; +pub type ChainID = u64; +pub type Hash = [u8; 32]; +pub type BlockNumber = u64; +pub type Timestamp = u64; +pub type TxOrder = u64; -struct Digest { - logs: Vec>, +/// The functions that a transaction can call (and be dispatched to). +pub enum Function { + StakingStake(), + StakingUnstake(), + ConsensusSetSessionKey(SessionKey), } -struct Header { - parent_hash: Hash, - number: BlockNumber, - state_root: Hash, - transaction_root: Hash, - digest: Digest, +impl Function { + /// Dispatch the function. + pub fn dispatch(self) -> Vec { unimplemented!() } } -struct Transaction { - senders: Vec, - function_name: String, - input_data: Vec, - nonce: TxOrder, +pub struct Digest { + pub logs: Vec>, } -struct Block { - header: Header, - transactions: Vec, +pub struct Header { + pub parent_hash: Hash, + pub number: BlockNumber, + pub state_root: Hash, + pub transaction_root: Hash, + pub digest: Digest, +} + +pub struct Transaction { + pub senders: Vec, + pub function: Function, + pub input_data: Vec, + pub nonce: TxOrder, +} + +pub struct Block { + pub header: Header, + pub transactions: Vec, } impl Header { @@ -97,21 +76,58 @@ impl Block { } } +/* +use std::sync::{rc, RefCell, Once, ONCE_INIT}; +use std::mem; + +#[derive(Default)] +struct Environment { + header: Option
, + current_user: Option, +} + +#[derive(Clone)] +struct EnvironmentHolder { + inner: Rc>, +} + +fn get_environment() -> EnvironmentHolder { + // Initialize it to a null value + static mut SINGLETON: *const EnvironmentHolder = 0 as *const EnvironmentHolder; + static ONCE: Once = ONCE_INIT; + + unsafe { + ONCE.call_once(|| { + // Make it + let singleton = EnvironmentHolder { + inner: Rc::new(RefCell::new(Default::default())), + }; + + // Put it in the heap so it can outlive this call + SINGLETON = mem::transmute(Box::new(singleton)); + }); + + // Now we give out a copy of the data that is safe to use concurrently. + (*SINGLETON).clone() + } +} +*/ + // TODO: include RLP implementation // TODO: add keccak256 (or some better hashing scheme) & ECDSA-recover (or some better sig scheme) -impl_stub!(execute_block); fn execute_block(_input: Vec) -> Vec { let block = Block::from_rlp(&_input); environment::execute_block(&block) } -impl_stub!(execute_transaction); fn execute_transaction(_input: Vec) -> Vec { let tx = Transaction::from_rlp(&_input); environment::execute_transaction(&tx) } +impl_stubs!(execute_block, execute_transaction); + /// The current relay chain identifier. fn chain_id() -> ChainID { // TODO: retrieve from external @@ -119,6 +135,8 @@ fn chain_id() -> ChainID { } mod environment { + use super::*; + /// The current block number being processed. Set by `execute_block`. pub fn block_number() -> BlockNumber { unimplemented!() } @@ -163,6 +181,8 @@ mod environment { } mod consensus { + use super::*; + fn value_vec(mut value: usize, initial: Vec) -> Vec { let mut acc = initial; while value > 0 { @@ -177,11 +197,11 @@ mod consensus { } fn authority(index: usize) -> AccountID { - storage_into::(&value_vec(index, b"\0authority".to_vec())) + storage_into(&value_vec(index, b"\0authority".to_vec())).unwrap() } fn set_authority_count(count: usize) { - (count..authority_count()).for_each(|i| set_authority(i, &[])); + (count..authority_count()).for_each(|i| set_authority(i, SessionKey::default())); set_storage(b"\0authority_count", &value_vec(count, Vec::new())); } @@ -191,7 +211,7 @@ mod consensus { /// Get the current set of authorities. These are the session keys. pub fn authorities() -> Vec { - (0..authority_count()).into_iter().map(authority).map.collect() + (0..authority_count()).into_iter().map(authority).collect() } /// Set the current set of authorities' session keys. @@ -199,7 +219,7 @@ mod consensus { /// Called by `next_session` only. fn set_authorities(authorities: &[AccountID]) { set_authority_count(authorities.len()); - authorities.iter().enumerate().for_each(|(v, i)| set_authority(v, i)); + authorities.iter().enumerate().for_each(|(v, &i)| set_authority(v, i)); } /// Get the current set of validators. These are the long-term identifiers for the validators @@ -215,9 +235,6 @@ mod consensus { unimplemented!() } - /// Flush out any statistics. - pub fn flush_statistics() -> Statistics { unimplemented!() } - /// Sets the session key of `_validator` to `_session`. This doesn't take effect until the next /// session. pub fn set_session_key(_validator: AccountID, _session: AccountID) { @@ -240,6 +257,8 @@ mod consensus { } mod staking { + use super::*; + /// The length of a staking era in blocks. fn era_length() -> BlockNumber { unimplemented!() } @@ -252,12 +271,12 @@ mod staking { fn balance(_who: AccountID) -> Balance { unimplemented!() } /// Transfer some unlocked staking balance to another staker. - fn transfer_stake(_who: AccountID, dest: AccountID, value: Balance) { unimplemented!() } + fn transfer_stake(_who: AccountID, _dest: AccountID, _value: Balance) { unimplemented!() } /// Declare the desire to stake. /// /// Effects will be felt at the beginning of the next era. - fn stake(minimum_era_return: Proportion) { unimplemented!() } + fn stake() { unimplemented!() } /// Retract the desire to stake. /// @@ -266,23 +285,27 @@ mod staking { /// Hook to be called prior to transaction processing. pub fn pre_transactions() { - conensus::pre_transactions(); + consensus::pre_transactions(); } /// Hook to be called after to transaction processing. pub fn post_transactions() { // TODO: check block number and call next_era if necessary. - conensus::post_transactions(); + consensus::post_transactions(); } } mod authentication { - fn validate_signature(self, tx: Transaction) -> ( AccountID, TxOrder ); - fn nonce(self, id: AccountID) -> TxOrder; - fn authenticate(mut self, tx: Transaction) -> AccountID; + use super::*; + + fn validate_signature(_tx: Transaction) -> ( AccountID, TxOrder ) { unimplemented!() } + fn nonce(_id: AccountID) -> TxOrder { unimplemented!() } + fn authenticate(_tx: Transaction) -> AccountID { unimplemented!() } } mod timestamp { + use super::*; + fn timestamp() -> Timestamp { unimplemented!() } - fn set_timestamp(Timestamp) { unimplemented!() } + fn set_timestamp(_now: Timestamp) { unimplemented!() } } diff --git a/substrate/runtime/support/src/lib.rs b/substrate/runtime/support/src/lib.rs index 4430f7249f..3114446880 100644 --- a/substrate/runtime/support/src/lib.rs +++ b/substrate/runtime/support/src/lib.rs @@ -3,9 +3,9 @@ #![cfg_attr(feature = "strict", deny(warnings))] #![feature(alloc)] - extern crate alloc; use alloc::vec::Vec; +use core::mem; extern crate pwasm_libc; extern crate pwasm_alloc; @@ -33,22 +33,18 @@ pub fn storage(key: &[u8]) -> Vec { } } -pub trait IsValue { - const value: usize; -} - -pub struct Value20; impl IsValue for Value20 { const value = 20usize; } -pub struct Value32; impl IsValue for Value32 { const value = 32usize; } -pub struct Value64; impl IsValue for Value64 { const value = 64usize; } -pub struct Value65; impl IsValue for Value65 { const value = 65usize; } - -pub fn storage_into(key: &[u8]) -> Option<[u8; T::value]> { - let mut result = [0u8; T::value]; - let written = unsafe { - ext_get_storage_into(&key[0], key.len() as u32, &result[0], result.len()) - }; +pub fn storage_into(key: &[u8]) -> Option { + let mut result: T; + let size = mem::size_of::(); + let mut written; + unsafe { + result = mem::uninitialized(); + let result_as_byte_blob = mem::transmute::<*mut T, *mut u8>(&mut result); + written = ext_get_storage_into(&key[0], key.len() as u32, result_as_byte_blob, size as u32) as usize; + } + // Only return a fully written value. match written { - T::value => Some(result), + size => Some(result), _ => None, } } @@ -93,18 +89,20 @@ pub fn print(value: T) { } #[macro_export] -macro_rules! impl_stub { - ($name:ident) => { +macro_rules! impl_stubs { + ( $( $name:ident ),* ) => { pub mod _internal { - #[no_mangle] - pub fn $name(input_data: *mut u8, input_len: usize) -> u64 { - let input = unsafe { - super::alloc::vec::Vec::from_raw_parts(input_data, input_len, input_len) - }; + $( + #[no_mangle] + pub fn $name(input_data: *mut u8, input_len: usize) -> u64 { + let input = unsafe { + super::alloc::vec::Vec::from_raw_parts(input_data, input_len, input_len) + }; - let output = super::$name(input); - &output[0] as *const u8 as u64 + ((output.len() as u64) << 32) - } + let output = super::$name(input); + &output[0] as *const u8 as u64 + ((output.len() as u64) << 32) + } + )* } } } diff --git a/substrate/runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm index 6ce8afb77ce2136b71e41d74bf115b4c8f918264..be2ae9b30e8d7d68992f083914c317bed5487e55 100644 GIT binary patch literal 218 zcmXwyTMmLS6h!B?r6Sb?!Uk|Bx(EMxc{M~R28!a3Y+dm2F_}5ZBnNrl5CDo*Mib`H zl!yc=P$F*As%-1!iCL#+%!_yZg_!$Gx4+ z!}0!T`$bPkp3ixHFH8z`D(LM!J9yo!Xz_}JQGYlV5ie*ne+Y|HJ37iz5hp?_p|v~^ zB95f!q+i9!UT<%I^jZl!?j4RdcecmdoBg3kJEJ48PkS%=!_A}NH~ry`$ddOy7#)1K zEh+M!=F%Uej3=b4SglRJUXUKFC{fFGC%nL@ioGPeTSp+>-CAup>ElXUW#~?+YVDK| z#w#BB*hgOR@A2g_uau8V;nliR2D)-w#l{P-R}~Cn7awEPHqid7Bg+X1!giYc%euV^ zYRQzEx)ei4mN9wK;6;`DHi=bLvVh(R%(tl=l(Kfdy`su8_O2APOc_>(=|=q)rKO&# zveiZlr(>-uqq~%!F8EVWIbGqV*v!(P6+nvCyz_EElfi8vd`{VT1Ro{%S~?&DZyH6P zGo;NQ00m$SjnAvZO2cx6(HQvHdWwD+k4r6JfDk}^)Y|^`Rmr{(4Gvf;cKEV)*$T%bsNbn+XnKxty z6^#1)k%IxR0%G2-stjDh3T?cVp>UYDgIf7w1G&vWa702m&X!DptvEi@0^uxpUm$5H5Z-KBAcz{` z>K=27HpwpkIoW5j8ykb`at0`jLm5;kgGx3jt`VZfxh}#W??ojqMY^3Vm7&UTG@uAP zHe8J0asW{ZB?nl5AixO-0<5djL~l+D;r|`^vZzpYS9KI8Y1Yb(EnK@icYf}|#rf{S zrOQ_qmwcx)Taed-|M&l;AZv?~II|#YRMbgzFZ1#37bnKhUj$d#z^7c@2?fGz+{H0K{$uato>`HDnLFGlXIkeq3t&#$-Zd()=%W*0 z&Tf0l_S%`i6m|*n08CRc+~aU5FfJ}A6_hsuI){BeY`WZe3~!#aN8_^%H&1gAt{5M) z;}ALeY5Ak&zgc3k=TRd%|r~^)0e8-?BR@9SKj6#Dd zd<2X+BA&X?UFJ*O?xH0iFKGc1oRC`xR`HrkkN_wN7EW9Shd_ju#l2*V*5(%J3dG1F z9dwpx5$x6Ggi9C#8t8_k;1=o!+zQj5AAE<;AL4tw9r*P?DVAO`xCBbOz@56ZUGCJS zoo_1mVpGo-LIvBork>B6kZ9*jfURRfK9z>9La%MegA^u&))^|n*@i>YV=gz;0cja( zgJgy{BB=>6N=(2U*99BHb-|}ZH(`v>O&AJv6FwkXXeOeyaBX}m_2jgpgcs6#yhZa4 zQ)tNijH)$1!BiEoF^zCW{B+QGl1U)RJn}_)+z(!dcNi7}MFb9ajPMZ`Zg_w3ODw#< z0Adaq6jT|R1jAA_1P=a!R}5*Re?%w*;Vztgol@7t{o%pUSdcgR+5S!sPcM`4l7_iu z(&i+0Z;1)9lFPxRV6{hvPKkOfV-P@@I{U%I`*R$V$3Fe(Jv1qLR T&JLgG3A7Ybp7PlGXgK~GM3S9O diff --git a/substrate/runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm b/substrate/runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm index 9fe583e7e40eeab56bf09d407ddd10c4e9070248..228d1aaf0c24cc037dfc52fcf4da91896ab05f32 100644 GIT binary patch literal 341 zcmYLE%Wi})3>+unnXSaCx1RWv?nmqySn5`&n}8tf<5GUT3AEy1duC*NY&4T00Q45s zw7>@~wOp1^gwH=UAkL9wdrSG@s?U)b2s97WG}mk2f_8yTJ3JwRpw|vIroZu~Y%^>o zc3#L*DU}d{pcD;2Bnii4$YR5$AD;p*{NQ$WTwT1$H=@^n?#9MWP3yYeB0i4u9pWC!?+9uuinwAu`P@trUUNV)^sE2+4B%~y5++sI&BIhO0 z12qT4nLD3>D;F+&gnj^yJ#yfPIPsf(wH>4XS?99&W&i>}luGl>qN+E>2k?hEc z*a;?+iJV}FKQ)0Mga8C%`D#Z9^@B`<-smLleN}Hi8~1ubFuTO;^IpBZyT5<%bhqy9 zZ6DPKyA$dOI`JtZ_YA)yvpB}z!G_=>~4TlFOf3xWgk9u{Z(qfgvaeq{cfY)d< zkJ;H)VUV>%6bmV(5@9G0g@^(vI>~2gJnRh*#xIpHb?>O&-rKErxBDZ}>Wq)UKIuL0 zkG79TU-n0PB4b_l%On_he=LjGk34>Rh<4}?U$msieqLyOCuKCDu#D8k^y>tLgEb{8 zxoL$H7?qKeWcI57q`P0KEh}AAhDK?+Q>ZGmN(k)~4_)K}r}+2ya$!p4qCz;eX_bbp ztjkC{;lg!=g|Ul^FluX9|Jjkngal!`klc%^y$)(f7cq4yf{iQ^auk9WW#-x>)>Xj* zdLuC3reaXY%DVQNDvHF}LeMIu(Du`f`7KI{cxuY4HdZ(tTa_u@rEIS7hoEArVW-%f zrryef6l^%_{05@k5&#ttr5=ktPWedWcNW00!I`KH$bX3+=xMyLTDOJ_zpx9F|kdVzR&tM0|dn zjtPPu_~Wuq3L}&pK(sDpx2!J~5O68|A}B|$qAUl9V2GpEO=WWi7yb|Y+4|Q8scgnbBZ>}F8?{%Ph~eY2G`{bP#F6% zC{YHbY*IW#h#Kd*2!p&A6s(GLo2g1)WjGp81Rh&9LU1{ND20LpEI<(87z6uY3RR|4Ttu1|@N3 zK~|`!S#_`S@y#c*#n4{_SJ}WNT-^xkNtM`TbLGs%wBLlQTT+uKoE-@&7MZYVD@w8W z$8a7M+`{lK`X(}$^QS~a3-gh7NccgSB4s%)xE&z<5QUCA1N{~RH8f42k_=`)z%1u3 zjsfx?dnfnIk}Q_F!;SJ(>%3+F%)ISgqZ~@_&44+(?X8+?X9AO(705j>O~r7J!==Eu zSZ|b5)(Gev_IbDIa_2F;IctyFrCWB979d>HE@Hu3?;>o^F-fabP%(nK-zIPLHqgPK@VpRZ%&8&vKBV9XJ5)P?OTU+QKbEdhB+OOW7% z+(MwmI+q{;P!cShxC{<~@GXmbNsZQKm+1<`$fD5Otk5#ptIY{lFa$KP^+~}k)D5^5 zCOw|G17>wyxeUedS(3bVwWx-ebt)P-4WD)?ek&lh|Jn}w#H&ugD(=d_2d zqkTRVny$jGt;vDp+K1L^D!`eBL(^j})6@ZJX=;O{nm8hf_A!dJ#~jxMFNW)aPl;~A z7@?am6zC>=K(x?Q1RMU^_*#aOc}MXtq_=pB<{hTckog%^h5Q6lWx$Jt2xq`ghY(LP z2_%_EzDO7H&%eW<3=|PK+%duhT)6)I#V;}c{sM>@WH3-gFdv5VVWeXy6sjR``zO3@ zDAeKi2#_G$kf&d?)YVacba-3~ayoo^u-C(bOsA~UFt>CveQ48Not^CN_wlwp7#|7T zZ8~Sg)3Vn>x1RM!{i82>d!?XXg--A&cLy)Pyb(GQ&8olgF=loGjYb!99$O!e>c0R6 CpR&{d diff --git a/substrate/runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm b/substrate/runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm index 6ce8afb77ce2136b71e41d74bf115b4c8f918264..bac77de7ffc344d73e46f9c32657563efb790174 100644 GIT binary patch literal 3392 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 T&JLgG3A7Ybp7PlGXgK~GM3S9O diff --git a/substrate/runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm b/substrate/runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm index 9fe583e7e40eeab56bf09d407ddd10c4e9070248..9f8b8bc2e8ffe194480b62236bf55efa0870ed80 100644 GIT binary patch literal 3480 zcmcgv&2k&Z5$>6t{hisxQldmrq{!K|6U$CyBPoS)B|e~CrsN!4KIcTyA}j+ENEHdv z(IJK^0>pc$I)yyQ!{k&rDvEhm_UQR`sOi_{+r68;qgT_{NwcC%hTbINQRp-d^(&S96o=3 z^5k$jJUTd=o}3;&9g>puLe?i?k@V|{;pEASmz{(S62r;lDz!^zoj+KJ>M^5S%K zJf%o<^kj_HR0on;sk;P7e=8$7I(| z&oTUB_;hr9aDM#t==g}7$ckZQicT=7k|{Bym(0DWP4Ip#S5*9Uqxh3DGd)=Rd15oZ ztEpA{C3!-x(O!AQYTBAdrSiIooVILg-A4PRX44p_tPf)^qDDTSZPjH1;hH=YY3s>H zdm0L%-5d0JmPr18r&K(Hl6YZ&9$aBU3lV*nu&U@)AGnLbe4zat#Z^sZiifL_7{PVq@+PZ(uzAJ)oR zHf|y=8pQ<{kIDdg(Zql%bw-e5jUEsnG|F$0|7rAOz>PLNL+$?7BK2DBzl%3OvRQJ8q>KRErAeZ z0E8$-YS}-p=@K`85z|Y0)|ODheYSPNA90KWRhz{$^WEr zt=im|clDr7eGbEafRT`w^-jqptgVy9W>G%hhub6j5V(Jl9J~_{%$9+KxCi`XN^X|%0lM7^# z^`+1EwChX}kNp^5*|;vC2iE%T;LIoC;F9}etO^2#gfHqItX9=zZ>g zYL>$Bok4JzpgS~5%Bj1Av<$?-6{k%owS?f=Ivv2n%T71bFJRJ^djX@Y#KM zg8T3Y$O}ldAoQWIr{ocQZE#~`Ca4z!67;}h22qn_7pjy@57ePE{x@+CDPqKmqSK&| zpAn*#?W<|Xo@g{iIpS)h}sw9HhUO|C-+ff;GEDG^cmq^K?FlN z)OgSj8qDDK=7NBvloR7J_+%wp3>*j-Vl`psc`|4-NxCd#Nddl?rzbQbJ>lF+dIrft z(i2C02J?g0; z3!j5MF50}@1({avH*ow)offy&7fYR9U~#`*>I|uaHxIA5=tRgb@DASwXIJi5&P$x=(UCtoU@AyAQ_X7|Xl341E9mKP8?}vA2+~6S((Q<4td(V1{$Er!C zAyD=_e|Fem^_N(cG=|0hE1Ty0gq)G2e>1zBoLxfCFRY}Lcerlh)!pS9v+rGvP~q;Z zqQ1iwWbZB!x*GKzUW3#-3xq=aK$=noq=Hbn>vqJ8qMP7rkp3Aa@aSAe_igK)TvQ28 z{HR>#bxgj6+GoGq<{RiE5hBRmL>K7&NSx!HO1olYi#IThorV)!xqI}T>SAZY1^iac z%agnMl|m&Ww)KUFI!==aZSgH=*hSnyV_*w_#haLc$sj5r7LmD)89*bn15>sz+73H} zT63P_B`I(5Hm0`%4EOiTO}>NS?at2~bT?5Ipm38SL4tKjV_{44_m5xU-+$=aP(GrR zsN7Ad1}b->yT0pE4OH%WxW(?8R0EY;vn-ib+kh6T2uY~Q@-CXvvPa`=h#n|Uf>_uP zcRZIpj4~UbMTIm}3s4|-Hl`;hM?>Ou>^VH2esyv>n!Y6VwthW4cye-%9~j)X zcJ-$Pe`Mp)@r!e;d{5SNdVV0AiBLDXB%3aN^q@|$c5%dLct&`YY)@q0nEa7!{^jU+ UboSNos3Cr(Y>MAV{^VKnUuVwX;Q#;t literal 3130 zcmcguPj6dA5Z~SR*Kc>9pWC!?+9uuinwAu`P@trUUNV)^sE2+4B%~y5++sI&BIhO0 z12qT4nLD3>D;F+&gnj^yJ#yfPIPsf(wH>4XS?99&W&i>}luGl>qN+E>2k?hEc z*a;?+iJV}FKQ)0Mga8C%`D#Z9^@B`<-smLleN}Hi8~1ubFuTO;^IpBZyT5<%bhqy9 zZ6DPKyA$dOI`JtZ_YA)yvpB}z!G_=>~4TlFOf3xWgk9u{Z(qfgvaeq{cfY)d< zkJ;H)VUV>%6bmV(5@9G0g@^(vI>~2gJnRh*#xIpHb?>O&-rKErxBDZ}>Wq)UKIuL0 zkG79TU-n0PB4b_l%On_he=LjGk34>Rh<4}?U$msieqLyOCuKCDu#D8k^y>tLgEb{8 zxoL$H7?qKeWcI57q`P0KEh}AAhDK?+Q>ZGmN(k)~4_)K}r}+2ya$!p4qCz;eX_bbp ztjkC{;lg!=g|Ul^FluX9|Jjkngal!`klc%^y$)(f7cq4yf{iQ^auk9WW#-x>)>Xj* zdLuC3reaXY%DVQNDvHF}LeMIu(Du`f`7KI{cxuY4HdZ(tTa_u@rEIS7hoEArVW-%f zrryef6l^%_{05@k5&#ttr5=ktPWedWcNW00!I`KH$bX3+=xMyLTDOJ_zpx9F|kdVzR&tM0|dn zjtPPu_~Wuq3L}&pK(sDpx2!J~5O68|A}B|$qAUl9V2GpEO=WWi7yb|Y+4|Q8scgnbBZ>}F8?{%Ph~eY2G`{bP#F6% zC{YHbY*IW#h#Kd*2!p&A6s(GLo2g1)WjGp81Rh&9LU1{ND20LpEI<(87z6uY3RR|4Ttu1|@N3 zK~|`!S#_`S@y#c*#n4{_SJ}WNT-^xkNtM`TbLGs%wBLlQTT+uKoE-@&7MZYVD@w8W z$8a7M+`{lK`X(}$^QS~a3-gh7NccgSB4s%)xE&z<5QUCA1N{~RH8f42k_=`)z%1u3 zjsfx?dnfnIk}Q_F!;SJ(>%3+F%)ISgqZ~@_&44+(?X8+?X9AO(705j>O~r7J!==Eu zSZ|b5)(Gev_IbDIa_2F;IctyFrCWB979d>HE@Hu3?;>o^F-fabP%(nK-zIPLHqgPK@VpRZ%&8&vKBV9XJ5)P?OTU+QKbEdhB+OOW7% z+(MwmI+q{;P!cShxC{<~@GXmbNsZQKm+1<`$fD5Otk5#ptIY{lFa$KP^+~}k)D5^5 zCOw|G17>wyxeUedS(3bVwWx-ebt)P-4WD)?ek&lh|Jn}w#H&ugD(=d_2d zqkTRVny$jGt;vDp+K1L^D!`eBL(^j})6@ZJX=;O{nm8hf_A!dJ#~jxMFNW)aPl;~A z7@?am6zC>=K(x?Q1RMU^_*#aOc}MXtq_=pB<{hTckog%^h5Q6lWx$Jt2xq`ghY(LP z2_%_EzDO7H&%eW<3=|PK+%duhT)6)I#V;}c{sM>@WH3-gFdv5VVWeXy6sjR``zO3@ zDAeKi2#_G$kf&d?)YVacba-3~ayoo^u-C(bOsA~UFt>CveQ48Not^CN_wlwp7#|7T zZ8~Sg)3Vn>x1RM!{i82>d!?XXg--A&cLy)Pyb(GQ&8olgF=loGjYb!99$O!e>c0R6 CpR&{d diff --git a/substrate/runtime/test/src/lib.rs b/substrate/runtime/test/src/lib.rs index 550e06c05d..e95844fdb0 100644 --- a/substrate/runtime/test/src/lib.rs +++ b/substrate/runtime/test/src/lib.rs @@ -53,7 +53,7 @@ pub fn set_authorities(authorities: &[&[u8]]) { authorities.iter().enumerate().for_each(|(v, i)| set_authority(v, i)); } -impl_stub!(test_data_in); +impl_stubs!(test_data_in); fn test_data_in(input: Vec) -> Vec { print(b"set_storage" as &[u8]); set_storage(b"input", &input); From b104f5e6e4166ca5c7492470aa98b7c68253dcfa Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 9 Jan 2018 13:47:28 +0100 Subject: [PATCH 004/112] Compile polkadot-runtime both for Wasm ad native, allowing for testing and direct usage. --- substrate/Cargo.lock | 11 ++++++++ substrate/Cargo.toml | 3 ++- substrate/executor/src/wasm_executor.rs | 10 +++---- substrate/native-runtime/Cargo.toml | 12 +++++++++ substrate/native-runtime/src | 1 + substrate/native-runtime/support/Cargo.toml | 7 +++++ substrate/native-runtime/support/src/lib.rs | 10 +++++++ .../{runtime => wasm-runtime}/Cargo.lock | 0 .../{runtime => wasm-runtime}/Cargo.toml | 0 substrate/{runtime => wasm-runtime}/build.sh | 0 substrate/{runtime => wasm-runtime}/init.sh | 0 .../polkadot/Cargo.toml | 5 ++++ .../polkadot/src/lib.rs | 25 ++++++++++-------- .../pwasm-alloc/Cargo.toml | 0 .../pwasm-alloc/README.md | 0 .../pwasm-alloc/src/lib.rs | 0 .../pwasm-libc/Cargo.toml | 0 .../pwasm-libc/README.md | 0 .../pwasm-libc/src/lib.rs | 0 .../support/Cargo.toml | 0 .../support/src/lib.rs | 15 ++++++----- .../wasm-runtime/target/debug/.cargo-lock | 0 .../dep-lib-pwasm_libc-e72991cbfafd2b71 | Bin 0 -> 409 bytes .../lib-pwasm_libc-e72991cbfafd2b71 | 1 + .../lib-pwasm_libc-e72991cbfafd2b71.json | 1 + .../deps/libpwasm_libc-e72991cbfafd2b71.rlib | Bin 0 -> 10670 bytes ...023388293df7da5.crate.allocator.rust-cgu.o | Bin 0 -> 1636 bytes ...b023388293df7da5.crate.metadata.rust-cgu.o | Bin 0 -> 184 bytes .../debug/deps/pwasm_libc-b023388293df7da5.d | 5 ++++ ...bc-b023388293df7da5.pwasm_libc0.rust-cgu.o | Bin 0 -> 2568 bytes ...bc-b023388293df7da5.pwasm_libc1.rust-cgu.o | Bin 0 -> 4208 bytes .../target/debug/libpwasm_libc.rlib | Bin 0 -> 10670 bytes .../wasm-runtime/target/release/.cargo-lock | 0 .../release/.cargo-lock | 0 .../dep-lib-pwasm_alloc-e37006629c0ab425 | Bin 0 -> 342 bytes .../lib-pwasm_alloc-e37006629c0ab425 | 1 + .../lib-pwasm_alloc-e37006629c0ab425.json | 1 + .../dep-lib-pwasm_libc-9375d1aea6d3c98f | Bin 0 -> 337 bytes .../lib-pwasm_libc-9375d1aea6d3c98f | 1 + .../lib-pwasm_libc-9375d1aea6d3c98f.json | 1 + .../dep-lib-runtime_polkadot | Bin 0 -> 306 bytes .../lib-runtime_polkadot | 1 + .../lib-runtime_polkadot.json | 1 + .../dep-lib-runtime_support-5482fb51bf4d410e | Bin 0 -> 338 bytes .../lib-runtime_support-5482fb51bf4d410e | 1 + .../lib-runtime_support-5482fb51bf4d410e.json | 1 + .../dep-lib-runtime_test | Bin 0 -> 286 bytes .../lib-runtime_test | 1 + .../lib-runtime_test.json | 1 + .../deps/libpwasm_alloc-e37006629c0ab425.rlib | Bin 0 -> 13718 bytes .../deps/libpwasm_libc-9375d1aea6d3c98f.rlib | Bin 0 -> 6310 bytes .../libruntime_support-5482fb51bf4d410e.rlib | Bin 0 -> 12778 bytes .../release/deps}/runtime_polkadot.wasm | Bin .../release/deps}/runtime_test.wasm | Bin .../release/libpwasm_alloc.d | 1 + .../release/libpwasm_alloc.rlib | Bin 0 -> 13718 bytes .../release/libpwasm_libc.d | 1 + .../release/libpwasm_libc.rlib | Bin 0 -> 6310 bytes .../release/libruntime_support.d | 1 + .../release/libruntime_support.rlib | Bin 0 -> 12778 bytes .../release/runtime_polkadot.compact.wasm | Bin .../release/runtime_polkadot.d | 1 + .../release/runtime_polkadot.wasm | Bin 0 -> 341 bytes .../release/runtime_test.compact.wasm | Bin .../release/runtime_test.d | 1 + .../release/runtime_test.wasm | Bin 0 -> 3480 bytes .../{runtime => wasm-runtime}/test/Cargo.toml | 0 .../{runtime => wasm-runtime}/test/src/lib.rs | 0 68 files changed, 98 insertions(+), 23 deletions(-) create mode 100644 substrate/native-runtime/Cargo.toml create mode 120000 substrate/native-runtime/src create mode 100644 substrate/native-runtime/support/Cargo.toml create mode 100644 substrate/native-runtime/support/src/lib.rs rename substrate/{runtime => wasm-runtime}/Cargo.lock (100%) rename substrate/{runtime => wasm-runtime}/Cargo.toml (100%) rename substrate/{runtime => wasm-runtime}/build.sh (100%) rename substrate/{runtime => wasm-runtime}/init.sh (100%) rename substrate/{runtime => wasm-runtime}/polkadot/Cargo.toml (75%) rename substrate/{runtime => wasm-runtime}/polkadot/src/lib.rs (93%) rename substrate/{runtime => wasm-runtime}/pwasm-alloc/Cargo.toml (100%) rename substrate/{runtime => wasm-runtime}/pwasm-alloc/README.md (100%) rename substrate/{runtime => wasm-runtime}/pwasm-alloc/src/lib.rs (100%) rename substrate/{runtime => wasm-runtime}/pwasm-libc/Cargo.toml (100%) rename substrate/{runtime => wasm-runtime}/pwasm-libc/README.md (100%) rename substrate/{runtime => wasm-runtime}/pwasm-libc/src/lib.rs (100%) rename substrate/{runtime => wasm-runtime}/support/Cargo.toml (100%) rename substrate/{runtime => wasm-runtime}/support/src/lib.rs (92%) create mode 100644 substrate/wasm-runtime/target/debug/.cargo-lock create mode 100644 substrate/wasm-runtime/target/debug/.fingerprint/pwasm-libc-e72991cbfafd2b71/dep-lib-pwasm_libc-e72991cbfafd2b71 create mode 100644 substrate/wasm-runtime/target/debug/.fingerprint/pwasm-libc-e72991cbfafd2b71/lib-pwasm_libc-e72991cbfafd2b71 create mode 100644 substrate/wasm-runtime/target/debug/.fingerprint/pwasm-libc-e72991cbfafd2b71/lib-pwasm_libc-e72991cbfafd2b71.json create mode 100644 substrate/wasm-runtime/target/debug/deps/libpwasm_libc-e72991cbfafd2b71.rlib create mode 100644 substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.crate.allocator.rust-cgu.o create mode 100644 substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.crate.metadata.rust-cgu.o create mode 100644 substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.d create mode 100644 substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.pwasm_libc0.rust-cgu.o create mode 100644 substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.pwasm_libc1.rust-cgu.o create mode 100644 substrate/wasm-runtime/target/debug/libpwasm_libc.rlib create mode 100644 substrate/wasm-runtime/target/release/.cargo-lock create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.cargo-lock create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-alloc-e37006629c0ab425/dep-lib-pwasm_alloc-e37006629c0ab425 create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-alloc-e37006629c0ab425/lib-pwasm_alloc-e37006629c0ab425 create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-alloc-e37006629c0ab425/lib-pwasm_alloc-e37006629c0ab425.json create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-libc-9375d1aea6d3c98f/dep-lib-pwasm_libc-9375d1aea6d3c98f create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-libc-9375d1aea6d3c98f/lib-pwasm_libc-9375d1aea6d3c98f create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-libc-9375d1aea6d3c98f/lib-pwasm_libc-9375d1aea6d3c98f.json create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/dep-lib-runtime_polkadot create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/lib-runtime_polkadot create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/lib-runtime_polkadot.json create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/dep-lib-runtime_support-5482fb51bf4d410e create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/lib-runtime_support-5482fb51bf4d410e create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/lib-runtime_support-5482fb51bf4d410e.json create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-test-0ee9f37942e84b82/dep-lib-runtime_test create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-test-0ee9f37942e84b82/lib-runtime_test create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-test-0ee9f37942e84b82/lib-runtime_test.json create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/deps/libpwasm_alloc-e37006629c0ab425.rlib create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/deps/libpwasm_libc-9375d1aea6d3c98f.rlib create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/deps/libruntime_support-5482fb51bf4d410e.rlib rename substrate/{runtime/target/wasm32-unknown-unknown/release => wasm-runtime/target/wasm32-unknown-unknown/release/deps}/runtime_polkadot.wasm (100%) rename substrate/{runtime/target/wasm32-unknown-unknown/release => wasm-runtime/target/wasm32-unknown-unknown/release/deps}/runtime_test.wasm (100%) create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libpwasm_alloc.d create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libpwasm_alloc.rlib create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libpwasm_libc.d create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libpwasm_libc.rlib create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libruntime_support.d create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libruntime_support.rlib rename substrate/{runtime => wasm-runtime}/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm (100%) create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.d create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm rename substrate/{runtime => wasm-runtime}/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm (100%) create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.d create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm rename substrate/{runtime => wasm-runtime}/test/Cargo.toml (100%) rename substrate/{runtime => wasm-runtime}/test/src/lib.rs (100%) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 15f526edd9..61afee3c0a 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -499,6 +499,13 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "native-runtime" +version = "0.1.0" +dependencies = [ + "runtime-support 0.1.0", +] + [[package]] name = "net2" version = "0.2.31" @@ -808,6 +815,10 @@ dependencies = [ "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "runtime-support" +version = "0.1.0" + [[package]] name = "rustc-demangle" version = "0.1.5" diff --git a/substrate/Cargo.toml b/substrate/Cargo.toml index a0f6303a67..bfbff56969 100644 --- a/substrate/Cargo.toml +++ b/substrate/Cargo.toml @@ -16,10 +16,11 @@ members = [ "primitives", "rpc", "rpc_servers", + "native-runtime", "serializer", "state_machine", "validator", ] exclude = [ - "runtime" + "wasm-runtime" ] diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index 4c3ed5b791..ff4b1a31a2 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -136,7 +136,7 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, } else { 0 } } else { 0 } }, - ext_deposit_log(_log_data: *const u8, _log_len: u32) { + ext_deposit_log(_log_data: *const u8, _log_len: u32) => { unimplemented!() } => <'e, E: Externalities + 'e> @@ -175,8 +175,8 @@ impl CodeExecutor for WasmExecutor { let returned = program .params_with_external("env", &mut fec) .map(|p| p - .add_argument(I32(offset as u32)) - .add_argument(I32(size as u32))) + .add_argument(I32(offset as i32)) + .add_argument(I32(size as i32))) .and_then(|p| module.execute_export(method, p)) .map_err(|_| -> Error { ErrorKind::Runtime.into() })?; @@ -233,8 +233,8 @@ mod tests { let returned = program .params_with_external("env", &mut fec) .map(|p| p - .add_argument(I32(offset as u32)) - .add_argument(I32(size as u32))) + .add_argument(I32(offset as i32)) + .add_argument(I32(size as i32))) .and_then(|p| module.execute_export("test_data_in", p)) .map_err(|_| -> Error { ErrorKind::Runtime.into() }).expect("function should be callable"); diff --git a/substrate/native-runtime/Cargo.toml b/substrate/native-runtime/Cargo.toml new file mode 100644 index 0000000000..c971a6d694 --- /dev/null +++ b/substrate/native-runtime/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "native-runtime" +version = "0.1.0" +authors = ["Parity Technologies "] + +[features] +default = ["with-std"] +with-std = [] +without-std = [] + +[dependencies] +runtime-support = { path = "./support", version = "0.1" } diff --git a/substrate/native-runtime/src b/substrate/native-runtime/src new file mode 120000 index 0000000000..12e3333860 --- /dev/null +++ b/substrate/native-runtime/src @@ -0,0 +1 @@ +../wasm-runtime/polkadot/src \ No newline at end of file diff --git a/substrate/native-runtime/support/Cargo.toml b/substrate/native-runtime/support/Cargo.toml new file mode 100644 index 0000000000..b9c56adf24 --- /dev/null +++ b/substrate/native-runtime/support/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "runtime-support" +version = "0.1.0" +authors = ["Parity Technologies "] + +[features] +strict = [] diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs new file mode 100644 index 0000000000..b1c41f4821 --- /dev/null +++ b/substrate/native-runtime/support/src/lib.rs @@ -0,0 +1,10 @@ +pub use std::vec::Vec; + +pub fn storage(_key: &[u8]) -> Vec { vec![] } +pub fn storage_into(_key: &[u8]) -> Option { None } +pub fn set_storage(_key: &[u8], _value: &[u8]) {} + +#[macro_export] +macro_rules! impl_stubs { + ($( $name:ident ),*) => {} +} diff --git a/substrate/runtime/Cargo.lock b/substrate/wasm-runtime/Cargo.lock similarity index 100% rename from substrate/runtime/Cargo.lock rename to substrate/wasm-runtime/Cargo.lock diff --git a/substrate/runtime/Cargo.toml b/substrate/wasm-runtime/Cargo.toml similarity index 100% rename from substrate/runtime/Cargo.toml rename to substrate/wasm-runtime/Cargo.toml diff --git a/substrate/runtime/build.sh b/substrate/wasm-runtime/build.sh similarity index 100% rename from substrate/runtime/build.sh rename to substrate/wasm-runtime/build.sh diff --git a/substrate/runtime/init.sh b/substrate/wasm-runtime/init.sh similarity index 100% rename from substrate/runtime/init.sh rename to substrate/wasm-runtime/init.sh diff --git a/substrate/runtime/polkadot/Cargo.toml b/substrate/wasm-runtime/polkadot/Cargo.toml similarity index 75% rename from substrate/runtime/polkadot/Cargo.toml rename to substrate/wasm-runtime/polkadot/Cargo.toml index a313da2a1e..ce2d9909a7 100644 --- a/substrate/runtime/polkadot/Cargo.toml +++ b/substrate/wasm-runtime/polkadot/Cargo.toml @@ -8,3 +8,8 @@ crate-type = ["cdylib"] [dependencies] runtime-support = { path = "../support", version = "0.1" } + +[features] +default = ["without-std"] +with-std = [] +without-std = [] diff --git a/substrate/runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs similarity index 93% rename from substrate/runtime/polkadot/src/lib.rs rename to substrate/wasm-runtime/polkadot/src/lib.rs index 4993b009b4..24529d4380 100644 --- a/substrate/runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -1,14 +1,9 @@ -#![no_std] -#![feature(lang_items)] +#![cfg_attr(feature = "without-std", no_std)] #![cfg_attr(feature = "strict", deny(warnings))] -#![feature(alloc)] -extern crate alloc; -use alloc::vec::Vec; - #[macro_use] extern crate runtime_support; -use runtime_support::{set_storage, storage, storage_into}; +use runtime_support::{set_storage, storage, storage_into, Vec}; /// The hash of an ECDSA pub key which is used to identify an external transactor. pub type AccountID = [u8; 32]; @@ -116,12 +111,12 @@ fn get_environment() -> EnvironmentHolder { // TODO: include RLP implementation // TODO: add keccak256 (or some better hashing scheme) & ECDSA-recover (or some better sig scheme) -fn execute_block(_input: Vec) -> Vec { +pub fn execute_block(_input: Vec) -> Vec { let block = Block::from_rlp(&_input); environment::execute_block(&block) } -fn execute_transaction(_input: Vec) -> Vec { +pub fn execute_transaction(_input: Vec) -> Vec { let tx = Transaction::from_rlp(&_input); environment::execute_transaction(&tx) } @@ -235,6 +230,11 @@ mod consensus { unimplemented!() } + /// The number of blocks in each session. + pub fn session_length() -> BlockNumber { + 10 + } + /// Sets the session key of `_validator` to `_session`. This doesn't take effect until the next /// session. pub fn set_session_key(_validator: AccountID, _session: AccountID) { @@ -260,11 +260,14 @@ mod staking { use super::*; /// The length of a staking era in blocks. - fn era_length() -> BlockNumber { unimplemented!() } + pub fn era_length() -> BlockNumber { sessions_per_era() * consensus::session_length() } + + /// The length of a staking era in sessions. + pub fn sessions_per_era() -> BlockNumber { 10 } /// The era has changed - enact new staking set. /// - /// NOTE: This is always a session change. + /// NOTE: This always happens on a session change. fn next_era() { unimplemented!() } /// The balance of a given account. diff --git a/substrate/runtime/pwasm-alloc/Cargo.toml b/substrate/wasm-runtime/pwasm-alloc/Cargo.toml similarity index 100% rename from substrate/runtime/pwasm-alloc/Cargo.toml rename to substrate/wasm-runtime/pwasm-alloc/Cargo.toml diff --git a/substrate/runtime/pwasm-alloc/README.md b/substrate/wasm-runtime/pwasm-alloc/README.md similarity index 100% rename from substrate/runtime/pwasm-alloc/README.md rename to substrate/wasm-runtime/pwasm-alloc/README.md diff --git a/substrate/runtime/pwasm-alloc/src/lib.rs b/substrate/wasm-runtime/pwasm-alloc/src/lib.rs similarity index 100% rename from substrate/runtime/pwasm-alloc/src/lib.rs rename to substrate/wasm-runtime/pwasm-alloc/src/lib.rs diff --git a/substrate/runtime/pwasm-libc/Cargo.toml b/substrate/wasm-runtime/pwasm-libc/Cargo.toml similarity index 100% rename from substrate/runtime/pwasm-libc/Cargo.toml rename to substrate/wasm-runtime/pwasm-libc/Cargo.toml diff --git a/substrate/runtime/pwasm-libc/README.md b/substrate/wasm-runtime/pwasm-libc/README.md similarity index 100% rename from substrate/runtime/pwasm-libc/README.md rename to substrate/wasm-runtime/pwasm-libc/README.md diff --git a/substrate/runtime/pwasm-libc/src/lib.rs b/substrate/wasm-runtime/pwasm-libc/src/lib.rs similarity index 100% rename from substrate/runtime/pwasm-libc/src/lib.rs rename to substrate/wasm-runtime/pwasm-libc/src/lib.rs diff --git a/substrate/runtime/support/Cargo.toml b/substrate/wasm-runtime/support/Cargo.toml similarity index 100% rename from substrate/runtime/support/Cargo.toml rename to substrate/wasm-runtime/support/Cargo.toml diff --git a/substrate/runtime/support/src/lib.rs b/substrate/wasm-runtime/support/src/lib.rs similarity index 92% rename from substrate/runtime/support/src/lib.rs rename to substrate/wasm-runtime/support/src/lib.rs index 3114446880..aaab93e960 100644 --- a/substrate/runtime/support/src/lib.rs +++ b/substrate/wasm-runtime/support/src/lib.rs @@ -1,10 +1,12 @@ #![no_std] #![feature(lang_items)] +#![feature(alloc)] #![cfg_attr(feature = "strict", deny(warnings))] #![feature(alloc)] +//#[macro_use] extern crate alloc; -use alloc::vec::Vec; +pub use alloc::vec::Vec; use core::mem; extern crate pwasm_libc; @@ -36,16 +38,17 @@ pub fn storage(key: &[u8]) -> Vec { pub fn storage_into(key: &[u8]) -> Option { let mut result: T; let size = mem::size_of::(); - let mut written; + let written; unsafe { result = mem::uninitialized(); let result_as_byte_blob = mem::transmute::<*mut T, *mut u8>(&mut result); written = ext_get_storage_into(&key[0], key.len() as u32, result_as_byte_blob, size as u32) as usize; } // Only return a fully written value. - match written { - size => Some(result), - _ => None, + if written == size { + Some(result) + } else { + None } } @@ -96,7 +99,7 @@ macro_rules! impl_stubs { #[no_mangle] pub fn $name(input_data: *mut u8, input_len: usize) -> u64 { let input = unsafe { - super::alloc::vec::Vec::from_raw_parts(input_data, input_len, input_len) + $crate::Vec::from_raw_parts(input_data, input_len, input_len) }; let output = super::$name(input); diff --git a/substrate/wasm-runtime/target/debug/.cargo-lock b/substrate/wasm-runtime/target/debug/.cargo-lock new file mode 100644 index 0000000000..e69de29bb2 diff --git a/substrate/wasm-runtime/target/debug/.fingerprint/pwasm-libc-e72991cbfafd2b71/dep-lib-pwasm_libc-e72991cbfafd2b71 b/substrate/wasm-runtime/target/debug/.fingerprint/pwasm-libc-e72991cbfafd2b71/dep-lib-pwasm_libc-e72991cbfafd2b71 new file mode 100644 index 0000000000000000000000000000000000000000..92c61885d84f13585667714e922ac63d3e89ddd5 GIT binary patch literal 409 zcmchSJr2S!3`UuA3NDaZ?NYTXXJAJ8aifZsSawpbPr?d9nOLk(pX{e+xC*jBFb7;B zBT(G##>WItBfIAONb8OunJ98PLDP0J958`Ln?so-u&tIV@K%D;I1ba)JG+?04|eQ3 hF7t@n+wrH_FD?HUr>_sq>IKdJl!pKS literal 0 HcmV?d00001 diff --git a/substrate/wasm-runtime/target/debug/.fingerprint/pwasm-libc-e72991cbfafd2b71/lib-pwasm_libc-e72991cbfafd2b71 b/substrate/wasm-runtime/target/debug/.fingerprint/pwasm-libc-e72991cbfafd2b71/lib-pwasm_libc-e72991cbfafd2b71 new file mode 100644 index 0000000000..cb6d43a3ff --- /dev/null +++ b/substrate/wasm-runtime/target/debug/.fingerprint/pwasm-libc-e72991cbfafd2b71/lib-pwasm_libc-e72991cbfafd2b71 @@ -0,0 +1 @@ +ba1707f874223553 \ No newline at end of file diff --git a/substrate/wasm-runtime/target/debug/.fingerprint/pwasm-libc-e72991cbfafd2b71/lib-pwasm_libc-e72991cbfafd2b71.json b/substrate/wasm-runtime/target/debug/.fingerprint/pwasm-libc-e72991cbfafd2b71/lib-pwasm_libc-e72991cbfafd2b71.json new file mode 100644 index 0000000000..e73f9ca5d1 --- /dev/null +++ b/substrate/wasm-runtime/target/debug/.fingerprint/pwasm-libc-e72991cbfafd2b71/lib-pwasm_libc-e72991cbfafd2b71.json @@ -0,0 +1 @@ +{"rustc":8291033049748019918,"features":"[]","target":14441046832906989149,"profile":731176819336294830,"deps":[],"local":[{"MtimeBased":[[1515500307,607755819],"/Users/gav/Core/polkadot/wasm-runtime/target/debug/.fingerprint/pwasm-libc-e72991cbfafd2b71/dep-lib-pwasm_libc-e72991cbfafd2b71"]}],"rustflags":[]} \ No newline at end of file diff --git a/substrate/wasm-runtime/target/debug/deps/libpwasm_libc-e72991cbfafd2b71.rlib b/substrate/wasm-runtime/target/debug/deps/libpwasm_libc-e72991cbfafd2b71.rlib new file mode 100644 index 0000000000000000000000000000000000000000..284e12e552798df2d3d6e5de9fd96601c0918b28 GIT binary patch literal 10670 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 Xk5~A7R5dzuyPJPu&DrP0@2>nGWWk?; literal 0 HcmV?d00001 diff --git a/substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.crate.allocator.rust-cgu.o b/substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.crate.allocator.rust-cgu.o new file mode 100644 index 0000000000000000000000000000000000000000..095c41adea2bd940449bc284431f91b9a03e463a GIT binary patch literal 1636 zcmcIku}&L75ZwbuSiy-6q%e{th(tkS6e=hvf*`^rL>6%oX*uk5Y{mGjJEK@m3KFG3 zG^RkJ;16ghDN<0<(YnY7KoNx!MG@i6-7FmE%ZY}O#&6!dx4UzzJD>gebv+=2(J%0W zBwVIq9Eli3p1W1}&n0;g4Mxqer=aX35g}z$wVGb-@%)=Y{*LQvj|?QdMNxHaC>lk@Eh2`)n-mTyYFS&!%Hgh>ETWY0fnA2&NanOB~+BTKL2=(jPRB zPJjO)^#z&A<*DS@ch~;dJh!tr5zlQePF%Ssbwba>B=pP_M*FQWS}7xy7>IZ9{2BBp zbN{?}LMC63Hiw*z(BDI!jL^S8Peh+0yAX|Al|v` zDvBf#jwvAVHRivW>vwjB{o}0D_eK6K=I@x}Y&X*Ef6W}!^*5NGFz+z0Gk?Xrgax!l z#{vpJj|KFl06z@)ivd0v@Y6Tz-@hB+-vS(eMAF`Ln$lKgt!5RaY892^xb2b(>ykOl z+S4PWWo_uKbV=<^$6T)|=~UZF%fS}eKG@bLS*^=P%`Dy;dz)l+Dt5L0vBw=?QvzWaMkn9zP|y+L^w1_nlE1|R{&Gk`RM0*GK>kOX2dAI!r|>_C$On#lmdATvQAKE5Qiq6ET* U@Izc9LJ)j(7P@&r`37V)06RttumAu6 literal 0 HcmV?d00001 diff --git a/substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.d b/substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.d new file mode 100644 index 0000000000..4116414cae --- /dev/null +++ b/substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.d @@ -0,0 +1,5 @@ +/Users/gav/Core/polkadot/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5: /Users/gav/Core/polkadot/wasm-runtime/pwasm-libc/src/lib.rs + +/Users/gav/Core/polkadot/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.d: /Users/gav/Core/polkadot/wasm-runtime/pwasm-libc/src/lib.rs + +/Users/gav/Core/polkadot/wasm-runtime/pwasm-libc/src/lib.rs: diff --git a/substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.pwasm_libc0.rust-cgu.o b/substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.pwasm_libc0.rust-cgu.o new file mode 100644 index 0000000000000000000000000000000000000000..43bde99ac7b005f8b8998304557aa557a927c94e GIT binary patch literal 2568 zcmbVO&2Jk;6rZ)zG;LaU3l%CNg*`yk3SxUUjz2&}F>%ly3Ti`B0#dcC*X!89U)|k= zf{*|e0T!ynffK5bxN+phflEXY>7k+*{)8fNDB^-d1cLB;vondkO-bNMZ{B+|@BQYz znR#p9{^OUw_cNv?83r&(eIEt`40;&+<%m#s9KN6cP?lmq$_6GQPSGUDwnOhq80nFH zVQ%rlwym`DQXxFr_Q$bE!gyEtkhE>L+X=P-ZF?ARQ94siL>~c9rW#GeM%%7=)s-bX z2z{|)+m)Bg^UrU2y&|%A`Vo{~A;+7-`h*mWPL7X`%o?WV+QNW2Z;4ffkOV`@owZ1qR8 zBM{^DW@YeYiT4`b9nrA^(RT{!(D{*Z96W(_YRwkpbx7>X&Vh-@hnTLK;D-QU?}Zku z{!iAmGvvzG`rrRd%B36i^pVHjCzXlyt9Nzln)pCi?rp2TZuM6-to{$y#|s-Gpxj@p z^w+Gb-|3fbh$swh3!P(}J$vy5{nmp+3mG_w3ef_Ii?-eo=82oFPYLuA4wh69>7H; zN?H=X5y>G5aAmk-ftf}>j+6a6{CO7gtklaj`6f#Izd`&1o!Z{!P&GJDiqd1SHu+1WPf>R=8pl z%*SyFQ~CVc-V}fGxv!s{?O(pD_NMY^J`EQ|1)SaJ8BX1NRB#&=V=s^ z_}}4#O_vuMwOXNAEKJqhlI!O4W^E4bb^o41K%GzXdeO{Hd4)VL<#JKLR1nroKjc~Z ftPnc%LZeXPrD}0H&ui1QVztWQ>wEQdma%^TH_UR6 literal 0 HcmV?d00001 diff --git a/substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.pwasm_libc1.rust-cgu.o b/substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.pwasm_libc1.rust-cgu.o new file mode 100644 index 0000000000000000000000000000000000000000..97cda093e5671de857e2df2707019da063a4a503 GIT binary patch literal 4208 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 Xk5~A7R5dzuyPJPu&DrP0@2>nGWWk?; literal 0 HcmV?d00001 diff --git a/substrate/wasm-runtime/target/release/.cargo-lock b/substrate/wasm-runtime/target/release/.cargo-lock new file mode 100644 index 0000000000..e69de29bb2 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.cargo-lock b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.cargo-lock new file mode 100644 index 0000000000..e69de29bb2 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-alloc-e37006629c0ab425/dep-lib-pwasm_alloc-e37006629c0ab425 b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-alloc-e37006629c0ab425/dep-lib-pwasm_alloc-e37006629c0ab425 new file mode 100644 index 0000000000000000000000000000000000000000..a4da1cb1a4785e0602bfc1a4030bfe35b9ce362d GIT binary patch literal 342 zcmb`BK@Ng25Jg@06kecAQxqdx&fwY%?Sv3YOJ<5(U%|LjmlR)U(X??h22+3(GPsUW0 kJv)Q#!5#~K0QG)D^oD@2TdjgcslVrZZSkK&-Urs|4sPChY5)KL literal 0 HcmV?d00001 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-alloc-e37006629c0ab425/lib-pwasm_alloc-e37006629c0ab425 b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-alloc-e37006629c0ab425/lib-pwasm_alloc-e37006629c0ab425 new file mode 100644 index 0000000000..96fca0ffc7 --- /dev/null +++ b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-alloc-e37006629c0ab425/lib-pwasm_alloc-e37006629c0ab425 @@ -0,0 +1 @@ +ee4d5b5400bf9619 \ No newline at end of file diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-alloc-e37006629c0ab425/lib-pwasm_alloc-e37006629c0ab425.json b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-alloc-e37006629c0ab425/lib-pwasm_alloc-e37006629c0ab425.json new file mode 100644 index 0000000000..c1764b5654 --- /dev/null +++ b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-alloc-e37006629c0ab425/lib-pwasm_alloc-e37006629c0ab425.json @@ -0,0 +1 @@ +{"rustc":8294656847287967537,"features":"[]","target":1127969377865045195,"profile":42358739494345872,"deps":[["pwasm-libc v0.1.0 (file:///Users/gav/Core/polkadot/wasm-runtime/pwasm-libc)",6197225601014249845]],"local":[{"MtimeBased":[[1515500743,816953612],"/Users/gav/Core/polkadot/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-alloc-e37006629c0ab425/dep-lib-pwasm_alloc-e37006629c0ab425"]}],"rustflags":[]} \ No newline at end of file diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-libc-9375d1aea6d3c98f/dep-lib-pwasm_libc-9375d1aea6d3c98f b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-libc-9375d1aea6d3c98f/dep-lib-pwasm_libc-9375d1aea6d3c98f new file mode 100644 index 0000000000000000000000000000000000000000..75ac0990e3be0ca9842cb7435c423e19f0ebb7d8 GIT binary patch literal 337 zcmb`BOAf*?3`AMy6kH&+AmY<*dj{6XB&MpGCXt=e>(hYP0b;?*BkPUk!AXb(I=n#} znIJ_!poEcl2zUt)9XV;v8NVm^`5nI7$M(zofEoUV_!NIqcj9 k3HQ#}`gpB)c{l3^p$h@Rwsa~MrT#AS&BT4wcx%_FJAK4?eEe)=y6?(|67Q literal 0 HcmV?d00001 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/lib-runtime_polkadot b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/lib-runtime_polkadot new file mode 100644 index 0000000000..3e7282f285 --- /dev/null +++ b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/lib-runtime_polkadot @@ -0,0 +1 @@ +d4940d6f62cf958e \ No newline at end of file diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/lib-runtime_polkadot.json b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/lib-runtime_polkadot.json new file mode 100644 index 0000000000..ae6a4a3c0f --- /dev/null +++ b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/lib-runtime_polkadot.json @@ -0,0 +1 @@ +{"rustc":8294656847287967537,"features":"[\"default\", \"without-std\"]","target":15371597068611496627,"profile":42358739494345872,"deps":[["runtime-support v0.1.0 (file:///Users/gav/Core/polkadot/wasm-runtime/support)",2223771509741189442]],"local":[{"MtimeBased":[[1515501953,507863132],"/Users/gav/Core/polkadot/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/dep-lib-runtime_polkadot"]}],"rustflags":[]} \ No newline at end of file diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/dep-lib-runtime_support-5482fb51bf4d410e b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/dep-lib-runtime_support-5482fb51bf4d410e new file mode 100644 index 0000000000000000000000000000000000000000..e910e84870e0c19cd1c4960302fa60875852926d GIT binary patch literal 338 zcmb`BF%H5o5Cp0H3O?W*366x)@&;;T<4Y99@mY5^`92^*1riigTkOti;3UWbgT2C$ z7$H%Ztfvf%m05F%d7N>}GF8;H~yIiMkqBDC% literal 0 HcmV?d00001 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/lib-runtime_support-5482fb51bf4d410e b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/lib-runtime_support-5482fb51bf4d410e new file mode 100644 index 0000000000..c062c60974 --- /dev/null +++ b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/lib-runtime_support-5482fb51bf4d410e @@ -0,0 +1 @@ +42f9c1f3676cdc1e \ No newline at end of file diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/lib-runtime_support-5482fb51bf4d410e.json b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/lib-runtime_support-5482fb51bf4d410e.json new file mode 100644 index 0000000000..497c7e5b56 --- /dev/null +++ b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/lib-runtime_support-5482fb51bf4d410e.json @@ -0,0 +1 @@ +{"rustc":8294656847287967537,"features":"[]","target":14982045766639954252,"profile":42358739494345872,"deps":[["pwasm-alloc v0.1.0 (file:///Users/gav/Core/polkadot/wasm-runtime/pwasm-alloc)",1843871105590971886],["pwasm-libc v0.1.0 (file:///Users/gav/Core/polkadot/wasm-runtime/pwasm-libc)",6197225601014249845]],"local":[{"MtimeBased":[[1515500954,752149165],"/Users/gav/Core/polkadot/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/dep-lib-runtime_support-5482fb51bf4d410e"]}],"rustflags":[]} \ No newline at end of file diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-test-0ee9f37942e84b82/dep-lib-runtime_test b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-test-0ee9f37942e84b82/dep-lib-runtime_test new file mode 100644 index 0000000000000000000000000000000000000000..9aade611431b40cb99925f0fc1275d234f5704d1 GIT binary patch literal 286 zcmcJJF%E)26hy7}6kY%((T>(LP?L{4A%ta@{QrUL8=^MG!p3T*n3*?djcOQV!>uT> zlr%{!j$Lf7bj?1_JmHrVTy)^GdA(F?o^sjqTcJ!8BO({WYq)co*9WRO9~P!}q_MBn OLijH`~bx%98fF%rK-ZlO;==WwOiIrLwdrl~7Wt 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 literal 0 HcmV?d00001 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/deps/libruntime_support-5482fb51bf4d410e.rlib b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/deps/libruntime_support-5482fb51bf4d410e.rlib new file mode 100644 index 0000000000000000000000000000000000000000..2e0626d0708f1edb9ac3677db1439b816a1e3eb1 GIT binary patch literal 12778 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 literal 0 HcmV?d00001 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libruntime_support.d b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libruntime_support.d new file mode 100644 index 0000000000..43fe058cb3 --- /dev/null +++ b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libruntime_support.d @@ -0,0 +1 @@ +/Users/gav/Core/polkadot/wasm-runtime/target/wasm32-unknown-unknown/release/libruntime_support.rlib: /Users/gav/Core/polkadot/wasm-runtime/pwasm-libc/src/lib.rs /Users/gav/Core/polkadot/wasm-runtime/support/src/lib.rs /Users/gav/Core/polkadot/wasm-runtime/pwasm-alloc/src/lib.rs diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libruntime_support.rlib b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libruntime_support.rlib new file mode 100644 index 0000000000000000000000000000000000000000..2e0626d0708f1edb9ac3677db1439b816a1e3eb1 GIT binary patch literal 12778 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 UboSNos3Cr(Y>MAV{^VKnUuVwX;Q#;t literal 0 HcmV?d00001 diff --git a/substrate/runtime/test/Cargo.toml b/substrate/wasm-runtime/test/Cargo.toml similarity index 100% rename from substrate/runtime/test/Cargo.toml rename to substrate/wasm-runtime/test/Cargo.toml diff --git a/substrate/runtime/test/src/lib.rs b/substrate/wasm-runtime/test/src/lib.rs similarity index 100% rename from substrate/runtime/test/src/lib.rs rename to substrate/wasm-runtime/test/src/lib.rs From 88d66681f62d45af86e1a9f92850943ecc6402a7 Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 9 Jan 2018 15:05:41 +0100 Subject: [PATCH 005/112] More fleshing out on runtime. --- substrate/wasm-runtime/polkadot/src/lib.rs | 93 ++++++++++-------- substrate/wasm-runtime/support/src/lib.rs | 11 ++- .../lib-runtime_polkadot | 2 +- .../lib-runtime_polkadot.json | 2 +- .../lib-runtime_support-5482fb51bf4d410e | 2 +- .../lib-runtime_support-5482fb51bf4d410e.json | 2 +- .../lib-runtime_test | 2 +- .../lib-runtime_test.json | 2 +- .../libruntime_support-5482fb51bf4d410e.rlib | Bin 12778 -> 13160 bytes .../release/libpwasm_alloc.d | 2 +- .../release/libruntime_support.d | 2 +- .../release/libruntime_support.rlib | Bin 12778 -> 13160 bytes .../release/runtime_polkadot.d | 2 +- .../release/runtime_test.d | 2 +- 14 files changed, 68 insertions(+), 56 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 24529d4380..fb8e5b86f8 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -3,7 +3,8 @@ #[macro_use] extern crate runtime_support; -use runtime_support::{set_storage, storage, storage_into, Vec}; +use runtime_support::{set_storage, storage, storage_into, Vec, size_of}; +use runtime_support::{Rc, RefCell, transmute, Box}; /// The hash of an ECDSA pub key which is used to identify an external transactor. pub type AccountID = [u8; 32]; @@ -19,20 +20,36 @@ pub type TxOrder = u64; /// The functions that a transaction can call (and be dispatched to). pub enum Function { - StakingStake(), - StakingUnstake(), - ConsensusSetSessionKey(SessionKey), + StakingStake, + StakingUnstake, + ConsensusSetSessionKey, } impl Function { /// Dispatch the function. - pub fn dispatch(self) -> Vec { unimplemented!() } + pub fn dispatch(&self, transactor: &AccountID, params: &[u8]) { + match *self { + Function::StakingStake => { + staking::stake(transactor); + } + Function::StakingUnstake => { + staking::unstake(transactor); + } + Function::ConsensusSetSessionKey => { + let mut session = AccountID::default(); + session.copy_from_slice(¶ms[0..size_of::()]); + consensus::set_session_key(transactor, session); + } + } + } } +#[derive(Clone)] pub struct Digest { pub logs: Vec>, } +#[derive(Clone)] pub struct Header { pub parent_hash: Hash, pub number: BlockNumber, @@ -42,7 +59,7 @@ pub struct Header { } pub struct Transaction { - pub senders: Vec, + pub signed: AccountID, pub function: Function, pub input_data: Vec, pub nonce: TxOrder, @@ -71,42 +88,28 @@ impl Block { } } -/* -use std::sync::{rc, RefCell, Once, ONCE_INIT}; -use std::mem; - #[derive(Default)] struct Environment { - header: Option
, - current_user: Option, + block_number: BlockNumber, } -#[derive(Clone)] -struct EnvironmentHolder { - inner: Rc>, -} - -fn get_environment() -> EnvironmentHolder { +fn env() -> Rc> { // Initialize it to a null value - static mut SINGLETON: *const EnvironmentHolder = 0 as *const EnvironmentHolder; - static ONCE: Once = ONCE_INIT; + static mut SINGLETON: *const Rc> = 0 as *const Rc>; unsafe { - ONCE.call_once(|| { + if SINGLETON == 0 as *const Rc> { // Make it - let singleton = EnvironmentHolder { - inner: Rc::new(RefCell::new(Default::default())), - }; + let singleton: Rc> = Rc::new(RefCell::new(Default::default())); // Put it in the heap so it can outlive this call - SINGLETON = mem::transmute(Box::new(singleton)); - }); + SINGLETON = transmute(Box::new(singleton)); + } // Now we give out a copy of the data that is safe to use concurrently. (*SINGLETON).clone() } } -*/ // TODO: include RLP implementation // TODO: add keccak256 (or some better hashing scheme) & ECDSA-recover (or some better sig scheme) @@ -133,20 +136,26 @@ mod environment { use super::*; /// The current block number being processed. Set by `execute_block`. - pub fn block_number() -> BlockNumber { unimplemented!() } + pub fn block_number() -> BlockNumber { let e = env(); let eb = e.borrow(); eb.block_number } /// Get the block hash of a given block. pub fn block_hash(_number: BlockNumber) -> Hash { unimplemented!() } - /// Get the current user's ID - pub fn current_user() -> AccountID { unimplemented!() } - pub fn execute_block(_block: &Block) -> Vec { - // TODO: populate environment from header. + // populate environment from header. + { + let e = env(); + e.borrow_mut().block_number = _block.header.number; + } + staking::pre_transactions(); + // TODO: go through each transaction and use execute_transaction to execute. + staking::post_transactions(); + // TODO: ensure digest in header is what we expect from transactions. + Vec::new() } @@ -156,9 +165,9 @@ mod environment { // TODO: ensure signature valid and recover id (use authentication::authenticate) // TODO: ensure target_function valid // TODO: decode parameters - // TODO: set `current_user` to the id - // TODO: make call - // TODO: reset `current_user` + + _tx.function.dispatch(&_tx.signed, &_tx.input_data); + // TODO: encode any return Vec::new() } @@ -235,9 +244,9 @@ mod consensus { 10 } - /// Sets the session key of `_validator` to `_session`. This doesn't take effect until the next + /// Sets the session key of `_transactor` to `_session`. This doesn't take effect until the next /// session. - pub fn set_session_key(_validator: AccountID, _session: AccountID) { + pub fn set_session_key(_transactor: &AccountID, _session: AccountID) { unimplemented!() } @@ -274,17 +283,17 @@ mod staking { fn balance(_who: AccountID) -> Balance { unimplemented!() } /// Transfer some unlocked staking balance to another staker. - fn transfer_stake(_who: AccountID, _dest: AccountID, _value: Balance) { unimplemented!() } + pub fn transfer_stake(_transactor: AccountID, _dest: AccountID, _value: Balance) { unimplemented!() } - /// Declare the desire to stake. + /// Declare the desire to stake for the transactor. /// /// Effects will be felt at the beginning of the next era. - fn stake() { unimplemented!() } + pub fn stake(_transactor: &AccountID) { unimplemented!() } - /// Retract the desire to stake. + /// Retract the desire to stake for the transactor. /// /// Effects will be felt at the beginning of the next era. - fn unstake() { unimplemented!() } + pub fn unstake(_transactor: &AccountID) { unimplemented!() } /// Hook to be called prior to transaction processing. pub fn pre_transactions() { diff --git a/substrate/wasm-runtime/support/src/lib.rs b/substrate/wasm-runtime/support/src/lib.rs index aaab93e960..3acad5237e 100644 --- a/substrate/wasm-runtime/support/src/lib.rs +++ b/substrate/wasm-runtime/support/src/lib.rs @@ -7,7 +7,10 @@ //#[macro_use] extern crate alloc; pub use alloc::vec::Vec; -use core::mem; +pub use alloc::boxed::Box; +pub use alloc::rc::Rc; +pub use core::mem::{transmute, size_of, uninitialized}; +pub use core::cell::{RefCell, Ref, RefMut}; extern crate pwasm_libc; extern crate pwasm_alloc; @@ -37,11 +40,11 @@ pub fn storage(key: &[u8]) -> Vec { pub fn storage_into(key: &[u8]) -> Option { let mut result: T; - let size = mem::size_of::(); + let size = size_of::(); let written; unsafe { - result = mem::uninitialized(); - let result_as_byte_blob = mem::transmute::<*mut T, *mut u8>(&mut result); + result = uninitialized(); + let result_as_byte_blob = transmute::<*mut T, *mut u8>(&mut result); written = ext_get_storage_into(&key[0], key.len() as u32, result_as_byte_blob, size as u32) as usize; } // Only return a fully written value. diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/lib-runtime_polkadot b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/lib-runtime_polkadot index 3e7282f285..77c1ca3667 100644 --- a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/lib-runtime_polkadot +++ b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/lib-runtime_polkadot @@ -1 +1 @@ -d4940d6f62cf958e \ No newline at end of file +6eee55b59b574864 \ No newline at end of file diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/lib-runtime_polkadot.json b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/lib-runtime_polkadot.json index ae6a4a3c0f..39174c4da4 100644 --- a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/lib-runtime_polkadot.json +++ b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/lib-runtime_polkadot.json @@ -1 +1 @@ -{"rustc":8294656847287967537,"features":"[\"default\", \"without-std\"]","target":15371597068611496627,"profile":42358739494345872,"deps":[["runtime-support v0.1.0 (file:///Users/gav/Core/polkadot/wasm-runtime/support)",2223771509741189442]],"local":[{"MtimeBased":[[1515501953,507863132],"/Users/gav/Core/polkadot/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/dep-lib-runtime_polkadot"]}],"rustflags":[]} \ No newline at end of file +{"rustc":8294656847287967537,"features":"[\"default\", \"without-std\"]","target":15371597068611496627,"profile":42358739494345872,"deps":[["runtime-support v0.1.0 (file:///Users/gav/Core/polkadot/wasm-runtime/support)",18014962227880213226]],"local":[{"MtimeBased":[[1515506687,785085370],"/Users/gav/Core/polkadot/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/dep-lib-runtime_polkadot"]}],"rustflags":[]} \ No newline at end of file diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/lib-runtime_support-5482fb51bf4d410e b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/lib-runtime_support-5482fb51bf4d410e index c062c60974..7d69f92972 100644 --- a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/lib-runtime_support-5482fb51bf4d410e +++ b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/lib-runtime_support-5482fb51bf4d410e @@ -1 +1 @@ -42f9c1f3676cdc1e \ No newline at end of file +ea3ae1eab20002fa \ No newline at end of file diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/lib-runtime_support-5482fb51bf4d410e.json b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/lib-runtime_support-5482fb51bf4d410e.json index 497c7e5b56..1e4859a996 100644 --- a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/lib-runtime_support-5482fb51bf4d410e.json +++ b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/lib-runtime_support-5482fb51bf4d410e.json @@ -1 +1 @@ -{"rustc":8294656847287967537,"features":"[]","target":14982045766639954252,"profile":42358739494345872,"deps":[["pwasm-alloc v0.1.0 (file:///Users/gav/Core/polkadot/wasm-runtime/pwasm-alloc)",1843871105590971886],["pwasm-libc v0.1.0 (file:///Users/gav/Core/polkadot/wasm-runtime/pwasm-libc)",6197225601014249845]],"local":[{"MtimeBased":[[1515500954,752149165],"/Users/gav/Core/polkadot/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/dep-lib-runtime_support-5482fb51bf4d410e"]}],"rustflags":[]} \ No newline at end of file +{"rustc":8294656847287967537,"features":"[]","target":14982045766639954252,"profile":42358739494345872,"deps":[["pwasm-alloc v0.1.0 (file:///Users/gav/Core/polkadot/wasm-runtime/pwasm-alloc)",1843871105590971886],["pwasm-libc v0.1.0 (file:///Users/gav/Core/polkadot/wasm-runtime/pwasm-libc)",6197225601014249845]],"local":[{"MtimeBased":[[1515504344,57881737],"/Users/gav/Core/polkadot/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/dep-lib-runtime_support-5482fb51bf4d410e"]}],"rustflags":[]} \ No newline at end of file diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-test-0ee9f37942e84b82/lib-runtime_test b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-test-0ee9f37942e84b82/lib-runtime_test index dc062b33e3..fb66643a92 100644 --- a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-test-0ee9f37942e84b82/lib-runtime_test +++ b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-test-0ee9f37942e84b82/lib-runtime_test @@ -1 +1 @@ -9cf830998a9aef5e \ No newline at end of file +0caae204cc6f3f45 \ No newline at end of file diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-test-0ee9f37942e84b82/lib-runtime_test.json b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-test-0ee9f37942e84b82/lib-runtime_test.json index 6040d1fe18..1003d6c5db 100644 --- a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-test-0ee9f37942e84b82/lib-runtime_test.json +++ b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-test-0ee9f37942e84b82/lib-runtime_test.json @@ -1 +1 @@ -{"rustc":8294656847287967537,"features":"[]","target":11385551307513482501,"profile":42358739494345872,"deps":[["runtime-support v0.1.0 (file:///Users/gav/Core/polkadot/wasm-runtime/support)",2223771509741189442]],"local":[{"MtimeBased":[[1515500955,389693545],"/Users/gav/Core/polkadot/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-test-0ee9f37942e84b82/dep-lib-runtime_test"]}],"rustflags":[]} \ No newline at end of file +{"rustc":8294656847287967537,"features":"[]","target":11385551307513482501,"profile":42358739494345872,"deps":[["runtime-support v0.1.0 (file:///Users/gav/Core/polkadot/wasm-runtime/support)",18014962227880213226]],"local":[{"MtimeBased":[[1515504344,719487568],"/Users/gav/Core/polkadot/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-test-0ee9f37942e84b82/dep-lib-runtime_test"]}],"rustflags":[]} \ No newline at end of file diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/deps/libruntime_support-5482fb51bf4d410e.rlib b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/deps/libruntime_support-5482fb51bf4d410e.rlib index 2e0626d0708f1edb9ac3677db1439b816a1e3eb1..c74a5505236b2abd831d543c288f99ad02138b74 100644 GIT binary patch delta 6273 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 delta 5976 zcmZt|2{=_-cb{|ab?57Hxn?0!N!+0o4n5!=qxf4UP84M7cJJ+S0TO~bO1m9 zpnyOKNC5DPg-^xf5UOws$7JS*_=Zal%P)$NzxJx2biA^H!_V@A&1PDL@!uhWmf=K3LlHQ0tjYM+` z33Qrfqmfv@XHI@Wz5t<-#BoZ18ytare`gOjoF<3UJRr^4$A|Cg9O$<5zgC4MTv^R& zxt(si`2k*mPCk4OfH0`Y2IvM2)pQ1k6h7gdmh#V6l8!=kB{_hN0=fi?%cRo1e0Tdm zg+VR>JRl8HIXPTxqnj&&e&l2!cMwzwfE=#SUiPGbBPqp6L=ZqiCBpC+5+5P~O+gyC zh?b#bFo_&O5t5Iyp9hY?KpaMopa4XmC(#)s+HPk*FIOjbUl{svp{XD#^{)w3P8t4 zDFOf>1;r4ASfZdfV4{LaCUNvh@)T5r!gG^C02dxBWPnOAC=FEtAc-4-_bmyZV%+oe zT&P-_0015}0F>+W`;f%DPS1xxh5!J_z!i*Gfz=FGAu}a$A7{j5kZu|q#*>0}(|*zh zq`-ibaIvzYpok8M7*7PGML<#nnD1$2xGyAJ5o27oj1H$5qnut20s9lRl1>4DOh-T^ z9ikXzh<=1YMrDWS<8(4AM*sliphu)BVnv<+0LbG`63hSyWN`&@2#`O*fYR7BkV6LO zR~Td%9$A2h0hA&J$gvC|RIfk);)dcFt{qI16rh`E6ypqo45@UKNDJb6LNy9!a5|aY9)BcW&m{_)N2`SycjGWjcof9W025r0F@y4(Aiyaw zJ}?_7u-=MX{@>k*Xk@rsXb!I|Ad?D%G5s&ZaYXcgh2xm$k6#aje1-=96wx1g3t$HU z-*`lQg2n(~2&gGM1i>p=H1z}?8vGa#F@Lv!AfG@{<$>Of%Oa!zul;UB4I+sMl)e65 zfq`y*M5Tcx6Ts?@8-*Caj}k9AP#sJ-F2WV*b8-%Fa@iN?=H%kTcOjxpgXfP&1&<;j z$e`l4;P>>o>c2QF{dh$p*v2IQUJ<56U|IinI;HwA4yzGfmqa46L?t3{@Ea8Xs20!p zUp#oFAn;-pNRJWW@X+woC+LtLPw-#-c;XW{0C-CMBIDWj3&+!rz~R=Wa|Vw+aZ6z$ z0OB}=f2yg>PU69{1PDA57);npP+2Ot#(2eK0_L<0fRr)H7{U}axot^25fj3|z-wkT ziwW>bNqooYXOq^RRDU?^A zDJYiw?K7e9jChqe6L29fe3wk?kOVTyWc+ROtGnY4zY=c~|KILD{iGTD6=fC~REx)Q zn0Uh&k7{D`o@1?~hk!HIbQallgtJVuba3^8oZkP=;JJ6jJmG!jP4wh>GxGRWO{ zV6*)u$Ip43yVe91BZeN<^aj7lkF6F+tM-5gtr>EWue(9UrSNOhfxGi|9?c1Ak&(G=W z|9wtB;Hyk-jbP57q(|g%!ODjw&aK_zU5*N&V=IyFHKfit^1X){4j>cM(4I4sV*^!JD-qou{BPhR9>biZ_HAP zspRP0Q}A6HS?y}=^-1}U{+M>|+r*4JEzU*N$)&m{<{K_NRI=pVqxnIK$?L~%ICC00 zhr*Jc>c(=h3rl=6A2@Gl(~Fpa0Nr5w@UCOYzWz258-=Sv)X=+%{`+s<)j#Glr+&YS3{kNTt3!#_7FyXF z=Yi)YS7)bF~D|_yU?*N>p*LM?aj=B8$a?+n>o65TwGgR zVZvE){Et%d)lKlf~nt*I+{IcjXW@N92)R`6ZBOvcb5x!1mbD#qRrcopnFxU=9v zz3oE&n6rJyguUtF5jTTj*$9=c?_VN{9yX=)1C#Lyyx7lbdQbwYr5JP4~PKW4}Ir zMBfqn#m2AiEOrW{#06eF{Q(i^FIqGx`SdY!3hl8|Pl86xqN5V~fu;m9& zEKS<~QFr;CSvHfVh78-l3i7pEp7R&5)zdPKIpmEz!165AD_2)pu8#KiNH6TyT)lkx zi(RMESdo7ySF|iNQ;Xhrg{EV!*Lc$3^}$&9sNEy$M|Q6EUWfX^B{$~^DvvGSnUK={ z^B>Q%^E^78ntHq`lfbfnd`k+rA;l%WH{Y{(!PY5lD~rk}SC-tfS)g|Et(M^A&+hy0 z@7txRuezDI^EBgDOZb+pYVYFrJdW2*vszYBW71w3cuRlmdd#l1qr>Y>a+@5Y@4fIH zDAb@!RU}{{Y#bok7rZINlw|9Ej&w%at^OMQQV@<^30g=OkKveA*S?n{~x{5 zYqzeJkFG8z_f|?JRBDZtJody9IVzdN;)FFduzx`(!t2DgT4sP*oAm0{Web z)%JBshf_M!l-9oTHDAxPNHj}#GQaTksJl4O#|v1%umdpawyzN{ zytnV#a0Ihvui-3xZc>r{PEak!sIuQD=*aE zb4kAbs(^jWC~h(-Kk>xez{u6N->#;ATQ+#;ZfbZm5ADv7x?b(=k-d4mv?XZ@J1)v zxbyL+4jB#KP!*R>W!HEcz;}+zq&JC z7a45Np9rhy6qrx+3IFN&p8ZFCX6-8_VUc!^qeSc1+6vRrdA`GiVEcsWUeC!;y{x69 zqlTI_2Tv^+*%#J$&F#yRC;2l+9PMn42d8ehwi;B$e;+u&YAbWBN6ZU*p9s*n)DNap zZMFR1yVou#9LNZ3euXVMvf67-ZGz(D1HGW26m&{*Uncw7T*Twy8ZC z7DYDPuoA}9Fiw2E@Wt*OpW15Agf!B3_st4i@!gPxip+LH^yCQU*%0r+k}ERnW=iiZ3=PMivq?Jp5-o@ z>;29<#c25S(8J4rz51A1yEj?>^{WMaOK!Ld(|0}lSsW|I^!d+6PqQp1RrkTmft%Ts19`Oz)K-=7_gMjhc?*PTn7-@_+Jb4n$F~FDq(@dTu{kz3?_j3bKo+L|Xd>j$^dU)G8 zJ0hJhSV3*6Jc&*8IRDqfM?-o1cG=_T>EYwz%Xjr~29QmKo6!ttn6@2&YD8m-utULH zFec2u&~qWCJPf|AJl}fs#rWxX*fE&-A-;d4Qd4y3&Cxr#)omVQt=AH6SJi!c3*)aG z6LtvW4rv@M9(voIQupc*6!zR37^rLPx&adh8=6jLylz`QI&?>rQ9XpPCQ@T>e*P!r zVibJcl~5lskyLjJhCQrnm`ts&obs+;FYVgLs=Ovz``h-?i(#pwhVQRLJk6_(JhQSk zer!A}ujh?t=1BbA6NAGa4i{LkBQOC^8E`P5prWLz$fCQrdAg!)@w4|)0_xy2E1fOv z=kDU};_G7P>T(=0XT^#;!{X8Pdj%P2fmXVisvx=G%f{_@QXO4 zxqI;4kcX=y(L|_c@C=*@SdsyRG_Dz`3y&fR*Kzd~I@ka(A(Tdu3t~vwBqlf^{J=F7 zR&tfNEo>2+Ac+lWjwZ6nC7mP-2e`}Chz`1l4d|^10YTupDyTb({DI5_k-s2#gjK7O z2z?0~3B*ToyA%^dAsbEMV`UcSzacPXS%lFkb&A3S(ZUT}4U|XV0Uk#YPE}c;-O7e! zbZQWw5z!VwE)L=;!&D|vkSq)Uc!hF>A{3}7njEDaqft?Y|M$c9IR;|GTr#|W3__p? zhy*|&Y#fYG)0s@bhM-wl*r=i^NT4Oqhy<-incS>=QiX|MrxQrz(Bi5eiqpE+Kfkd1#z!+zcG423k6ftEn13(!~ ziS$L>qatPis1UOh8v`KV5&+5&sEiXf_)n$``x&WBGTI+5x@Q1Jkpkp!=1C?QlL!WJ91Z zh-9K*S@ioT=fq_k1Ftnes}h(%)#jH%KxokZpnRZUX!-xoY9u-`S}humC?O!5hBo8p z_ckFz$+w%3amkkm4@i!sqc27BMY9EJh#Hl}g$NA>07F3i#D$P3S*K`1VnM_)Kq+rW zA3s-LN$EkeYvDl>aY>1b5J{q-_Z$i_4>c2 zX!?ILDn~?NlDP21rARD;-=Y8@SR(0v*$|~dEGJAu`oj_#9U77QVm-1aGW?f4k@;d7 z03xM+sfq0SB@<~UmeJCF<_xj-;-f~10K~^3{62N6-7ptj6abEAKOzL4?SKphFu&wT-Yugd`!< zRMh04A_c&yQ1oB{=(&d$A%>DiRv%@CWmQUagbOrh+mz`1hQ!fgLA>mcEEA{@;%{H% zh)R<9ha|w!Bct3vW8nazdm9pQibhL7cPmm74~h}lyK<@tio!dZ(_9i1|L*{ia@BH7 zqF?}?7?GGW4{+3fV-g!kKsL*@$o=1|oV?%8)z1-YR{n`7O$N1c;VdRlBho~;eww=A zB&w!pF2wbXVV~r_$pH)(Gjt+oAP7Ing|Sd>6HL5!Cq%?%}LTE3;ncankIfP>wOt<{#YYS?CVH6n(}X}L2XC=)1)uL zW_z?SbOVkV0BB3(4XA}MTv`e@{HAVTVnX~&Mlv*6Fh@w$-XMsSQ~{8)HE6rlHu;of zQN>cGiB^uu{0Ng!rG%%aLP@dn4d&{$A0JQ>QE1dKMV|V|jjq0x@^05yE{-`xsjcsd z%QD;YWJQUmR%A5jD(MY9wf@_x!TM9d)1gw^tf1L9%f1))Onwgb*YfFWYVzo7>K%!i{$|9+hkhv-P5d7&#ZW0FYF&b}slXWwwl z&C2eEwGUqEUj+Z?^x-*o{h!=fwp$y!zU18PCpR_~S}hdh-#v50+~M-e7dD1r%%OW- zF}sa+D5#Wj;=<&|&U`U-G4L~WH+thqx~ONVzx&1`!~90uajkgh%01#c7U0-Z?aO&yQ-3;kD zJg}Ko$vxm^v^rkU-oI*q;lFz6VpGwF7@yVN^||UZpBgIPoI5AghFY$=aI2;M79G+Uw>b&%Q0+)CaBuD5*OHzNSm|BGdp)5 zkKY(+X+A6N%(2p!_t!Xm+vpxCT01p_?WyKj*uKJgcYBu9R>7hX4Y>|Q=bMwJN!RLZ zzi|eWzExLenYz_y`LSH*u6@De`qZ8$b2jMhCX z_OI2bNIeyvJ!1GeG20@mf;#Ifa zI`9pCv}uXCQ`Z84Nw&ac-rvCk*-wX6Ne8;l`b7u68q?M-FJA6Z^kB=*Xp`;bMe!xY zJ$j}Ui+`xpJfFizht-_UF_yI_dCM~G#@V0i%ol!LP48cMY@+wN@j}hA$oj@Bj!Coc zmj98P9pckmv3%CEZ&KxHZaan^ES>QCM~`n{=8_OSbI<7mdp0nwB}!*4@iLr?}?GbL-yJx7+?~ zdzYTk9X9>_QRxkdizhs7XWCcI(zn}8Udv#_aV;$MvO;d$xYB9O-&3$vBzT(P6wldb z7(e6Mt^OH~76}V0T!+FY`5A$QMF)B=H8e*R6?zv33G8$S4_Y0n#P_}oi+!`a`-dBQ zrQCX3WsgJNhZ7gT38u>BZ(EM!HfFVukL0dccR8b7clkiKb*7=7eQ4UNir%|A zM;{GbrEj)?WZY!I%)G|mX`)}yCXbs$p4JT)UV3+0vX-N zR{uanqY|glgImp38Z6KJGdOy`Ony|{>{ZG411q*TR9=uVv206B%G@Q(OFna-IU1aE zlAEHGc&Pks{f53snabP4X?PoXS;cT{LkHv5%-&dyZddu(K!$$g!G&|?r5f+fTzzt{ zXIlL-TKciGtChcf7oE#LwK&#<_HylPftK?hfwf5k`K!Xh55x&N)j4{WZG~~Fr$Zn4 z$g~eVD9|=@?4nwbKBh$sL>IIK7YjBRAAVHhG|Z|Q8?DN(HH&fk8t5vOXV~Ge&Lzb4 z_119D`nt!5UzHep;d6G4Ke99W&ha`Bys*jADl5d!`Doa!X)({(^;M#vrCE5}@m&JH z_D5cW)!hg8EYDx0dnrnN)0s2>&d}LxdTB{k}+sDS1hdNu` zrkywGbLFWg**#i?k2YQZ8uPELhML!nov(sN6vp(DhPq_TOW!-G=B}w6H}$%_iOWwA zxit;0Z)987ol803#*g@3^S(c7qPm1W(PM0~rFzN^P0i7VLRo#&5WU$c?C`qP4@dly zIfCSmWgE_W7+;#UvSe;hnU06m=L${lXDLSy4zIme=%aCSET%kdUcs7;&SM|*V$Oe` z>T+-NUgFi03uAWGNAv{lSm`!1z@ahSve|r}ynoXCwG+J+k={>YCP}J))E@lNw!ve6 zQO*U8MXjcOZO=-p<01>+G{^|7&sU~<{@CZ-ShiI#JGti0m#@|`i!DYMO@>_AR<)BO zFk7;CV&rUKmuzDH)kpqn6W8|gYjc%lZ;Xx4c9T7y*WIl+dMwW-%j{&}x&Y~_3I5Sz zA!Ze0WW4VU~MogOupZY(oEQ5|!j<1Mve*VqE*fGY#)w(SDZqD$Bkb4gmp3(LX zJU#e)Ky#-cSv@ED%lg`JtG(N7Zs`ebp0|_kWXBc$ya3VPn;ah9d-#2z g%l1xrS+n-_Z9GOzKnw5wyc_5IPh8k8Gf4vf0~2h($ delta 5976 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 Date: Tue, 9 Jan 2018 15:07:55 +0100 Subject: [PATCH 006/112] Update native support. --- substrate/native-runtime/support/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index b1c41f4821..93d3aad9cd 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -1,4 +1,8 @@ pub use std::vec::Vec; +pub use std::rc::Rc; +pub use std::cell::RefCell; +pub use std::boxed::Box; +pub use std::mem::{size_of, transmute}; pub fn storage(_key: &[u8]) -> Vec { vec![] } pub fn storage_into(_key: &[u8]) -> Option { None } From f3dd41efd6d9717134a2394b3ea3631e10e2b139 Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 9 Jan 2018 15:50:48 +0100 Subject: [PATCH 007/112] Fix warning. --- substrate/executor/src/wasm_executor.rs | 2 +- substrate/executor/src/wasm_utils.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index ff4b1a31a2..5de36f7d23 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -137,7 +137,7 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, } else { 0 } }, ext_deposit_log(_log_data: *const u8, _log_len: u32) => { - unimplemented!() + // TODO } => <'e, E: Externalities + 'e> ); diff --git a/substrate/executor/src/wasm_utils.rs b/substrate/executor/src/wasm_utils.rs index 577e6ab0b2..6d4fedfedb 100644 --- a/substrate/executor/src/wasm_utils.rs +++ b/substrate/executor/src/wasm_utils.rs @@ -75,13 +75,13 @@ macro_rules! reverse_params { #[macro_export] macro_rules! marshall { - ( $context:ident, $self:ident, ( $( $names:ident : $params:ty ),* ) -> $returns:ty => $body:tt ) => ({ - let r : <$returns as $crate::wasm_utils::ConvertibleToWasm>::NativeType = reverse_params!($body, $self, $context, $( $names : $params ),*); - Ok(Some({ use $crate::wasm_utils::ConvertibleToWasm; r.to_runtime_value() })) - }); ( $context:ident, $self:ident, ( $( $names:ident : $params:ty ),* ) => $body:tt ) => ({ reverse_params!($body, $self, $context, $( $names : $params ),*); Ok(None) + }); + ( $context:ident, $self:ident, ( $( $names:ident : $params:ty ),* ) -> $returns:ty => $body:tt ) => ({ + let r : <$returns as $crate::wasm_utils::ConvertibleToWasm>::NativeType = reverse_params!($body, $self, $context, $( $names : $params ),*); + Ok(Some({ use $crate::wasm_utils::ConvertibleToWasm; r.to_runtime_value() })) }) } From 6e2fbb8e84049ced068180121b08d261c269f5bf Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 9 Jan 2018 15:58:17 +0100 Subject: [PATCH 008/112] Update gitignore --- substrate/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/.gitignore b/substrate/.gitignore index cd789637f9..c7a3830779 100644 --- a/substrate/.gitignore +++ b/substrate/.gitignore @@ -1,5 +1,5 @@ /target/ **/*.rs.bk *.swp -runtime/**/target/ +wasm-runtime/**/target/ **/._* From 06791fa07fcdfcdd10d76149bc78823accaf4ccc Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 9 Jan 2018 15:58:45 +0100 Subject: [PATCH 009/112] Update path. --- substrate/executor/src/wasm_executor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index 5de36f7d23..f7b9c1e9e3 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -217,7 +217,7 @@ mod tests { let program = ProgramInstance::new().unwrap(); - let test_module = include_bytes!("../../runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); + let test_module = include_bytes!("../../runtime-wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); let module = deserialize_buffer(test_module.to_vec()).expect("Failed to load module"); let module = program.add_module_by_sigs("test", module, map!["env" => FunctionExecutor::::SIGNATURES]).expect("Failed to initialize module"); From 55418c7ed84f53b54fdd29b0dc7571ae54f4c124 Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 9 Jan 2018 15:59:05 +0100 Subject: [PATCH 010/112] Fix path. --- substrate/executor/src/wasm_executor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index f7b9c1e9e3..e0d47de267 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -217,7 +217,7 @@ mod tests { let program = ProgramInstance::new().unwrap(); - let test_module = include_bytes!("../../runtime-wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); + let test_module = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); let module = deserialize_buffer(test_module.to_vec()).expect("Failed to load module"); let module = program.add_module_by_sigs("test", module, map!["env" => FunctionExecutor::::SIGNATURES]).expect("Failed to initialize module"); From 5db5d2d98ab6de01dfe7580ad96c6bb9e0be3113 Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 9 Jan 2018 16:00:39 +0100 Subject: [PATCH 011/112] Remove accidentally committed files. --- substrate/wasm-runtime/target/debug/.cargo-lock | 0 .../dep-lib-pwasm_libc-e72991cbfafd2b71 | Bin 409 -> 0 bytes .../lib-pwasm_libc-e72991cbfafd2b71 | 1 - .../lib-pwasm_libc-e72991cbfafd2b71.json | 1 - .../deps/libpwasm_libc-e72991cbfafd2b71.rlib | Bin 10670 -> 0 bytes ...-b023388293df7da5.crate.allocator.rust-cgu.o | Bin 1636 -> 0 bytes ...c-b023388293df7da5.crate.metadata.rust-cgu.o | Bin 184 -> 0 bytes .../debug/deps/pwasm_libc-b023388293df7da5.d | 5 ----- ...libc-b023388293df7da5.pwasm_libc0.rust-cgu.o | Bin 2568 -> 0 bytes ...libc-b023388293df7da5.pwasm_libc1.rust-cgu.o | Bin 4208 -> 0 bytes .../target/debug/libpwasm_libc.rlib | Bin 10670 -> 0 bytes .../wasm-runtime/target/release/.cargo-lock | 0 .../wasm32-unknown-unknown/release/.cargo-lock | 0 .../dep-lib-pwasm_alloc-e37006629c0ab425 | Bin 342 -> 0 bytes .../lib-pwasm_alloc-e37006629c0ab425 | 1 - .../lib-pwasm_alloc-e37006629c0ab425.json | 1 - .../dep-lib-pwasm_libc-9375d1aea6d3c98f | Bin 337 -> 0 bytes .../lib-pwasm_libc-9375d1aea6d3c98f | 1 - .../lib-pwasm_libc-9375d1aea6d3c98f.json | 1 - .../dep-lib-runtime_polkadot | Bin 306 -> 0 bytes .../lib-runtime_polkadot | 1 - .../lib-runtime_polkadot.json | 1 - .../dep-lib-runtime_support-5482fb51bf4d410e | Bin 338 -> 0 bytes .../lib-runtime_support-5482fb51bf4d410e | 1 - .../lib-runtime_support-5482fb51bf4d410e.json | 1 - .../dep-lib-runtime_test | Bin 286 -> 0 bytes .../lib-runtime_test | 1 - .../lib-runtime_test.json | 1 - .../deps/libpwasm_alloc-e37006629c0ab425.rlib | Bin 13718 -> 0 bytes .../deps/libpwasm_libc-9375d1aea6d3c98f.rlib | Bin 6310 -> 0 bytes .../libruntime_support-5482fb51bf4d410e.rlib | Bin 13160 -> 0 bytes .../release/deps/runtime_polkadot.wasm | Bin 341 -> 0 bytes .../release/deps/runtime_test.wasm | Bin 3480 -> 0 bytes .../release/libpwasm_alloc.d | 1 - .../release/libpwasm_alloc.rlib | Bin 13718 -> 0 bytes .../release/libpwasm_libc.d | 1 - .../release/libpwasm_libc.rlib | Bin 6310 -> 0 bytes .../release/libruntime_support.d | 1 - .../release/libruntime_support.rlib | Bin 13160 -> 0 bytes .../release/runtime_polkadot.compact.wasm | Bin 218 -> 0 bytes .../release/runtime_polkadot.d | 1 - .../release/runtime_polkadot.wasm | Bin 341 -> 0 bytes .../release/runtime_test.compact.wasm | Bin 3392 -> 0 bytes .../release/runtime_test.d | 1 - .../release/runtime_test.wasm | Bin 3480 -> 0 bytes 45 files changed, 22 deletions(-) delete mode 100644 substrate/wasm-runtime/target/debug/.cargo-lock delete mode 100644 substrate/wasm-runtime/target/debug/.fingerprint/pwasm-libc-e72991cbfafd2b71/dep-lib-pwasm_libc-e72991cbfafd2b71 delete mode 100644 substrate/wasm-runtime/target/debug/.fingerprint/pwasm-libc-e72991cbfafd2b71/lib-pwasm_libc-e72991cbfafd2b71 delete mode 100644 substrate/wasm-runtime/target/debug/.fingerprint/pwasm-libc-e72991cbfafd2b71/lib-pwasm_libc-e72991cbfafd2b71.json delete mode 100644 substrate/wasm-runtime/target/debug/deps/libpwasm_libc-e72991cbfafd2b71.rlib delete mode 100644 substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.crate.allocator.rust-cgu.o delete mode 100644 substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.crate.metadata.rust-cgu.o delete mode 100644 substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.d delete mode 100644 substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.pwasm_libc0.rust-cgu.o delete mode 100644 substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.pwasm_libc1.rust-cgu.o delete mode 100644 substrate/wasm-runtime/target/debug/libpwasm_libc.rlib delete mode 100644 substrate/wasm-runtime/target/release/.cargo-lock delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.cargo-lock delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-alloc-e37006629c0ab425/dep-lib-pwasm_alloc-e37006629c0ab425 delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-alloc-e37006629c0ab425/lib-pwasm_alloc-e37006629c0ab425 delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-alloc-e37006629c0ab425/lib-pwasm_alloc-e37006629c0ab425.json delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-libc-9375d1aea6d3c98f/dep-lib-pwasm_libc-9375d1aea6d3c98f delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-libc-9375d1aea6d3c98f/lib-pwasm_libc-9375d1aea6d3c98f delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-libc-9375d1aea6d3c98f/lib-pwasm_libc-9375d1aea6d3c98f.json delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/dep-lib-runtime_polkadot delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/lib-runtime_polkadot delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/lib-runtime_polkadot.json delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/dep-lib-runtime_support-5482fb51bf4d410e delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/lib-runtime_support-5482fb51bf4d410e delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/lib-runtime_support-5482fb51bf4d410e.json delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-test-0ee9f37942e84b82/dep-lib-runtime_test delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-test-0ee9f37942e84b82/lib-runtime_test delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-test-0ee9f37942e84b82/lib-runtime_test.json delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/deps/libpwasm_alloc-e37006629c0ab425.rlib delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/deps/libpwasm_libc-9375d1aea6d3c98f.rlib delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/deps/libruntime_support-5482fb51bf4d410e.rlib delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/deps/runtime_polkadot.wasm delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/deps/runtime_test.wasm delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libpwasm_alloc.d delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libpwasm_alloc.rlib delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libpwasm_libc.d delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libpwasm_libc.rlib delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libruntime_support.d delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libruntime_support.rlib delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.d delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.d delete mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm diff --git a/substrate/wasm-runtime/target/debug/.cargo-lock b/substrate/wasm-runtime/target/debug/.cargo-lock deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/substrate/wasm-runtime/target/debug/.fingerprint/pwasm-libc-e72991cbfafd2b71/dep-lib-pwasm_libc-e72991cbfafd2b71 b/substrate/wasm-runtime/target/debug/.fingerprint/pwasm-libc-e72991cbfafd2b71/dep-lib-pwasm_libc-e72991cbfafd2b71 deleted file mode 100644 index 92c61885d84f13585667714e922ac63d3e89ddd5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 409 zcmchSJr2S!3`UuA3NDaZ?NYTXXJAJ8aifZsSawpbPr?d9nOLk(pX{e+xC*jBFb7;B zBT(G##>WItBfIAONb8OunJ98PLDP0J958`Ln?so-u&tIV@K%D;I1ba)JG+?04|eQ3 hF7t@n+wrH_FD?HUr>_sq>IKdJl!pKS diff --git a/substrate/wasm-runtime/target/debug/.fingerprint/pwasm-libc-e72991cbfafd2b71/lib-pwasm_libc-e72991cbfafd2b71 b/substrate/wasm-runtime/target/debug/.fingerprint/pwasm-libc-e72991cbfafd2b71/lib-pwasm_libc-e72991cbfafd2b71 deleted file mode 100644 index cb6d43a3ff..0000000000 --- a/substrate/wasm-runtime/target/debug/.fingerprint/pwasm-libc-e72991cbfafd2b71/lib-pwasm_libc-e72991cbfafd2b71 +++ /dev/null @@ -1 +0,0 @@ -ba1707f874223553 \ No newline at end of file diff --git a/substrate/wasm-runtime/target/debug/.fingerprint/pwasm-libc-e72991cbfafd2b71/lib-pwasm_libc-e72991cbfafd2b71.json b/substrate/wasm-runtime/target/debug/.fingerprint/pwasm-libc-e72991cbfafd2b71/lib-pwasm_libc-e72991cbfafd2b71.json deleted file mode 100644 index e73f9ca5d1..0000000000 --- a/substrate/wasm-runtime/target/debug/.fingerprint/pwasm-libc-e72991cbfafd2b71/lib-pwasm_libc-e72991cbfafd2b71.json +++ /dev/null @@ -1 +0,0 @@ -{"rustc":8291033049748019918,"features":"[]","target":14441046832906989149,"profile":731176819336294830,"deps":[],"local":[{"MtimeBased":[[1515500307,607755819],"/Users/gav/Core/polkadot/wasm-runtime/target/debug/.fingerprint/pwasm-libc-e72991cbfafd2b71/dep-lib-pwasm_libc-e72991cbfafd2b71"]}],"rustflags":[]} \ No newline at end of file diff --git a/substrate/wasm-runtime/target/debug/deps/libpwasm_libc-e72991cbfafd2b71.rlib b/substrate/wasm-runtime/target/debug/deps/libpwasm_libc-e72991cbfafd2b71.rlib deleted file mode 100644 index 284e12e552798df2d3d6e5de9fd96601c0918b28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10670 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 Xk5~A7R5dzuyPJPu&DrP0@2>nGWWk?; diff --git a/substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.crate.allocator.rust-cgu.o b/substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.crate.allocator.rust-cgu.o deleted file mode 100644 index 095c41adea2bd940449bc284431f91b9a03e463a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1636 zcmcIku}&L75ZwbuSiy-6q%e{th(tkS6e=hvf*`^rL>6%oX*uk5Y{mGjJEK@m3KFG3 zG^RkJ;16ghDN<0<(YnY7KoNx!MG@i6-7FmE%ZY}O#&6!dx4UzzJD>gebv+=2(J%0W zBwVIq9Eli3p1W1}&n0;g4Mxqer=aX35g}z$wVGb-@%)=Y{*LQvj|?QdMNxHaC>lk@Eh2`)n-mTyYFS&!%Hgh>ETWY0fnA2&NanOB~+BTKL2=(jPRB zPJjO)^#z&A<*DS@ch~;dJh!tr5zlQePF%Ssbwba>B=pP_M*FQWS}7xy7>IZ9{2BBp zbN{?}LMC63Hiw*z(BDI!jL^S8Peh+0yAX|Al|v` zDvBf#jwvAVHRivW>vwjB{o}0D_eK6K=I@x}Y&X*Ef6W}!^*5NGFz+z0Gk?Xrgax!l z#{vpJj|KFl06z@)ivd0v@Y6Tz-@hB+-vS(eMAF`Ln$lKgt!5RaY892^xb2b(>ykOl z+S4PWWo_uKbV=<^$6T)|=~UZF%fS}eKG@bLS*^=P%`Dy;dz)l+Dt5L0vBw=?QvzWaMkn9zP|y+L^w1_nlE1|R{&Gk`RM0*GK>kOX2dAI!r|>_C$On#lmdATvQAKE5Qiq6ET* U@Izc9LJ)j(7P@&r`37V)06RttumAu6 diff --git a/substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.d b/substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.d deleted file mode 100644 index 4116414cae..0000000000 --- a/substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.d +++ /dev/null @@ -1,5 +0,0 @@ -/Users/gav/Core/polkadot/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5: /Users/gav/Core/polkadot/wasm-runtime/pwasm-libc/src/lib.rs - -/Users/gav/Core/polkadot/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.d: /Users/gav/Core/polkadot/wasm-runtime/pwasm-libc/src/lib.rs - -/Users/gav/Core/polkadot/wasm-runtime/pwasm-libc/src/lib.rs: diff --git a/substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.pwasm_libc0.rust-cgu.o b/substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.pwasm_libc0.rust-cgu.o deleted file mode 100644 index 43bde99ac7b005f8b8998304557aa557a927c94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2568 zcmbVO&2Jk;6rZ)zG;LaU3l%CNg*`yk3SxUUjz2&}F>%ly3Ti`B0#dcC*X!89U)|k= zf{*|e0T!ynffK5bxN+phflEXY>7k+*{)8fNDB^-d1cLB;vondkO-bNMZ{B+|@BQYz znR#p9{^OUw_cNv?83r&(eIEt`40;&+<%m#s9KN6cP?lmq$_6GQPSGUDwnOhq80nFH zVQ%rlwym`DQXxFr_Q$bE!gyEtkhE>L+X=P-ZF?ARQ94siL>~c9rW#GeM%%7=)s-bX z2z{|)+m)Bg^UrU2y&|%A`Vo{~A;+7-`h*mWPL7X`%o?WV+QNW2Z;4ffkOV`@owZ1qR8 zBM{^DW@YeYiT4`b9nrA^(RT{!(D{*Z96W(_YRwkpbx7>X&Vh-@hnTLK;D-QU?}Zku z{!iAmGvvzG`rrRd%B36i^pVHjCzXlyt9Nzln)pCi?rp2TZuM6-to{$y#|s-Gpxj@p z^w+Gb-|3fbh$swh3!P(}J$vy5{nmp+3mG_w3ef_Ii?-eo=82oFPYLuA4wh69>7H; zN?H=X5y>G5aAmk-ftf}>j+6a6{CO7gtklaj`6f#Izd`&1o!Z{!P&GJDiqd1SHu+1WPf>R=8pl z%*SyFQ~CVc-V}fGxv!s{?O(pD_NMY^J`EQ|1)SaJ8BX1NRB#&=V=s^ z_}}4#O_vuMwOXNAEKJqhlI!O4W^E4bb^o41K%GzXdeO{Hd4)VL<#JKLR1nroKjc~Z ftPnc%LZeXPrD}0H&ui1QVztWQ>wEQdma%^TH_UR6 diff --git a/substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.pwasm_libc1.rust-cgu.o b/substrate/wasm-runtime/target/debug/deps/pwasm_libc-b023388293df7da5.pwasm_libc1.rust-cgu.o deleted file mode 100644 index 97cda093e5671de857e2df2707019da063a4a503..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4208 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 Xk5~A7R5dzuyPJPu&DrP0@2>nGWWk?; diff --git a/substrate/wasm-runtime/target/release/.cargo-lock b/substrate/wasm-runtime/target/release/.cargo-lock deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.cargo-lock b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.cargo-lock deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-alloc-e37006629c0ab425/dep-lib-pwasm_alloc-e37006629c0ab425 b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-alloc-e37006629c0ab425/dep-lib-pwasm_alloc-e37006629c0ab425 deleted file mode 100644 index a4da1cb1a4785e0602bfc1a4030bfe35b9ce362d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 342 zcmb`BK@Ng25Jg@06kecAQxqdx&fwY%?Sv3YOJ<5(U%|LjmlR)U(X??h22+3(GPsUW0 kJv)Q#!5#~K0QG)D^oD@2TdjgcslVrZZSkK&-Urs|4sPChY5)KL diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-alloc-e37006629c0ab425/lib-pwasm_alloc-e37006629c0ab425 b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-alloc-e37006629c0ab425/lib-pwasm_alloc-e37006629c0ab425 deleted file mode 100644 index 96fca0ffc7..0000000000 --- a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-alloc-e37006629c0ab425/lib-pwasm_alloc-e37006629c0ab425 +++ /dev/null @@ -1 +0,0 @@ -ee4d5b5400bf9619 \ No newline at end of file diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-alloc-e37006629c0ab425/lib-pwasm_alloc-e37006629c0ab425.json b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-alloc-e37006629c0ab425/lib-pwasm_alloc-e37006629c0ab425.json deleted file mode 100644 index c1764b5654..0000000000 --- a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-alloc-e37006629c0ab425/lib-pwasm_alloc-e37006629c0ab425.json +++ /dev/null @@ -1 +0,0 @@ -{"rustc":8294656847287967537,"features":"[]","target":1127969377865045195,"profile":42358739494345872,"deps":[["pwasm-libc v0.1.0 (file:///Users/gav/Core/polkadot/wasm-runtime/pwasm-libc)",6197225601014249845]],"local":[{"MtimeBased":[[1515500743,816953612],"/Users/gav/Core/polkadot/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-alloc-e37006629c0ab425/dep-lib-pwasm_alloc-e37006629c0ab425"]}],"rustflags":[]} \ No newline at end of file diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-libc-9375d1aea6d3c98f/dep-lib-pwasm_libc-9375d1aea6d3c98f b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/pwasm-libc-9375d1aea6d3c98f/dep-lib-pwasm_libc-9375d1aea6d3c98f deleted file mode 100644 index 75ac0990e3be0ca9842cb7435c423e19f0ebb7d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 337 zcmb`BOAf*?3`AMy6kH&+AmY<*dj{6XB&MpGCXt=e>(hYP0b;?*BkPUk!AXb(I=n#} znIJ_!poEcl2zUt)9XV;v8NVm^`5nI7$M(zofEoUV_!NIqcj9 k3HQ#}`gpB)c{l3^p$h@Rwsa~MrT#AS&BT4wcx%_FJAK4?eEe)=y6?(|67Q diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/lib-runtime_polkadot b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/lib-runtime_polkadot deleted file mode 100644 index 77c1ca3667..0000000000 --- a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/lib-runtime_polkadot +++ /dev/null @@ -1 +0,0 @@ -6eee55b59b574864 \ No newline at end of file diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/lib-runtime_polkadot.json b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/lib-runtime_polkadot.json deleted file mode 100644 index 39174c4da4..0000000000 --- a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/lib-runtime_polkadot.json +++ /dev/null @@ -1 +0,0 @@ -{"rustc":8294656847287967537,"features":"[\"default\", \"without-std\"]","target":15371597068611496627,"profile":42358739494345872,"deps":[["runtime-support v0.1.0 (file:///Users/gav/Core/polkadot/wasm-runtime/support)",18014962227880213226]],"local":[{"MtimeBased":[[1515506687,785085370],"/Users/gav/Core/polkadot/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-polkadot-1e4c8740d04ba868/dep-lib-runtime_polkadot"]}],"rustflags":[]} \ No newline at end of file diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/dep-lib-runtime_support-5482fb51bf4d410e b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/dep-lib-runtime_support-5482fb51bf4d410e deleted file mode 100644 index e910e84870e0c19cd1c4960302fa60875852926d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 338 zcmb`BF%H5o5Cp0H3O?W*366x)@&;;T<4Y99@mY5^`92^*1riigTkOti;3UWbgT2C$ z7$H%Ztfvf%m05F%d7N>}GF8;H~yIiMkqBDC% diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/lib-runtime_support-5482fb51bf4d410e b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/lib-runtime_support-5482fb51bf4d410e deleted file mode 100644 index 7d69f92972..0000000000 --- a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/lib-runtime_support-5482fb51bf4d410e +++ /dev/null @@ -1 +0,0 @@ -ea3ae1eab20002fa \ No newline at end of file diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/lib-runtime_support-5482fb51bf4d410e.json b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/lib-runtime_support-5482fb51bf4d410e.json deleted file mode 100644 index 1e4859a996..0000000000 --- a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/lib-runtime_support-5482fb51bf4d410e.json +++ /dev/null @@ -1 +0,0 @@ -{"rustc":8294656847287967537,"features":"[]","target":14982045766639954252,"profile":42358739494345872,"deps":[["pwasm-alloc v0.1.0 (file:///Users/gav/Core/polkadot/wasm-runtime/pwasm-alloc)",1843871105590971886],["pwasm-libc v0.1.0 (file:///Users/gav/Core/polkadot/wasm-runtime/pwasm-libc)",6197225601014249845]],"local":[{"MtimeBased":[[1515504344,57881737],"/Users/gav/Core/polkadot/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-support-5482fb51bf4d410e/dep-lib-runtime_support-5482fb51bf4d410e"]}],"rustflags":[]} \ No newline at end of file diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-test-0ee9f37942e84b82/dep-lib-runtime_test b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/.fingerprint/runtime-test-0ee9f37942e84b82/dep-lib-runtime_test deleted file mode 100644 index 9aade611431b40cb99925f0fc1275d234f5704d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 286 zcmcJJF%E)26hy7}6kY%((T>(LP?L{4A%ta@{QrUL8=^MG!p3T*n3*?djcOQV!>uT> zlr%{!j$Lf7bj?1_JmHrVTy)^GdA(F?o^sjqTcJ!8BO({WYq)co*9WRO9~P!}q_MBn OLijH`~bx%98fF%rK-ZlO;==WwOiIrLwdrl~7Wt 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 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/deps/libruntime_support-5482fb51bf4d410e.rlib b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/deps/libruntime_support-5482fb51bf4d410e.rlib deleted file mode 100644 index c74a5505236b2abd831d543c288f99ad02138b74..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13160 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
    HR$IqRQ-~NdMd_~>}hj^GH`OEk}jvxFLe4Nh1 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 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/deps/runtime_polkadot.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/deps/runtime_polkadot.wasm deleted file mode 100644 index 228d1aaf0c24cc037dfc52fcf4da91896ab05f32..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 341 zcmYLE%Wi})3>+unnXSaCx1RWv?nmqySn5`&n}8tf<5GUT3AEy1duC*NY&4T00Q45s zw7>@~wOp1^gwH=UAkL9wdrSG@s?U)b2s97WG}mk2f_8yTJ3JwRpw|vIroZu~Y%^>o zc3#L*DU}d{pcD;2Bnii4$YR5$AD;p*{NQ$WTwT1$H=@^n?#9MWP3yYeB0i4u6t{hisxQldmrq{!K|6U$CyBPoS)B|e~CrsN!4KIcTyA}j+ENEHdv z(IJK^0>pc$I)yyQ!{k&rDvEhm_UQR`sOi_{+r68;qgT_{NwcC%hTbINQRp-d^(&S96o=3 z^5k$jJUTd=o}3;&9g>puLe?i?k@V|{;pEASmz{(S62r;lDz!^zoj+KJ>M^5S%K zJf%o<^kj_HR0on;sk;P7e=8$7I(| z&oTUB_;hr9aDM#t==g}7$ckZQicT=7k|{Bym(0DWP4Ip#S5*9Uqxh3DGd)=Rd15oZ ztEpA{C3!-x(O!AQYTBAdrSiIooVILg-A4PRX44p_tPf)^qDDTSZPjH1;hH=YY3s>H zdm0L%-5d0JmPr18r&K(Hl6YZ&9$aBU3lV*nu&U@)AGnLbe4zat#Z^sZiifL_7{PVq@+PZ(uzAJ)oR zHf|y=8pQ<{kIDdg(Zql%bw-e5jUEsnG|F$0|7rAOz>PLNL+$?7BK2DBzl%3OvRQJ8q>KRErAeZ z0E8$-YS}-p=@K`85z|Y0)|ODheYSPNA90KWRhz{$^WEr zt=im|clDr7eGbEafRT`w^-jqptgVy9W>G%hhub6j5V(Jl9J~_{%$9+KxCi`XN^X|%0lM7^# z^`+1EwChX}kNp^5*|;vC2iE%T;LIoC;F9}etO^2#gfHqItX9=zZ>g zYL>$Bok4JzpgS~5%Bj1Av<$?-6{k%owS?f=Ivv2n%T71bFJRJ^djX@Y#KM zg8T3Y$O}ldAoQWIr{ocQZE#~`Ca4z!67;}h22qn_7pjy@57ePE{x@+CDPqKmqSK&| zpAn*#?W<|Xo@g{iIpS)h}sw9HhUO|C-+ff;GEDG^cmq^K?FlN z)OgSj8qDDK=7NBvloR7J_+%wp3>*j-Vl`psc`|4-NxCd#Nddl?rzbQbJ>lF+dIrft z(i2C02J?g0; z3!j5MF50}@1({avH*ow)offy&7fYR9U~#`*>I|uaHxIA5=tRgb@DASwXIJi5&P$x=(UCtoU@AyAQ_X7|Xl341E9mKP8?}vA2+~6S((Q<4td(V1{$Er!C zAyD=_e|Fem^_N(cG=|0hE1Ty0gq)G2e>1zBoLxfCFRY}Lcerlh)!pS9v+rGvP~q;Z zqQ1iwWbZB!x*GKzUW3#-3xq=aK$=noq=Hbn>vqJ8qMP7rkp3Aa@aSAe_igK)TvQ28 z{HR>#bxgj6+GoGq<{RiE5hBRmL>K7&NSx!HO1olYi#IThorV)!xqI}T>SAZY1^iac z%agnMl|m&Ww)KUFI!==aZSgH=*hSnyV_*w_#haLc$sj5r7LmD)89*bn15>sz+73H} zT63P_B`I(5Hm0`%4EOiTO}>NS?at2~bT?5Ipm38SL4tKjV_{44_m5xU-+$=aP(GrR zsN7Ad1}b->yT0pE4OH%WxW(?8R0EY;vn-ib+kh6T2uY~Q@-CXvvPa`=h#n|Uf>_uP zcRZIpj4~UbMTIm}3s4|-Hl`;hM?>Ou>^VH2esyv>n!Y6VwthW4cye-%9~j)X zcJ-$Pe`Mp)@r!e;d{5SNdVV0AiBLDXB%3aN^q@|$c5%dLct&`YY)@q0nEa7!{^jU+ UboSNos3Cr(Y>MAV{^VKnUuVwX;Q#;t diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libpwasm_alloc.d b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libpwasm_alloc.d deleted file mode 100644 index 4bcb36f425..0000000000 --- a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libpwasm_alloc.d +++ /dev/null @@ -1 +0,0 @@ -/Users/gav/Core/polkadot/wasm-runtime/target/wasm32-unknown-unknown/release/libpwasm_alloc.rlib: /Users/gav/Core/polkadot/wasm-runtime/pwasm-libc/src/lib.rs /Users/gav/Core/polkadot/wasm-runtime/pwasm-alloc/src/lib.rs diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libpwasm_alloc.rlib b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libpwasm_alloc.rlib deleted file mode 100644 index e3eb1a92d763dab9d4914d81a7146b0aafa6be2f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13718 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 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libruntime_support.d b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libruntime_support.d deleted file mode 100644 index 6ea9ca2b93..0000000000 --- a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libruntime_support.d +++ /dev/null @@ -1 +0,0 @@ -/Users/gav/Core/polkadot/wasm-runtime/target/wasm32-unknown-unknown/release/libruntime_support.rlib: /Users/gav/Core/polkadot/wasm-runtime/pwasm-alloc/src/lib.rs /Users/gav/Core/polkadot/wasm-runtime/pwasm-libc/src/lib.rs /Users/gav/Core/polkadot/wasm-runtime/support/src/lib.rs diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libruntime_support.rlib b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/libruntime_support.rlib deleted file mode 100644 index c74a5505236b2abd831d543c288f99ad02138b74..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13160 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
      HR$IqRQ-~NdMd_~>}hj^GH`OEk}jvxFLe4Nh1 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 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm deleted file mode 100644 index be2ae9b30e8d7d68992f083914c317bed5487e55..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 218 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 UboSNos3Cr(Y>MAV{^VKnUuVwX;Q#;t From 6a69b71f4629ef30ebca7fbd230df68e268a4a7a Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 9 Jan 2018 16:01:46 +0100 Subject: [PATCH 012/112] Add wasm binaries. --- .../release/runtime_polkadot.compact.wasm | Bin 0 -> 218 bytes .../release/runtime_polkadot.wasm | Bin 0 -> 341 bytes .../release/runtime_test.compact.wasm | Bin 0 -> 3392 bytes .../release/runtime_test.wasm | Bin 0 -> 3480 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm create mode 100644 substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm new file mode 100644 index 0000000000000000000000000000000000000000..be2ae9b30e8d7d68992f083914c317bed5487e55 GIT binary patch literal 218 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 UboSNos3Cr(Y>MAV{^VKnUuVwX;Q#;t literal 0 HcmV?d00001 From 391fb191439583f87b6f450c767b525a1a83c171 Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 9 Jan 2018 17:50:35 +0100 Subject: [PATCH 013/112] Fix test. --- substrate/executor/src/wasm_executor.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index e0d47de267..cb2df774d9 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -252,8 +252,8 @@ mod tests { b"\0code".to_vec() => b"Hello world".to_vec(), b"input".to_vec() => b"Hello world".to_vec(), b"code".to_vec() => b"The code".to_vec(), - b"\0validator_count".to_vec() => vec![1], - b"\0validator".to_vec() => b"Hello world".to_vec() + b"\0authority_count".to_vec() => vec![1], + b"\0authority".to_vec() => b"Hello world".to_vec() ]; assert_eq!(expected, ext.storage); } From adc2e52aa3c91028204e5a3e7a6391df25dbfc09 Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 9 Jan 2018 19:28:22 +0100 Subject: [PATCH 014/112] Native storage support API. --- substrate/Cargo.lock | 20 +++++++ substrate/native-runtime/support/Cargo.toml | 4 ++ substrate/native-runtime/support/src/lib.rs | 65 ++++++++++++++++++++- 3 files changed, 86 insertions(+), 3 deletions(-) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 61afee3c0a..2d02a1799c 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -425,6 +425,11 @@ name = "lazy_static" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "lazy_static" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "lazycell" version = "0.5.1" @@ -568,6 +573,15 @@ dependencies = [ "parking_lot_core 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parking_lot_core" version = "0.2.6" @@ -818,6 +832,10 @@ dependencies = [ [[package]] name = "runtime-support" version = "0.1.0" +dependencies = [ + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "rustc-demangle" @@ -1189,6 +1207,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9e5e58fa1a4c3b915a561a78a22ee0cac6ab97dca2504428bc1cb074375f8d5" +"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" "checksum lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b585b7a6811fb03aa10e74b278a0f00f8dd9b45dc681f148bb29fa5cb61859b" "checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2" "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" @@ -1205,6 +1224,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" "checksum parity-wasm 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)" = "235801e9531998c4bb307f4ea6833c9f40a4cf132895219ac8c2cd25a9b310f7" "checksum parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e" +"checksum parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3e7f7c9857874e54afeb950eebeae662b1e51a2493666d2ea4c0a5d91dcf0412" "checksum parking_lot_core 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4f610cb9664da38e417ea3225f23051f589851999535290e077939838ab7a595" "checksum patricia-trie 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f1e2f638d79aba5c4a71a4f373df6e3cd702250a53b7f0ed4da1e2a7be9737ae" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" diff --git a/substrate/native-runtime/support/Cargo.toml b/substrate/native-runtime/support/Cargo.toml index b9c56adf24..4f4e0202b5 100644 --- a/substrate/native-runtime/support/Cargo.toml +++ b/substrate/native-runtime/support/Cargo.toml @@ -5,3 +5,7 @@ authors = ["Parity Technologies "] [features] strict = [] + +[dependencies] +lazy_static = "1.0.0" +parking_lot = "0.5" diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index 93d3aad9cd..0e12d5e678 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -1,14 +1,73 @@ +#[macro_use] +extern crate lazy_static; +extern crate parking_lot; + pub use std::vec::Vec; pub use std::rc::Rc; pub use std::cell::RefCell; pub use std::boxed::Box; pub use std::mem::{size_of, transmute}; -pub fn storage(_key: &[u8]) -> Vec { vec![] } -pub fn storage_into(_key: &[u8]) -> Option { None } -pub fn set_storage(_key: &[u8], _value: &[u8]) {} +use std::collections::HashMap; +use parking_lot::Mutex; + +lazy_static! { + static ref HASHMAP: Mutex, Vec>> = Mutex::new(HashMap::new()); +} + +pub fn storage(_key: &[u8]) -> Vec { + HASHMAP.lock().get(_key).cloned().unwrap_or_else(Vec::new) +} + +pub fn storage_into(_key: &[u8]) -> Option { + let size = size_of::(); + if let Some(value) = HASHMAP.lock().get(_key) { + if value.len() == size { + unsafe { + let mut result: T = std::mem::uninitialized(); + std::slice::from_raw_parts_mut(transmute::<*mut T, *mut u8>(&mut result), size) + .copy_from_slice(&value); + return Some(result); + } + } + } + None +} + +pub fn set_storage(_key: &[u8], _value: &[u8]) { + HASHMAP.lock().insert(_key.to_vec(), _value.to_vec()); +} + +pub fn init_storage(new: HashMap, Vec>) { + *HASHMAP.lock() = new; +} #[macro_export] macro_rules! impl_stubs { ($( $name:ident ),*) => {} } + +#[cfg(test)] +mod tests { + use super::*; + + macro_rules! map { + ($( $name:expr => $value:expr ),*) => ( + vec![ $( ( $name, $value ) ),* ].into_iter().collect() + ) + } + + #[test] + fn storage_works() { + assert_eq!(storage(b"hello"), vec![]); + set_storage(b"hello", b"world"); + assert_eq!(storage(b"hello"), b"world".to_vec()); + assert_eq!(storage(b"foo"), vec![]); + set_storage(b"foo", &[1, 2, 3][..]); + assert_eq!(storage_into::<[u8; 3]>(b"foo"), Some([1, 2, 3])); + assert_eq!(storage_into::<[u8; 3]>(b"hello"), None); + init_storage(map![b"foo".to_vec() => b"bar".to_vec()]); + assert_eq!(storage(b"hello"), vec![]); + assert_eq!(storage(b"foo"), b"bar".to_vec()); + } +} From 5f86160320de3e931aa9e03f566b891f039b1ca4 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 10 Jan 2018 14:12:14 +0100 Subject: [PATCH 015/112] Add environmental module --- substrate/environmental/Cargo.toml | 4 ++ substrate/environmental/src/lib.rs | 107 +++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 substrate/environmental/Cargo.toml create mode 100644 substrate/environmental/src/lib.rs diff --git a/substrate/environmental/Cargo.toml b/substrate/environmental/Cargo.toml new file mode 100644 index 0000000000..52c3337f8a --- /dev/null +++ b/substrate/environmental/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "environmental" +version = "0.1.0" +authors = ["Parity Technologies "] diff --git a/substrate/environmental/src/lib.rs b/substrate/environmental/src/lib.rs new file mode 100644 index 0000000000..db46b13158 --- /dev/null +++ b/substrate/environmental/src/lib.rs @@ -0,0 +1,107 @@ +// 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 . + +use std::cell::RefCell; +use std::thread::LocalKey; + +pub fn using_environment<'a, T: 'a, S, F: FnOnce()>( + global: &'static LocalKey>, + protected: &'a mut T, + f: F +) { + global.with(|r| *r.borrow_mut() = protected as *mut T as *mut S); + f(); + global.with(|r| *r.borrow_mut() = 0 as *mut S); +} + +pub fn with_environment<'r, S, T: 'r, F: FnOnce(&'r mut T)>( + global: &'static LocalKey>, + mutator: F, +) { + global.with(|r| { + let br = r.borrow_mut(); + if *br != 0 as *mut S { + // safe because it's only non-zero when it in with_environment, which + // is holding on to the underlying reference safely + unsafe { + mutator(&mut *(*br as *mut S as *mut T)); + } + } + }); +} + +#[macro_export] +macro_rules! decl_environment { + ($name:ident : $t:ty) => { + thread_local! { + static $name: std::cell::RefCell<*mut $t> = std::cell::RefCell::new(0 as *mut $t); + } + } +} + +#[macro_export] +macro_rules! declare_generic_environment { + ($name:ident : $t:tt) => { + mod $name { + use super::*; + + decl_environment!(GLOBAL: $t<'static> ); + + pub fn using<'a: 'b, 'b, F: FnOnce(), T: 'a>(protected: &'b mut T, f: F) { + $crate::using_environment(&GLOBAL, protected, f); + } + + pub fn with FnOnce(&'r mut $t<'t>)>(f: F) { + let dummy = (); + with_closed(f, &dummy); + } + + fn with_closed<'d: 't, 't: 'r, 'r, F: FnOnce(&'r mut $t<'t>)>( + f: F, + _dummy: &'d (), + ) { + $crate::with_environment(&GLOBAL, f); + } + } + } +} + +#[macro_export] +macro_rules! declare_simple_environment { + ($name:ident : $t:tt) => { + mod $name { + use super::*; + + decl_environment!(GLOBAL: $t ); + + pub fn using<'a: 'b, 'b, F: FnOnce(), T: 'a>(protected: &'b mut T, f: F) { + $crate::using_environment(&GLOBAL, protected, f); + } + + pub fn with FnOnce(&'r mut $t)>(f: F) { + let dummy = (); + with_closed(f, &dummy); + } + + fn with_closed<'d: 'r, 'r, F: FnOnce(&'r mut $t)>( + f: F, + _dummy: &'d (), + ) { + $crate::with_environment(&GLOBAL, f); + } + } + } +} From ad9037df2d71ce8b2aa67b1ab5c29fa389338a9a Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 10 Jan 2018 14:39:56 +0100 Subject: [PATCH 016/112] Add native environment to make native source-code compatible with wasm. Also tests. --- substrate/Cargo.lock | 6 ++ substrate/Cargo.toml | 1 + substrate/environmental/src/lib.rs | 35 ++++--- substrate/executor/src/wasm_utils.rs | 6 +- substrate/native-runtime/support/Cargo.toml | 2 + substrate/native-runtime/support/src/lib.rs | 106 ++++++++++++++------ 6 files changed, 108 insertions(+), 48 deletions(-) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 2d02a1799c..d0eee3e39a 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -170,6 +170,10 @@ dependencies = [ "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "environmental" +version = "0.1.0" + [[package]] name = "error-chain" version = "0.11.0" @@ -833,8 +837,10 @@ dependencies = [ name = "runtime-support" version = "0.1.0" dependencies = [ + "environmental 0.1.0", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "polkadot-state-machine 0.1.0", ] [[package]] diff --git a/substrate/Cargo.toml b/substrate/Cargo.toml index bfbff56969..21232d39ef 100644 --- a/substrate/Cargo.toml +++ b/substrate/Cargo.toml @@ -12,6 +12,7 @@ members = [ "candidate-agreement", "client", "collator", + "environmental", "executor", "primitives", "rpc", diff --git a/substrate/environmental/src/lib.rs b/substrate/environmental/src/lib.rs index db46b13158..420c22f44f 100644 --- a/substrate/environmental/src/lib.rs +++ b/substrate/environmental/src/lib.rs @@ -27,20 +27,23 @@ pub fn using_environment<'a, T: 'a, S, F: FnOnce()>( global.with(|r| *r.borrow_mut() = 0 as *mut S); } -pub fn with_environment<'r, S, T: 'r, F: FnOnce(&'r mut T)>( +pub fn with_environment<'r, R, S, T: 'r, F: FnOnce(&'r mut T) -> R>( global: &'static LocalKey>, mutator: F, -) { +) -> Option { + global.with(|r| { let br = r.borrow_mut(); if *br != 0 as *mut S { // safe because it's only non-zero when it in with_environment, which // is holding on to the underlying reference safely unsafe { - mutator(&mut *(*br as *mut S as *mut T)); + Some(mutator(&mut *(*br as *mut S as *mut T))) } + } else { + None } - }); + }) } #[macro_export] @@ -64,16 +67,18 @@ macro_rules! declare_generic_environment { $crate::using_environment(&GLOBAL, protected, f); } - pub fn with FnOnce(&'r mut $t<'t>)>(f: F) { + pub fn with FnOnce(&'r mut $t<'t>) -> R>( + f: F + ) -> Option { let dummy = (); - with_closed(f, &dummy); + with_closed(f, &dummy) } - fn with_closed<'d: 't, 't: 'r, 'r, F: FnOnce(&'r mut $t<'t>)>( + fn with_closed<'d: 't, 't: 'r, 'r, R, F: FnOnce(&'r mut $t<'t>) -> R>( f: F, _dummy: &'d (), - ) { - $crate::with_environment(&GLOBAL, f); + ) -> Option { + $crate::with_environment(&GLOBAL, f) } } } @@ -91,16 +96,18 @@ macro_rules! declare_simple_environment { $crate::using_environment(&GLOBAL, protected, f); } - pub fn with FnOnce(&'r mut $t)>(f: F) { + pub fn with FnOnce(&'r mut $t -> R)>( + f: F + ) -> Option { let dummy = (); - with_closed(f, &dummy); + with_closed(f, &dummy) } - fn with_closed<'d: 'r, 'r, F: FnOnce(&'r mut $t)>( + fn with_closed<'d: 'r, 'r, R, F: FnOnce(&'r mut $t -> R)>( f: F, _dummy: &'d (), - ) { - $crate::with_environment(&GLOBAL, f); + ) -> Option { + $crate::with_environment(&GLOBAL, f) } } } diff --git a/substrate/executor/src/wasm_utils.rs b/substrate/executor/src/wasm_utils.rs index 6d4fedfedb..f6440628b9 100644 --- a/substrate/executor/src/wasm_utils.rs +++ b/substrate/executor/src/wasm_utils.rs @@ -119,13 +119,13 @@ pub trait IntoUserDefinedElements { #[macro_export] macro_rules! impl_function_executor { ( $objectname:ident : $structname:ty, $( $name:ident ( $( $names:ident : $params:ty ),* ) $( -> $returns:ty )* => $body:tt ),* => $($pre:tt)+ ) => ( - impl $( $pre ) + $crate::wasm_utils::UserFunctionExecutor<$crate::wasm_utils::DummyUserError> for $structname { + impl $($pre)+ $crate::wasm_utils::UserFunctionExecutor<$crate::wasm_utils::DummyUserError> for $structname { dispatch!($objectname, $( $name( $( $names : $params ),* ) $( -> $returns )* => $body ),*); } - impl $( $pre ) + $structname { + impl $($pre)+ $structname { signatures!($( $name( $( $params ),* ) $( -> $returns )* ),*); } - impl $( $pre ) + $crate::wasm_utils::IntoUserDefinedElements for $structname { + impl $($pre)+ $crate::wasm_utils::IntoUserDefinedElements for $structname { fn into_user_defined_elements(&mut self) -> UserDefinedElements<$crate::wasm_utils::DummyUserError> { $crate::wasm_utils::UserDefinedElements { executor: Some(self), diff --git a/substrate/native-runtime/support/Cargo.toml b/substrate/native-runtime/support/Cargo.toml index 4f4e0202b5..3f979bd4ff 100644 --- a/substrate/native-runtime/support/Cargo.toml +++ b/substrate/native-runtime/support/Cargo.toml @@ -9,3 +9,5 @@ strict = [] [dependencies] lazy_static = "1.0.0" parking_lot = "0.5" +polkadot-state-machine = { path = "../../state_machine" , version = "0.1" } +environmental = { path = "../../environmental", version = "0.1.0" } diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index 0e12d5e678..091e07fbce 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -1,6 +1,6 @@ #[macro_use] -extern crate lazy_static; -extern crate parking_lot; +extern crate environmental; +extern crate polkadot_state_machine; pub use std::vec::Vec; pub use std::rc::Rc; @@ -8,38 +8,51 @@ pub use std::cell::RefCell; pub use std::boxed::Box; pub use std::mem::{size_of, transmute}; -use std::collections::HashMap; -use parking_lot::Mutex; +use polkadot_state_machine::Externalities; +use std::fmt; -lazy_static! { - static ref HASHMAP: Mutex, Vec>> = Mutex::new(HashMap::new()); +// TODO: use the real error, not NoError. + +#[derive(Debug)] +struct NoError; +impl fmt::Display for NoError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "") } } +pub struct ExternalitiesHolder<'a> { + ext: &'a mut Externalities, +} + +declare_generic_environment!(ext : ExternalitiesHolder); + pub fn storage(_key: &[u8]) -> Vec { - HASHMAP.lock().get(_key).cloned().unwrap_or_else(Vec::new) + ext::with(|holder| holder.ext.storage(_key).ok().map(|s| s.to_vec())) + .unwrap_or(None) + .unwrap_or_else(|| vec![]) } pub fn storage_into(_key: &[u8]) -> Option { let size = size_of::(); - if let Some(value) = HASHMAP.lock().get(_key) { - if value.len() == size { - unsafe { - let mut result: T = std::mem::uninitialized(); - std::slice::from_raw_parts_mut(transmute::<*mut T, *mut u8>(&mut result), size) - .copy_from_slice(&value); - return Some(result); + + ext::with(|holder| { + if let Ok(value) = holder.ext.storage(_key) { + if value.len() == size { + unsafe { + let mut result: T = std::mem::uninitialized(); + std::slice::from_raw_parts_mut(transmute::<*mut T, *mut u8>(&mut result), size) + .copy_from_slice(&value); + return Some(result); + } } } - } - None + None + }).unwrap_or(None) } pub fn set_storage(_key: &[u8], _value: &[u8]) { - HASHMAP.lock().insert(_key.to_vec(), _value.to_vec()); -} - -pub fn init_storage(new: HashMap, Vec>) { - *HASHMAP.lock() = new; + ext::with(|holder| + holder.ext.set_storage(_key.to_vec(), _value.to_vec()) + ); } #[macro_export] @@ -50,6 +63,23 @@ macro_rules! impl_stubs { #[cfg(test)] mod tests { use super::*; + use std::collections::HashMap; + + #[derive(Debug, Default)] + struct TestExternalities { + storage: HashMap, Vec>, + } + impl Externalities for TestExternalities { + type Error = NoError; + + fn storage(&self, key: &[u8]) -> Result<&[u8], NoError> { + Ok(self.storage.get(&key.to_vec()).map_or(&[] as &[u8], Vec::as_slice)) + } + + fn set_storage(&mut self, key: Vec, value: Vec) { + self.storage.insert(key, value); + } + } macro_rules! map { ($( $name:expr => $value:expr ),*) => ( @@ -59,15 +89,29 @@ mod tests { #[test] fn storage_works() { - assert_eq!(storage(b"hello"), vec![]); - set_storage(b"hello", b"world"); - assert_eq!(storage(b"hello"), b"world".to_vec()); - assert_eq!(storage(b"foo"), vec![]); - set_storage(b"foo", &[1, 2, 3][..]); - assert_eq!(storage_into::<[u8; 3]>(b"foo"), Some([1, 2, 3])); - assert_eq!(storage_into::<[u8; 3]>(b"hello"), None); - init_storage(map![b"foo".to_vec() => b"bar".to_vec()]); - assert_eq!(storage(b"hello"), vec![]); - assert_eq!(storage(b"foo"), b"bar".to_vec()); + let mut t = TestExternalities { storage: map![], }; + + { + let mut h = ExternalitiesHolder { ext: &mut t, }; + ext::using(&mut h, || { + assert_eq!(storage(b"hello"), b"".to_vec()); + set_storage(b"hello", b"world"); + assert_eq!(storage(b"hello"), b"world".to_vec()); + assert_eq!(storage(b"foo"), b"".to_vec()); + set_storage(b"foo", &[1, 2, 3][..]); + assert_eq!(storage_into::<[u8; 3]>(b"foo"), Some([1, 2, 3])); + assert_eq!(storage_into::<[u8; 3]>(b"hello"), None); + }); + } + + t.storage = map![b"foo".to_vec() => b"bar".to_vec()]; + + { + let mut h = ExternalitiesHolder { ext: &mut t, }; + ext::using(&mut h, || { + assert_eq!(storage(b"hello"), b"".to_vec()); + assert_eq!(storage(b"foo"), b"bar".to_vec()); + }); + } } } From b48003b69a1b064131931933b3d7e5a7fce11ccb Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 10 Jan 2018 14:53:03 +0100 Subject: [PATCH 017/112] Finish up & polish environment stuff. --- substrate/environmental/src/lib.rs | 28 ++++++++----- substrate/native-runtime/support/src/lib.rs | 44 +++++++++++---------- 2 files changed, 42 insertions(+), 30 deletions(-) diff --git a/substrate/environmental/src/lib.rs b/substrate/environmental/src/lib.rs index 420c22f44f..b7fc47ea50 100644 --- a/substrate/environmental/src/lib.rs +++ b/substrate/environmental/src/lib.rs @@ -17,21 +17,21 @@ use std::cell::RefCell; use std::thread::LocalKey; -pub fn using_environment<'a, T: 'a, S, F: FnOnce()>( +pub fn using_environment<'a, T: 'a, R, S, F: FnOnce() -> R>( global: &'static LocalKey>, protected: &'a mut T, f: F -) { +) -> R { global.with(|r| *r.borrow_mut() = protected as *mut T as *mut S); - f(); + let r = f(); global.with(|r| *r.borrow_mut() = 0 as *mut S); + r } pub fn with_environment<'r, R, S, T: 'r, F: FnOnce(&'r mut T) -> R>( global: &'static LocalKey>, mutator: F, ) -> Option { - global.with(|r| { let br = r.borrow_mut(); if *br != 0 as *mut S { @@ -63,8 +63,11 @@ macro_rules! declare_generic_environment { decl_environment!(GLOBAL: $t<'static> ); - pub fn using<'a: 'b, 'b, F: FnOnce(), T: 'a>(protected: &'b mut T, f: F) { - $crate::using_environment(&GLOBAL, protected, f); + pub fn using<'a: 'b, 'b, R, F: FnOnce() -> R, T: 'a>( + protected: &'b mut T, + f: F + ) -> R { + $crate::using_environment(&GLOBAL, protected, f) } pub fn with FnOnce(&'r mut $t<'t>) -> R>( @@ -90,10 +93,13 @@ macro_rules! declare_simple_environment { mod $name { use super::*; - decl_environment!(GLOBAL: $t ); + decl_environment!(GLOBAL: $t); - pub fn using<'a: 'b, 'b, F: FnOnce(), T: 'a>(protected: &'b mut T, f: F) { - $crate::using_environment(&GLOBAL, protected, f); + pub fn using<'a: 'b, 'b, R, F: FnOnce() -> R, T: 'a>( + protected: &'b mut T, + f: F + ) -> R { + $crate::using_environment(&GLOBAL, protected, f) } pub fn with FnOnce(&'r mut $t -> R)>( @@ -112,3 +118,7 @@ macro_rules! declare_simple_environment { } } } + +// TODO: Docs +// TODO: Example +// TODO: Tests diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index 091e07fbce..2926a20891 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -14,7 +14,7 @@ use std::fmt; // TODO: use the real error, not NoError. #[derive(Debug)] -struct NoError; +pub struct NoError; impl fmt::Display for NoError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "") } } @@ -55,6 +55,13 @@ pub fn set_storage(_key: &[u8], _value: &[u8]) { ); } +/// Execute the given closure with global function available whose functionality routes into the +/// externalities `ext`. Forwards the value that the closure returns. +pub fn with_externalities R>(ext: &mut Externalities, f: F) -> R { + let mut h = ExternalitiesHolder { ext }; + ext::using(&mut h, f) +} + #[macro_export] macro_rules! impl_stubs { ($( $name:ident ),*) => {} @@ -90,28 +97,23 @@ mod tests { #[test] fn storage_works() { let mut t = TestExternalities { storage: map![], }; - - { - let mut h = ExternalitiesHolder { ext: &mut t, }; - ext::using(&mut h, || { - assert_eq!(storage(b"hello"), b"".to_vec()); - set_storage(b"hello", b"world"); - assert_eq!(storage(b"hello"), b"world".to_vec()); - assert_eq!(storage(b"foo"), b"".to_vec()); - set_storage(b"foo", &[1, 2, 3][..]); - assert_eq!(storage_into::<[u8; 3]>(b"foo"), Some([1, 2, 3])); - assert_eq!(storage_into::<[u8; 3]>(b"hello"), None); - }); - } + assert!(with_externalities(&mut t, || { + assert_eq!(storage(b"hello"), b"".to_vec()); + set_storage(b"hello", b"world"); + assert_eq!(storage(b"hello"), b"world".to_vec()); + assert_eq!(storage(b"foo"), b"".to_vec()); + set_storage(b"foo", &[1, 2, 3][..]); + assert_eq!(storage_into::<[u8; 3]>(b"foo"), Some([1, 2, 3])); + assert_eq!(storage_into::<[u8; 3]>(b"hello"), None); + true + })); t.storage = map![b"foo".to_vec() => b"bar".to_vec()]; - { - let mut h = ExternalitiesHolder { ext: &mut t, }; - ext::using(&mut h, || { - assert_eq!(storage(b"hello"), b"".to_vec()); - assert_eq!(storage(b"foo"), b"bar".to_vec()); - }); - } + assert!(!with_externalities(&mut t, || { + assert_eq!(storage(b"hello"), b"".to_vec()); + assert_eq!(storage(b"foo"), b"bar".to_vec()); + false + })); } } From fd65f3380ab08a27df9e43f2ea189e809de69e72 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 10 Jan 2018 15:08:41 +0100 Subject: [PATCH 018/112] Avoid using reentrancy issues. --- substrate/environmental/src/lib.rs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/substrate/environmental/src/lib.rs b/substrate/environmental/src/lib.rs index b7fc47ea50..cd278f8123 100644 --- a/substrate/environmental/src/lib.rs +++ b/substrate/environmental/src/lib.rs @@ -22,9 +22,21 @@ pub fn using_environment<'a, T: 'a, R, S, F: FnOnce() -> R>( protected: &'a mut T, f: F ) -> R { - global.with(|r| *r.borrow_mut() = protected as *mut T as *mut S); + // store the `protected` reference as a pointer so we can provide it to logic running within + // `f`. + // while re record this pointer (while it's non-zero) we guarantee: + // - it will only be used once at any time (no reentrancy); + // - that no other thread will use it; and + // - that we do not use the original mutating reference while the pointer. + // exists. + let original = global.with(|r| { + let mut b = r.borrow_mut(); + let o = *b; + *b = protected as *mut T as *mut S; + o + }); let r = f(); - global.with(|r| *r.borrow_mut() = 0 as *mut S); + global.with(|r| *r.borrow_mut() = original); r } @@ -35,8 +47,8 @@ pub fn with_environment<'r, R, S, T: 'r, F: FnOnce(&'r mut T) -> R>( global.with(|r| { let br = r.borrow_mut(); if *br != 0 as *mut S { - // safe because it's only non-zero when it in with_environment, which - // is holding on to the underlying reference safely + // safe because it's only non-zero when it's being called from using_environment, which + // is holding on to the underlying reference (and not using it itself) safely. unsafe { Some(mutator(&mut *(*br as *mut S as *mut T))) } From 8d1825fb0d62fc0ea4143ae6eb1b606440b37561 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 10 Jan 2018 18:58:49 +0100 Subject: [PATCH 019/112] Add some docs and a test. --- substrate/environmental/src/lib.rs | 61 +++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/substrate/environmental/src/lib.rs b/substrate/environmental/src/lib.rs index cd278f8123..0dcd55bdcb 100644 --- a/substrate/environmental/src/lib.rs +++ b/substrate/environmental/src/lib.rs @@ -14,9 +14,38 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -use std::cell::RefCell; +//! Safe global references to stack variables. +//! +//! Set up a global reference with declare_simple_environment! macro giving it a name and type. +//! Use the `using` function scoped under its name to name a reference and call a function that +//! takes no parameters yet can access said reference through the similarly place `with` function. +//! +//! # Examples +//! +//! ``` +//! #[macro_use] extern crate environmental; +//! // create a place for the global reference to exist. +//! declare_simple_environment!(counter: u32); +//! fn stuff() { +//! // do some stuff, accessing the named reference as desired. +//! counter::with(|value| *value += 1); +//! } +//! fn main() { +//! // declare a stack variable of the same type as our global declaration. +//! let mut local = 41u32; +//! // call stuff, setting up our `counter` environment as a refrence to our local counter var. +//! counter::using(&mut local, stuff); +//! println!("The answer is {:?}", local); // will print 42! +//! stuff(); // safe! doesn't do anything. +//! } +//! ``` + + +pub use std::cell::RefCell; use std::thread::LocalKey; +pub fn test_me() { panic!("Hello") } + pub fn using_environment<'a, T: 'a, R, S, F: FnOnce() -> R>( global: &'static LocalKey>, protected: &'a mut T, @@ -24,7 +53,7 @@ pub fn using_environment<'a, T: 'a, R, S, F: FnOnce() -> R>( ) -> R { // store the `protected` reference as a pointer so we can provide it to logic running within // `f`. - // while re record this pointer (while it's non-zero) we guarantee: + // while we record this pointer (while it's non-zero) we guarantee: // - it will only be used once at any time (no reentrancy); // - that no other thread will use it; and // - that we do not use the original mutating reference while the pointer. @@ -62,7 +91,7 @@ pub fn with_environment<'r, R, S, T: 'r, F: FnOnce(&'r mut T) -> R>( macro_rules! decl_environment { ($name:ident : $t:ty) => { thread_local! { - static $name: std::cell::RefCell<*mut $t> = std::cell::RefCell::new(0 as *mut $t); + static $name: $crate::RefCell<*mut $t> = $crate::RefCell::new(0 as *mut $t); } } } @@ -71,6 +100,7 @@ macro_rules! decl_environment { macro_rules! declare_generic_environment { ($name:ident : $t:tt) => { mod $name { + #[allow(unused_imports)] use super::*; decl_environment!(GLOBAL: $t<'static> ); @@ -103,6 +133,7 @@ macro_rules! declare_generic_environment { macro_rules! declare_simple_environment { ($name:ident : $t:tt) => { mod $name { + #[allow(unused_imports)] use super::*; decl_environment!(GLOBAL: $t); @@ -114,14 +145,14 @@ macro_rules! declare_simple_environment { $crate::using_environment(&GLOBAL, protected, f) } - pub fn with FnOnce(&'r mut $t -> R)>( + pub fn with FnOnce(&'r mut $t) -> R>( f: F ) -> Option { let dummy = (); with_closed(f, &dummy) } - fn with_closed<'d: 'r, 'r, R, F: FnOnce(&'r mut $t -> R)>( + fn with_closed<'d: 'r, 'r, R, F: FnOnce(&'r mut $t) -> R>( f: F, _dummy: &'d (), ) -> Option { @@ -134,3 +165,23 @@ macro_rules! declare_simple_environment { // TODO: Docs // TODO: Example // TODO: Tests + +#[cfg(test)] +mod tests { + declare_simple_environment!(counter: u32); + + fn stuff() { + // do some stuff, accessing the named reference as desired. + counter::with(|value| *value += 1); + } + + #[test] + fn simple_environment_works() { + // declare a stack variable of the same type as our global declaration. + let mut local = 41u32; + // call stuff, setting up our `counter` environment as a refrence to our local counter var. + counter::using(&mut local, stuff); + println!("The answer is {:?}", local); // will print 42! + stuff(); // safe! doesn't do anything. + } +} From 2d1f1a893375b3326bf6efb82b9b7dab0511e81c Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 10 Jan 2018 18:59:49 +0100 Subject: [PATCH 020/112] Remove unneeded function. --- substrate/environmental/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/substrate/environmental/src/lib.rs b/substrate/environmental/src/lib.rs index 0dcd55bdcb..2556b437ae 100644 --- a/substrate/environmental/src/lib.rs +++ b/substrate/environmental/src/lib.rs @@ -44,8 +44,6 @@ pub use std::cell::RefCell; use std::thread::LocalKey; -pub fn test_me() { panic!("Hello") } - pub fn using_environment<'a, T: 'a, R, S, F: FnOnce() -> R>( global: &'static LocalKey>, protected: &'a mut T, From e11f701c09e2980e31ad9458222c43cad87eef70 Mon Sep 17 00:00:00 2001 From: Gav Date: Thu, 11 Jan 2018 18:23:06 +0100 Subject: [PATCH 021/112] Documentation --- substrate/environmental/src/lib.rs | 171 ++++++++++++++------ substrate/native-runtime/support/src/lib.rs | 2 +- 2 files changed, 120 insertions(+), 53 deletions(-) diff --git a/substrate/environmental/src/lib.rs b/substrate/environmental/src/lib.rs index 2556b437ae..0c389e13dc 100644 --- a/substrate/environmental/src/lib.rs +++ b/substrate/environmental/src/lib.rs @@ -16,35 +16,36 @@ //! Safe global references to stack variables. //! -//! Set up a global reference with declare_simple_environment! macro giving it a name and type. +//! Set up a global reference with declare_simple! macro giving it a name and type. //! Use the `using` function scoped under its name to name a reference and call a function that -//! takes no parameters yet can access said reference through the similarly place `with` function. +//! takes no parameters yet can access said reference through the similarly placed `with` function. //! //! # Examples //! //! ``` //! #[macro_use] extern crate environmental; //! // create a place for the global reference to exist. -//! declare_simple_environment!(counter: u32); +//! declare_simple!(counter: u32); //! fn stuff() { //! // do some stuff, accessing the named reference as desired. -//! counter::with(|value| *value += 1); +//! counter::with(|i| *i += 1); //! } //! fn main() { //! // declare a stack variable of the same type as our global declaration. -//! let mut local = 41u32; -//! // call stuff, setting up our `counter` environment as a refrence to our local counter var. -//! counter::using(&mut local, stuff); -//! println!("The answer is {:?}", local); // will print 42! +//! let mut counter_value = 41u32; +//! // call stuff, setting up our `counter` environment as a refrence to our counter_value var. +//! counter::using(&mut counter_value, stuff); +//! println!("The answer is {:?}", counter_value); // will print 42! //! stuff(); // safe! doesn't do anything. //! } //! ``` - +#[doc(hidden)] pub use std::cell::RefCell; use std::thread::LocalKey; -pub fn using_environment<'a, T: 'a, R, S, F: FnOnce() -> R>( +#[doc(hidden)] +pub fn using<'a, T: 'a, R, S, F: FnOnce() -> R>( global: &'static LocalKey>, protected: &'a mut T, f: F @@ -67,14 +68,15 @@ pub fn using_environment<'a, T: 'a, R, S, F: FnOnce() -> R>( r } -pub fn with_environment<'r, R, S, T: 'r, F: FnOnce(&'r mut T) -> R>( +#[doc(hidden)] +pub fn with<'r, R, S, T: 'r, F: FnOnce(&'r mut T) -> R>( global: &'static LocalKey>, mutator: F, ) -> Option { global.with(|r| { let br = r.borrow_mut(); if *br != 0 as *mut S { - // safe because it's only non-zero when it's being called from using_environment, which + // safe because it's only non-zero when it's being called from using, which // is holding on to the underlying reference (and not using it itself) safely. unsafe { Some(mutator(&mut *(*br as *mut S as *mut T))) @@ -85,8 +87,9 @@ pub fn with_environment<'r, R, S, T: 'r, F: FnOnce(&'r mut T) -> R>( }) } +#[doc(hidden)] #[macro_export] -macro_rules! decl_environment { +macro_rules! decl { ($name:ident : $t:ty) => { thread_local! { static $name: $crate::RefCell<*mut $t> = $crate::RefCell::new(0 as *mut $t); @@ -94,53 +97,51 @@ macro_rules! decl_environment { } } +/// Declare a new global reference module whose underlying value does not contain references. +/// +/// Will create a module of a given name that contains two functions: +/// - `pub fn using<'a: 'b, 'b, R, F: FnOnce() -> R, T: 'a>(protected: &'b mut T, f: F) -> R` +/// This executes `f`, returning its value. During the call, the module's reference is set to +/// be equal to `protected`. +/// - `pub fn with FnOnce(&'r mut $t<'t>) -> R>(f: F) -> Option` +/// This executes `f`, returning its value if called from code that is being executed as part of +/// a `using` call. The function takes one argument: the same reference as provided to the most +/// recent `using` call. +/// +/// # Examples +/// +/// ``` +/// #[macro_use] extern crate environmental; +/// declare_simple!(counter: u32); +/// fn main() { +/// let mut counter_value = 41u32; +/// counter::using(&mut counter_value, || { +/// let odd = counter::with(|value| +/// if *value % 2 == 1 { +/// *value += 1; true +/// } else { +/// *value -= 3; false +/// }).unwrap(); // safe because we're inside a counter::using +/// println!("counter was {}", match odd { true => "odd", _ => "even" }); +/// }); +/// +/// println!("The answer is {:?}", counter_value); // 42 +/// } +/// ``` #[macro_export] -macro_rules! declare_generic_environment { +macro_rules! declare_simple { ($name:ident : $t:tt) => { mod $name { #[allow(unused_imports)] use super::*; - decl_environment!(GLOBAL: $t<'static> ); + decl!(GLOBAL: $t); pub fn using<'a: 'b, 'b, R, F: FnOnce() -> R, T: 'a>( protected: &'b mut T, f: F ) -> R { - $crate::using_environment(&GLOBAL, protected, f) - } - - pub fn with FnOnce(&'r mut $t<'t>) -> R>( - f: F - ) -> Option { - let dummy = (); - with_closed(f, &dummy) - } - - fn with_closed<'d: 't, 't: 'r, 'r, R, F: FnOnce(&'r mut $t<'t>) -> R>( - f: F, - _dummy: &'d (), - ) -> Option { - $crate::with_environment(&GLOBAL, f) - } - } - } -} - -#[macro_export] -macro_rules! declare_simple_environment { - ($name:ident : $t:tt) => { - mod $name { - #[allow(unused_imports)] - use super::*; - - decl_environment!(GLOBAL: $t); - - pub fn using<'a: 'b, 'b, R, F: FnOnce() -> R, T: 'a>( - protected: &'b mut T, - f: F - ) -> R { - $crate::using_environment(&GLOBAL, protected, f) + $crate::using(&GLOBAL, protected, f) } pub fn with FnOnce(&'r mut $t) -> R>( @@ -154,7 +155,73 @@ macro_rules! declare_simple_environment { f: F, _dummy: &'d (), ) -> Option { - $crate::with_environment(&GLOBAL, f) + $crate::with(&GLOBAL, f) + } + } + } +} + +/// Declare a new global reference module whose underlying value is generic over a reference. +/// +/// Will create a module of a given name that contains two functions: +/// - `pub fn using<'a: 'b, 'b, R, F: FnOnce() -> R, T: 'a>(protected: &'b mut T, f: F) -> R` +/// This executes `f`, returning its value. During the call, the module's reference is set to +/// be equal to `protected`. +/// - `pub fn with FnOnce(&'r mut $t<'t>) -> R>(f: F) -> Option` +/// This executes `f`, returning its value if called from code that is being executed as part of +/// a `using` call. The function takes one argument: the same reference as provided to the most +/// recent `using` call. +/// +/// # Examples +/// +/// ``` +/// #[macro_use] extern crate environmental; +/// // a type that we want to reference from a temp global; it has a reference in it. +/// struct WithReference<'a> { answer_ref: &'a mut u32, } +/// // create a place for the global reference to exist. +/// declare_generic!(counter: WithReference); +/// fn stuff() { +/// // do some stuff, accessing the named reference as desired. +/// counter::with(|i| *i.answer_ref += 1); +/// } +/// fn main() { +/// // declare a stack variable of the same type as our global declaration. +/// let mut answer = 41u32; +/// { +/// let mut ref_struct = WithReference { answer_ref: &mut answer, }; +/// counter::using(&mut ref_struct, stuff); +/// } +/// println!("The answer is {:?}", answer); // will print 42! +/// } +/// ``` +#[macro_export] +macro_rules! declare_generic { + ($name:ident : $t:tt) => { + mod $name { + #[allow(unused_imports)] + use super::*; + + decl!(GLOBAL: $t<'static> ); + + pub fn using<'a: 'b, 'b, R, F: FnOnce() -> R, T: 'a>( + protected: &'b mut T, + f: F + ) -> R { + $crate::using(&GLOBAL, protected, f) + } + + pub fn with FnOnce(&'r mut $t<'t>) -> R>( + f: F + ) -> Option { + let dummy = (); + with_closed(f, &dummy) + } + + fn with_closed<'d: 't, 't: 'r, 'r, R, F: FnOnce(&'r mut $t<'t>) -> R>( + f: F, + _dummy: &'d (), + ) -> Option { + $crate::with(&GLOBAL, f) } } } @@ -166,7 +233,7 @@ macro_rules! declare_simple_environment { #[cfg(test)] mod tests { - declare_simple_environment!(counter: u32); + declare_simple!(counter: u32); fn stuff() { // do some stuff, accessing the named reference as desired. @@ -174,7 +241,7 @@ mod tests { } #[test] - fn simple_environment_works() { + fn simple_works() { // declare a stack variable of the same type as our global declaration. let mut local = 41u32; // call stuff, setting up our `counter` environment as a refrence to our local counter var. diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index 2926a20891..93947dde68 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -23,7 +23,7 @@ pub struct ExternalitiesHolder<'a> { ext: &'a mut Externalities, } -declare_generic_environment!(ext : ExternalitiesHolder); +declare_generic!(ext : ExternalitiesHolder); pub fn storage(_key: &[u8]) -> Vec { ext::with(|holder| holder.ext.storage(_key).ok().map(|s| s.to_vec())) From 2b05b8ff5eebae736a3ff733b9930d6f5eeebeb0 Mon Sep 17 00:00:00 2001 From: Gav Date: Thu, 11 Jan 2018 18:28:29 +0100 Subject: [PATCH 022/112] Tweak docs --- substrate/environmental/src/lib.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/substrate/environmental/src/lib.rs b/substrate/environmental/src/lib.rs index 0c389e13dc..e921833301 100644 --- a/substrate/environmental/src/lib.rs +++ b/substrate/environmental/src/lib.rs @@ -100,13 +100,13 @@ macro_rules! decl { /// Declare a new global reference module whose underlying value does not contain references. /// /// Will create a module of a given name that contains two functions: -/// - `pub fn using<'a: 'b, 'b, R, F: FnOnce() -> R, T: 'a>(protected: &'b mut T, f: F) -> R` +/// * `pub fn using<'a: 'b, 'b, R, F: FnOnce() -> R, T: 'a>(protected: &'b mut T, f: F) -> R` /// This executes `f`, returning its value. During the call, the module's reference is set to /// be equal to `protected`. -/// - `pub fn with FnOnce(&'r mut $t<'t>) -> R>(f: F) -> Option` -/// This executes `f`, returning its value if called from code that is being executed as part of -/// a `using` call. The function takes one argument: the same reference as provided to the most -/// recent `using` call. +/// * `pub fn with FnOnce(&'r mut $t<'t>) -> R>(f: F) -> Option` +/// This executes `f`, returning `Some` of its value if called from code that is being executed +/// as part of a `using` call. If not, it returns `None`. `f` is provided with one argument: the +/// same reference as provided to the most recent `using` call. /// /// # Examples /// @@ -164,13 +164,14 @@ macro_rules! declare_simple { /// Declare a new global reference module whose underlying value is generic over a reference. /// /// Will create a module of a given name that contains two functions: -/// - `pub fn using<'a: 'b, 'b, R, F: FnOnce() -> R, T: 'a>(protected: &'b mut T, f: F) -> R` +/// +/// * `pub fn using<'a: 'b, 'b, R, F: FnOnce() -> R, T: 'a>(protected: &'b mut T, f: F) -> R` /// This executes `f`, returning its value. During the call, the module's reference is set to /// be equal to `protected`. -/// - `pub fn with FnOnce(&'r mut $t<'t>) -> R>(f: F) -> Option` -/// This executes `f`, returning its value if called from code that is being executed as part of -/// a `using` call. The function takes one argument: the same reference as provided to the most -/// recent `using` call. +/// * `pub fn with FnOnce(&'r mut $t<'t>) -> R>(f: F) -> Option` +/// This executes `f`, returning `Some` of its value if called from code that is being executed +/// as part of a `using` call. If not, it returns `None`. `f` is provided with one argument: the +/// same reference as provided to the most recent `using` call. /// /// # Examples /// From 6146779e6ea3e64ff44b8aba3d843d65662b7f63 Mon Sep 17 00:00:00 2001 From: Gav Date: Thu, 11 Jan 2018 18:29:08 +0100 Subject: [PATCH 023/112] Remove TODOs. --- substrate/environmental/src/lib.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/substrate/environmental/src/lib.rs b/substrate/environmental/src/lib.rs index e921833301..239a2fb90f 100644 --- a/substrate/environmental/src/lib.rs +++ b/substrate/environmental/src/lib.rs @@ -228,10 +228,6 @@ macro_rules! declare_generic { } } -// TODO: Docs -// TODO: Example -// TODO: Tests - #[cfg(test)] mod tests { declare_simple!(counter: u32); From bd8f67a20ddad66933f3b95ce035a38870d04be8 Mon Sep 17 00:00:00 2001 From: Gav Date: Sun, 14 Jan 2018 20:51:46 +0100 Subject: [PATCH 024/112] Balance transfers + util methods. --- substrate/native-runtime/support/src/lib.rs | 2 +- substrate/wasm-runtime/polkadot/src/lib.rs | 257 ++++++++++++++++---- 2 files changed, 212 insertions(+), 47 deletions(-) diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index 93947dde68..7bbd6d235e 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -8,7 +8,7 @@ pub use std::cell::RefCell; pub use std::boxed::Box; pub use std::mem::{size_of, transmute}; -use polkadot_state_machine::Externalities; +pub use polkadot_state_machine::Externalities; use std::fmt; // TODO: use the real error, not NoError. diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index fb8e5b86f8..205d2e31a7 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -3,7 +3,7 @@ #[macro_use] extern crate runtime_support; -use runtime_support::{set_storage, storage, storage_into, Vec, size_of}; +use runtime_support::{Vec, size_of}; use runtime_support::{Rc, RefCell, transmute, Box}; /// The hash of an ECDSA pub key which is used to identify an external transactor. @@ -93,6 +93,12 @@ struct Environment { block_number: BlockNumber, } +fn with_env T>(f: F) -> T { + let e = env(); + let mut eb = e.borrow_mut(); + f(&mut *eb) +} + fn env() -> Rc> { // Initialize it to a null value static mut SINGLETON: *const Rc> = 0 as *const Rc>; @@ -111,6 +117,77 @@ fn env() -> Rc> { } } +fn value_vec(mut value: u32, initial: Vec) -> Vec { + let mut acc = initial; + while value > 0 { + acc.push(value as u8); + value /= 256; + } + acc +} + +trait EndianSensitive: Sized { + fn to_le(self) -> Self { self } + fn to_be(self) -> Self { self } + fn from_le(self) -> Self { self } + fn from_be(self) -> Self { self } +} + +macro_rules! impl_endians { + ( $( $t:ty ),* ) => { $( + impl EndianSensitive for $t { + fn to_le(self) -> Self { <$t>::to_le(self) } + fn to_be(self) -> Self { <$t>::to_be(self) } + fn from_le(self) -> Self { <$t>::from_le(self) } + fn from_be(self) -> Self { <$t>::from_be(self) } + } + )* } +} +macro_rules! impl_non_endians { + ( $( $t:ty ),* ) => { $( + impl EndianSensitive for $t {} + )* } +} + +impl_endians!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize); +impl_non_endians!([u8; 20], [u8; 32]); + +trait Storage { + fn storage_into(key: &[u8]) -> Self; + fn store(self, key: &[u8]); +} + +impl Storage for T { + fn storage_into(key: &[u8]) -> Self { + runtime_support::storage_into(key).map(EndianSensitive::from_le).unwrap_or_else(Default::default) + } + + fn store(self, key: &[u8]) { + let size = size_of::(); + let value_bytes = self.to_le(); + let value_slice = unsafe { + std::slice::from_raw_parts(transmute::<*const Self, *const u8>(&value_bytes), size) + }; + runtime_support::set_storage(key, value_slice); + } +} + +fn storage_into(key: &[u8]) -> T { + T::storage_into(key) +} + + +trait KeyedVec { + fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec; +} +impl KeyedVec for AccountID { + fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec { + let mut r = prepend_key.to_vec(); + r.extend_from_slice(self); + r + } +} + // TODO: include RLP implementation // TODO: add keccak256 (or some better hashing scheme) & ECDSA-recover (or some better sig scheme) @@ -127,26 +204,27 @@ pub fn execute_transaction(_input: Vec) -> Vec { impl_stubs!(execute_block, execute_transaction); /// The current relay chain identifier. -fn chain_id() -> ChainID { +pub fn chain_id() -> ChainID { // TODO: retrieve from external unimplemented!() } -mod environment { +pub mod environment { use super::*; /// The current block number being processed. Set by `execute_block`. - pub fn block_number() -> BlockNumber { let e = env(); let eb = e.borrow(); eb.block_number } + pub fn block_number() -> BlockNumber { + with_env(|e| e.block_number) + } /// Get the block hash of a given block. - pub fn block_hash(_number: BlockNumber) -> Hash { unimplemented!() } + pub fn block_hash(_number: BlockNumber) -> Hash { + unimplemented!() + } pub fn execute_block(_block: &Block) -> Vec { // populate environment from header. - { - let e = env(); - e.borrow_mut().block_number = _block.header.number; - } + with_env(|e| e.block_number = _block.header.number); staking::pre_transactions(); @@ -174,7 +252,7 @@ mod environment { /// Set the new code. pub fn set_code(new: &[u8]) { - set_storage(b"\0code", new) + runtime_support::set_storage(b"\0code", new) } /// Set the light-client digest for the header. @@ -184,33 +262,24 @@ mod environment { } } -mod consensus { +pub mod consensus { use super::*; - fn value_vec(mut value: usize, initial: Vec) -> Vec { - let mut acc = initial; - while value > 0 { - acc.push(value as u8); - value /= 256; - } - acc + pub fn set_authority(index: u32, authority: AccountID) { + runtime_support::set_storage(&value_vec(index, b"\0authority".to_vec()), &authority[..]); } - fn set_authority(index: usize, authority: AccountID) { - set_storage(&value_vec(index, b"\0authority".to_vec()), &authority[..]); + fn authority(index: u32) -> AccountID { + runtime_support::storage_into(&value_vec(index, b"\0authority".to_vec())).unwrap() } - fn authority(index: usize) -> AccountID { - storage_into(&value_vec(index, b"\0authority".to_vec())).unwrap() - } - - fn set_authority_count(count: usize) { + pub fn set_authority_count(count: u32) { (count..authority_count()).for_each(|i| set_authority(i, SessionKey::default())); - set_storage(b"\0authority_count", &value_vec(count, Vec::new())); + runtime_support::set_storage(b"\0authority_count", &value_vec(count, Vec::new())); } - fn authority_count() -> usize { - storage(b"\0authority_count").into_iter().rev().fold(0, |acc, i| (acc << 8) + (i as usize)) + fn authority_count() -> u32 { + runtime_support::storage(b"\0authority_count").into_iter().rev().fold(0, |acc, i| (acc << 8) + (i as u32)) } /// Get the current set of authorities. These are the session keys. @@ -221,9 +290,9 @@ mod consensus { /// Set the current set of authorities' session keys. /// /// Called by `next_session` only. - fn set_authorities(authorities: &[AccountID]) { - set_authority_count(authorities.len()); - authorities.iter().enumerate().for_each(|(v, &i)| set_authority(v, i)); + pub fn set_authorities(authorities: &[AccountID]) { + set_authority_count(authorities.len() as u32); + authorities.iter().enumerate().for_each(|(v, &i)| set_authority(v as u32, i)); } /// Get the current set of validators. These are the long-term identifiers for the validators @@ -265,35 +334,56 @@ mod consensus { } } -mod staking { +pub mod staking { use super::*; /// The length of a staking era in blocks. - pub fn era_length() -> BlockNumber { sessions_per_era() * consensus::session_length() } + pub fn era_length() -> BlockNumber { + sessions_per_era() * consensus::session_length() + } /// The length of a staking era in sessions. - pub fn sessions_per_era() -> BlockNumber { 10 } + pub fn sessions_per_era() -> BlockNumber { + 10 + } /// The era has changed - enact new staking set. /// /// NOTE: This always happens on a session change. - fn next_era() { unimplemented!() } + pub fn next_era() { + unimplemented!() + } /// The balance of a given account. - fn balance(_who: AccountID) -> Balance { unimplemented!() } + pub fn balance(who: &AccountID) -> Balance { + storage_into(&who.to_keyed_vec(b"sta\0bal\0")) + } /// Transfer some unlocked staking balance to another staker. - pub fn transfer_stake(_transactor: AccountID, _dest: AccountID, _value: Balance) { unimplemented!() } + pub fn transfer_stake(transactor: &AccountID, dest: &AccountID, value: Balance) { + let from_key = transactor.to_keyed_vec(b"sta\0bal\0"); + let from_balance: Balance = storage_into(&from_key); + assert!(from_balance >= value); + let to_key = dest.to_keyed_vec(b"sta\0bal\0"); + let to_balance: Balance = storage_into(&to_key); + assert!(to_balance + value > to_balance); // no overflow + (from_balance - value).store(&from_key); + (to_balance + value).store(&to_key); + } /// Declare the desire to stake for the transactor. /// /// Effects will be felt at the beginning of the next era. - pub fn stake(_transactor: &AccountID) { unimplemented!() } + pub fn stake(_transactor: &AccountID) { + unimplemented!() + } /// Retract the desire to stake for the transactor. /// /// Effects will be felt at the beginning of the next era. - pub fn unstake(_transactor: &AccountID) { unimplemented!() } + pub fn unstake(_transactor: &AccountID) { + unimplemented!() + } /// Hook to be called prior to transaction processing. pub fn pre_transactions() { @@ -307,17 +397,92 @@ mod staking { } } -mod authentication { +pub mod authentication { use super::*; - fn validate_signature(_tx: Transaction) -> ( AccountID, TxOrder ) { unimplemented!() } - fn nonce(_id: AccountID) -> TxOrder { unimplemented!() } - fn authenticate(_tx: Transaction) -> AccountID { unimplemented!() } + pub fn validate_signature(_tx: Transaction) -> ( AccountID, TxOrder ) { + unimplemented!() + } + + pub fn nonce(_id: AccountID) -> TxOrder { + unimplemented!() + } + + pub fn authenticate(_tx: Transaction) -> AccountID { + unimplemented!() + } } -mod timestamp { +pub mod timestamp { use super::*; - fn timestamp() -> Timestamp { unimplemented!() } - fn set_timestamp(_now: Timestamp) { unimplemented!() } + pub fn timestamp() -> Timestamp { + unimplemented!() + } + + pub fn set_timestamp(_now: Timestamp) { + unimplemented!() + } +} + +#[cfg(test)] +mod tests { + + use super::*; + + use std::collections::HashMap; + use runtime_support::{NoError, with_externalities, Externalities}; + + #[derive(Debug, Default)] + struct TestExternalities { + storage: HashMap, Vec>, + } + impl Externalities for TestExternalities { + type Error = NoError; + + fn storage(&self, key: &[u8]) -> Result<&[u8], NoError> { + Ok(self.storage.get(&key.to_vec()).map_or(&[] as &[u8], Vec::as_slice)) + } + + fn set_storage(&mut self, key: Vec, value: Vec) { + self.storage.insert(key, value); + } + } + + macro_rules! map { + ($( $name:expr => $value:expr ),*) => ( + vec![ $( ( $name, $value ) ),* ].into_iter().collect() + ) + } + + #[test] + fn staking_balance_works() { + let one: AccountID = [1u8; 32]; + let two: AccountID = [2u8; 32]; + + let mut t = TestExternalities { storage: map![ + { let mut r = b"sta\0bal\0".to_vec(); r.extend_from_slice(&one); r } => vec![42u8, 0, 0, 0, 0, 0, 0, 0] + ], }; + + with_externalities(&mut t, || { + assert_eq!(staking::balance(&one), 42); + assert_eq!(staking::balance(&two), 0); + }); + } + + #[test] + fn staking_balance_transfer_works() { + let one: AccountID = [1u8; 32]; + let two: AccountID = [2u8; 32]; + + let mut t = TestExternalities { storage: map![ + { let mut r = b"sta\0bal\0".to_vec(); r.extend_from_slice(&one); r } => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + ], }; + + with_externalities(&mut t, || { + staking::transfer_stake(&one, &two, 69); + assert_eq!(staking::balance(&one), 42); + assert_eq!(staking::balance(&two), 69); + }); + } } From adbeecbdcf1746ad69b4fc27e4606432bd01b207 Mon Sep 17 00:00:00 2001 From: Gav Date: Sun, 14 Jan 2018 23:41:32 +0100 Subject: [PATCH 025/112] Rejig tests and ensure authorities are addressed consistently. --- substrate/state_machine/src/lib.rs | 42 ++++++++++------------ substrate/wasm-runtime/polkadot/src/lib.rs | 38 ++++++++++++-------- 2 files changed, 43 insertions(+), 37 deletions(-) diff --git a/substrate/state_machine/src/lib.rs b/substrate/state_machine/src/lib.rs index 58ba558322..38c481113f 100644 --- a/substrate/state_machine/src/lib.rs +++ b/substrate/state_machine/src/lib.rs @@ -114,13 +114,9 @@ impl OverlayedChanges { pub trait Error: 'static + fmt::Debug + fmt::Display + Send {} impl Error for E where E: 'static + fmt::Debug + fmt::Display + Send {} -fn value_vec(mut value: usize, initial: Vec) -> Vec { - let mut acc = initial; - while value > 0 { - acc.push(value as u8); - value /= 256; - } - acc +fn to_keyed_vec(value: u32, mut prepend: Vec) -> Vec { + prepend.extend((0..::std::mem::size_of::()).into_iter().map(|i| (value >> (i * 8)) as u8)); + prepend } /// Externalities: pinned to specific active address. @@ -134,12 +130,12 @@ pub trait Externalities { /// Set storage of current contract being called (effective immediately). fn set_storage(&mut self, key: Vec, value: Vec); - /// Get the current set of validators. - fn validators(&self) -> Result, Self::Error> { - (0..self.storage(b"\0validator_count")?.into_iter() + /// Get the current set of authorities. + fn authorities(&self) -> Result, Self::Error> { + (0..self.storage(b"con\0aut\0len")?.into_iter() .rev() - .fold(0, |acc, &i| (acc << 8) + (i as usize))) - .map(|i| self.storage(&value_vec(i, b"\0validator".to_vec()))) + .fold(0, |acc, &i| (acc << 8) + (i as u32))) + .map(|i| self.storage(&to_keyed_vec(i, b"con\0aut\0".to_vec()))) .collect() } } @@ -248,22 +244,22 @@ mod tests { } #[test] - fn validators_call_works() { + fn authorities_call_works() { let mut ext = TestExternalities::default(); - assert_eq!(ext.validators(), Ok(vec![])); + assert_eq!(ext.authorities(), Ok(vec![])); - ext.set_storage(b"\0validator_count".to_vec(), vec![]); - assert_eq!(ext.validators(), Ok(vec![])); + ext.set_storage(b"con\0aut\0len".to_vec(), vec![0u8; 4]); + assert_eq!(ext.authorities(), Ok(vec![])); - ext.set_storage(b"\0validator_count".to_vec(), vec![1]); - assert_eq!(ext.validators(), Ok(vec![&[][..]])); + ext.set_storage(b"con\0aut\0len".to_vec(), vec![1u8, 0, 0, 0]); + assert_eq!(ext.authorities(), Ok(vec![&[][..]])); - ext.set_storage(b"\0validator".to_vec(), b"first".to_vec()); - assert_eq!(ext.validators(), Ok(vec![&b"first"[..]])); + ext.set_storage(b"con\0aut\0\0\0\0\0".to_vec(), b"first".to_vec()); + assert_eq!(ext.authorities(), Ok(vec![&b"first"[..]])); - ext.set_storage(b"\0validator_count".to_vec(), vec![2]); - ext.set_storage(b"\0validator\x01".to_vec(), b"second".to_vec()); - assert_eq!(ext.validators(), Ok(vec![&b"first"[..], &b"second"[..]])); + ext.set_storage(b"con\0aut\0len".to_vec(), vec![2u8, 0, 0, 0]); + ext.set_storage(b"con\0aut\0\x01\0\0\0".to_vec(), b"second".to_vec()); + assert_eq!(ext.authorities(), Ok(vec![&b"first"[..], &b"second"[..]])); } } diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 205d2e31a7..b54eac0cdf 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -117,15 +117,6 @@ fn env() -> Rc> { } } -fn value_vec(mut value: u32, initial: Vec) -> Vec { - let mut acc = initial; - while value > 0 { - acc.push(value as u8); - value /= 256; - } - acc -} - trait EndianSensitive: Sized { fn to_le(self) -> Self { self } fn to_be(self) -> Self { self } @@ -176,10 +167,10 @@ fn storage_into(key: &[u8]) -> T { T::storage_into(key) } - trait KeyedVec { fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec; } + impl KeyedVec for AccountID { fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec { let mut r = prepend_key.to_vec(); @@ -188,6 +179,25 @@ impl KeyedVec for AccountID { } } +macro_rules! impl_endians { + ( $( $t:ty ),* ) => { $( + impl KeyedVec for $t { + fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec { + let size = size_of::(); + let value_bytes = self.to_le(); + let value_slice = unsafe { + std::slice::from_raw_parts(transmute::<*const Self, *const u8>(&value_bytes), size) + }; + let mut r = prepend_key.to_vec(); + r.extend_from_slice(value_slice); + r + } + } + )* } +} + +impl_endians!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize); + // TODO: include RLP implementation // TODO: add keccak256 (or some better hashing scheme) & ECDSA-recover (or some better sig scheme) @@ -266,20 +276,20 @@ pub mod consensus { use super::*; pub fn set_authority(index: u32, authority: AccountID) { - runtime_support::set_storage(&value_vec(index, b"\0authority".to_vec()), &authority[..]); + authority.store(&index.to_keyed_vec(b"con\0aut\0")); } fn authority(index: u32) -> AccountID { - runtime_support::storage_into(&value_vec(index, b"\0authority".to_vec())).unwrap() + storage_into(&index.to_keyed_vec(b"con\0aut\0")) } pub fn set_authority_count(count: u32) { (count..authority_count()).for_each(|i| set_authority(i, SessionKey::default())); - runtime_support::set_storage(b"\0authority_count", &value_vec(count, Vec::new())); + count.store(b"con\0aut\0len"); } fn authority_count() -> u32 { - runtime_support::storage(b"\0authority_count").into_iter().rev().fold(0, |acc, i| (acc << 8) + (i as u32)) + storage_into(b"con\0aut\0len") } /// Get the current set of authorities. These are the session keys. From 2e6300cad70333e0c705ff9d014ad796e23e0de8 Mon Sep 17 00:00:00 2001 From: Gav Date: Mon, 15 Jan 2018 00:01:25 +0100 Subject: [PATCH 026/112] Add marshaller for xfer function --- substrate/wasm-runtime/polkadot/src/lib.rs | 36 +++++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index b54eac0cdf..639cdcdbc4 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -22,6 +22,7 @@ pub type TxOrder = u64; pub enum Function { StakingStake, StakingUnstake, + StakingTransferStake, ConsensusSetSessionKey, } @@ -35,6 +36,11 @@ impl Function { Function::StakingUnstake => { staking::unstake(transactor); } + Function::StakingTransferStake => { + let dest = FromSlice::from_slice(¶ms[0..size_of::()]).unwrap(); + let value = FromSlice::from_slice(¶ms[size_of::()..size_of::() + 4]).unwrap(); + staking::transfer_stake(transactor, &dest, value); + } Function::ConsensusSetSessionKey => { let mut session = AccountID::default(); session.copy_from_slice(¶ms[0..size_of::()]); @@ -140,8 +146,8 @@ macro_rules! impl_non_endians { )* } } -impl_endians!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize); -impl_non_endians!([u8; 20], [u8; 32]); +impl_endians!(u16, u32, u64, usize, i16, i32, i64, isize); +impl_non_endians!(u8, i8, [u8; 20], [u8; 32]); trait Storage { fn storage_into(key: &[u8]) -> Self; @@ -150,7 +156,9 @@ trait Storage { impl Storage for T { fn storage_into(key: &[u8]) -> Self { - runtime_support::storage_into(key).map(EndianSensitive::from_le).unwrap_or_else(Default::default) + runtime_support::storage_into(key) + .map(EndianSensitive::from_le) + .unwrap_or_else(Default::default) } fn store(self, key: &[u8]) { @@ -167,6 +175,26 @@ fn storage_into(key: &[u8]) -> T { T::storage_into(key) } +trait FromSlice: Sized { + fn from_slice(value: &[u8]) -> Option; +} + +impl FromSlice for T { + fn from_slice(value: &[u8]) -> Option { + let size = size_of::(); + if value.len() == size { + unsafe { + let mut result: T = std::mem::uninitialized(); + std::slice::from_raw_parts_mut(transmute::<*mut T, *mut u8>(&mut result), size) + .copy_from_slice(&value); + Some(result.from_le()) + } + } else { + None + } + } +} + trait KeyedVec { fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec; } @@ -196,7 +224,7 @@ macro_rules! impl_endians { )* } } -impl_endians!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize); +impl_endians!(u16, u32, u64, usize, i16, i32, i64, isize); // TODO: include RLP implementation // TODO: add keccak256 (or some better hashing scheme) & ECDSA-recover (or some better sig scheme) From 209542581a723213a4d047a844b06ea37bf5729a Mon Sep 17 00:00:00 2001 From: Gav Date: Mon, 15 Jan 2018 11:59:54 +0100 Subject: [PATCH 027/112] Transaction dispatch test. --- substrate/native-runtime/support/src/lib.rs | 16 +- substrate/wasm-runtime/polkadot/src/lib.rs | 187 ++++++++++++++++---- 2 files changed, 163 insertions(+), 40 deletions(-) diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index 7bbd6d235e..38de2f29b6 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -25,12 +25,24 @@ pub struct ExternalitiesHolder<'a> { declare_generic!(ext : ExternalitiesHolder); -pub fn storage(_key: &[u8]) -> Vec { - ext::with(|holder| holder.ext.storage(_key).ok().map(|s| s.to_vec())) +pub fn storage(key: &[u8]) -> Vec { + ext::with(|holder| holder.ext.storage(key).ok().map(|s| s.to_vec())) .unwrap_or(None) .unwrap_or_else(|| vec![]) } +pub fn read_storage(key: &[u8], value_out: &mut [u8]) -> usize { + ext::with(|holder| { + if let Ok(value) = holder.ext.storage(key) { + let written = ::std::cmp::min(value.len(), value_out.len()); + value_out[0..written].copy_from_slice(&value[0..written]); + value.len() + } else { + 0 + } + }).unwrap_or(0) +} + pub fn storage_into(_key: &[u8]) -> Option { let size = size_of::(); diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 639cdcdbc4..fa22929a79 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -26,9 +26,81 @@ pub enum Function { ConsensusSetSessionKey, } +impl Function { + fn from_u8(value: u8) -> Option { + match value { + x if x == Function::StakingStake as u8 => Some(Function::StakingStake), + x if x == Function::StakingUnstake as u8 => Some(Function::StakingUnstake), + x if x == Function::StakingTransferStake as u8 => Some(Function::StakingTransferStake), + x if x == Function::ConsensusSetSessionKey as u8 => Some(Function::ConsensusSetSessionKey), + _ => None, + } + } +} + +struct StreamReader<'a> { + data: &'a[u8], + offset: usize, +} + +impl<'a> StreamReader<'a> { + fn new(data: &'a[u8]) -> Self { + StreamReader { + data: data, + offset: 0, + } + } + fn read(&mut self) -> Option { + let size = size_of::(); + let new_offset = self.offset + size; + let slice = &self.data[self.offset..new_offset]; + self.offset = new_offset; + Slicable::from_slice(slice) + } +} + +struct StreamWriter<'a> { + data: &'a mut[u8], + offset: usize, +} + +impl<'a> StreamWriter<'a> { + fn new(data: &'a mut[u8]) -> Self { + StreamWriter { + data: data, + offset: 0, + } + } + fn write(&mut self, value: &T) -> bool { + value.as_slice_then(|s| { + let new_offset = self.offset + s.len(); + if self.data.len() <= new_offset { + let slice = &self.data[self.offset..new_offset]; + self.offset = new_offset; + slice.copy_from_slice(s); + true + } else { + false + } + }) + } +} + +trait Joiner { + fn join(self, value: &T) -> Self; +} + +impl Joiner for Vec { + fn join(mut self, value: &T) -> Vec { + value.as_slice_then(|s| self.extend_from_slice(s)); + self + } +} + impl Function { /// Dispatch the function. - pub fn dispatch(&self, transactor: &AccountID, params: &[u8]) { + pub fn dispatch(&self, transactor: &AccountID, data: &[u8]) { + let mut params = StreamReader::new(data); match *self { Function::StakingStake => { staking::stake(transactor); @@ -37,14 +109,13 @@ impl Function { staking::unstake(transactor); } Function::StakingTransferStake => { - let dest = FromSlice::from_slice(¶ms[0..size_of::()]).unwrap(); - let value = FromSlice::from_slice(¶ms[size_of::()..size_of::() + 4]).unwrap(); + let dest = params.read().unwrap(); + let value = params.read().unwrap(); staking::transfer_stake(transactor, &dest, value); } Function::ConsensusSetSessionKey => { - let mut session = AccountID::default(); - session.copy_from_slice(¶ms[0..size_of::()]); - consensus::set_session_key(transactor, session); + let session = params.read().unwrap(); + consensus::set_session_key(transactor, &session); } } } @@ -128,6 +199,8 @@ trait EndianSensitive: Sized { fn to_be(self) -> Self { self } fn from_le(self) -> Self { self } fn from_be(self) -> Self { self } + fn as_be_then T>(&self, f: F) -> T { f(&self) } + fn as_le_then T>(&self, f: F) -> T { f(&self) } } macro_rules! impl_endians { @@ -137,6 +210,8 @@ macro_rules! impl_endians { fn to_be(self) -> Self { <$t>::to_be(self) } fn from_le(self) -> Self { <$t>::from_le(self) } fn from_be(self) -> Self { <$t>::from_be(self) } + fn as_be_then T>(&self, f: F) -> T { let d = self.to_be(); f(&d) } + fn as_le_then T>(&self, f: F) -> T { let d = self.to_le(); f(&d) } } )* } } @@ -151,23 +226,17 @@ impl_non_endians!(u8, i8, [u8; 20], [u8; 32]); trait Storage { fn storage_into(key: &[u8]) -> Self; - fn store(self, key: &[u8]); + fn store(&self, key: &[u8]); } -impl Storage for T { +impl Storage for T { fn storage_into(key: &[u8]) -> Self { - runtime_support::storage_into(key) - .map(EndianSensitive::from_le) + Slicable::set_as_slice(|out| runtime_support::read_storage(key, out) == out.len()) .unwrap_or_else(Default::default) } - fn store(self, key: &[u8]) { - let size = size_of::(); - let value_bytes = self.to_le(); - let value_slice = unsafe { - std::slice::from_raw_parts(transmute::<*const Self, *const u8>(&value_bytes), size) - }; - runtime_support::set_storage(key, value_slice); + fn store(&self, key: &[u8]) { + self.as_slice_then(|slice| runtime_support::set_storage(key, slice)); } } @@ -175,24 +244,47 @@ fn storage_into(key: &[u8]) -> T { T::storage_into(key) } -trait FromSlice: Sized { - fn from_slice(value: &[u8]) -> Option; +/// Trait that allows zero-copy read/write of value-references to/from slices in LE format. +trait Slicable: Sized { + fn from_slice(value: &[u8]) -> Option { + Self::set_as_slice(|out| if value.len() == out.len() { + out.copy_from_slice(&value); + true + } else { + false + }) + } + fn to_vec(&self) -> Vec { + self.as_slice_then(|s| s.to_vec()) + } + fn set_as_slice bool>(set_slice: F) -> Option; + fn as_slice_then R>(&self, f: F) -> R { + f(&self.to_vec()) + } } -impl FromSlice for T { - fn from_slice(value: &[u8]) -> Option { +impl Slicable for T { + fn set_as_slice bool>(fill_slice: F) -> Option { let size = size_of::(); - if value.len() == size { - unsafe { - let mut result: T = std::mem::uninitialized(); - std::slice::from_raw_parts_mut(transmute::<*mut T, *mut u8>(&mut result), size) - .copy_from_slice(&value); - Some(result.from_le()) - } + let mut result: T = unsafe { std::mem::uninitialized() }; + let result_slice = unsafe { + std::slice::from_raw_parts_mut(transmute::<*mut T, *mut u8>(&mut result), size) + }; + if fill_slice(result_slice) { + Some(result.from_le()) } else { None } } + fn as_slice_then R>(&self, f: F) -> R { + let size = size_of::(); + self.as_le_then(|le| { + let value_slice = unsafe { + std::slice::from_raw_parts(transmute::<*const Self, *const u8>(le), size) + }; + f(value_slice) + }) + } } trait KeyedVec { @@ -211,14 +303,11 @@ macro_rules! impl_endians { ( $( $t:ty ),* ) => { $( impl KeyedVec for $t { fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec { - let size = size_of::(); - let value_bytes = self.to_le(); - let value_slice = unsafe { - std::slice::from_raw_parts(transmute::<*const Self, *const u8>(&value_bytes), size) - }; - let mut r = prepend_key.to_vec(); - r.extend_from_slice(value_slice); - r + self.as_slice_then(|slice| { + let mut r = prepend_key.to_vec(); + r.extend_from_slice(slice); + r + }) } } )* } @@ -226,7 +315,6 @@ macro_rules! impl_endians { impl_endians!(u16, u32, u64, usize, i16, i32, i64, isize); -// TODO: include RLP implementation // TODO: add keccak256 (or some better hashing scheme) & ECDSA-recover (or some better sig scheme) pub fn execute_block(_input: Vec) -> Vec { @@ -353,7 +441,7 @@ pub mod consensus { /// Sets the session key of `_transactor` to `_session`. This doesn't take effect until the next /// session. - pub fn set_session_key(_transactor: &AccountID, _session: AccountID) { + pub fn set_session_key(_transactor: &AccountID, _session: &AccountID) { unimplemented!() } @@ -523,4 +611,27 @@ mod tests { assert_eq!(staking::balance(&two), 69); }); } + + #[test] + fn staking_balance_transfer_dispatch_works() { + let one: AccountID = [1u8; 32]; + let two: AccountID = [2u8; 32]; + + let mut t = TestExternalities { storage: map![ + { let mut r = b"sta\0bal\0".to_vec(); r.extend_from_slice(&one); r } => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + ], }; + + let tx = Transaction { + signed: one.clone(), + function: Function::StakingTransferStake, + input_data: vec![].join(&two).join(&69u64), + nonce: 0, + }; + + with_externalities(&mut t, || { + environment::execute_transaction(&tx); + assert_eq!(staking::balance(&one), 42); + assert_eq!(staking::balance(&two), 69); + }); + } } From 8869741166584a533330e6bfbb43d39bbbef731b Mon Sep 17 00:00:00 2001 From: Gav Date: Mon, 15 Jan 2018 12:01:05 +0100 Subject: [PATCH 028/112] Minor fix. --- substrate/wasm-runtime/polkadot/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index fa22929a79..02c35675e3 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -75,7 +75,7 @@ impl<'a> StreamWriter<'a> { value.as_slice_then(|s| { let new_offset = self.offset + s.len(); if self.data.len() <= new_offset { - let slice = &self.data[self.offset..new_offset]; + let slice = &mut self.data[self.offset..new_offset]; self.offset = new_offset; slice.copy_from_slice(s); true From 6d3cb828204c17a6b95753785f011e8fd98e670b Mon Sep 17 00:00:00 2001 From: Gav Date: Mon, 15 Jan 2018 18:30:04 +0100 Subject: [PATCH 029/112] Add test for ser/de transaction. --- substrate/wasm-runtime/polkadot/src/lib.rs | 93 ++++++++++++++++++++-- 1 file changed, 88 insertions(+), 5 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 02c35675e3..39cab5def1 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -19,6 +19,8 @@ pub type Timestamp = u64; pub type TxOrder = u64; /// The functions that a transaction can call (and be dispatched to). +#[cfg_attr(test, derive(PartialEq, Debug))] +#[derive(Clone, Copy)] pub enum Function { StakingStake, StakingUnstake, @@ -50,8 +52,8 @@ impl<'a> StreamReader<'a> { offset: 0, } } - fn read(&mut self) -> Option { - let size = size_of::(); + fn read(&mut self) -> Option { + let size = T::size_of(&self.data[self.offset..])?; let new_offset = self.offset + size; let slice = &self.data[self.offset..new_offset]; self.offset = new_offset; @@ -71,7 +73,7 @@ impl<'a> StreamWriter<'a> { offset: 0, } } - fn write(&mut self, value: &T) -> bool { + fn write(&mut self, value: &T) -> bool { value.as_slice_then(|s| { let new_offset = self.offset + s.len(); if self.data.len() <= new_offset { @@ -135,6 +137,7 @@ pub struct Header { pub digest: Digest, } +#[cfg_attr(test, derive(PartialEq, Debug))] pub struct Transaction { pub signed: AccountID, pub function: Function, @@ -261,6 +264,7 @@ trait Slicable: Sized { fn as_slice_then R>(&self, f: F) -> R { f(&self.to_vec()) } + fn size_of(_value: &[u8]) -> Option; } impl Slicable for T { @@ -285,6 +289,56 @@ impl Slicable for T { f(value_slice) }) } + fn size_of(_value: &[u8]) -> Option { + Some(size_of::()) + } +} + +impl Slicable for Vec { + fn from_slice(value: &[u8]) -> Option { + Some(value[4..].to_vec()) + } + fn set_as_slice bool>(_fill_slice: F) -> Option { + unimplemented!(); + } + fn to_vec(&self) -> Vec { + let mut r = vec![].join(&(self.len() as u32)); + r.extend_from_slice(&self); + r + } + fn size_of(data: &[u8]) -> Option { + u32::from_slice(&data[0..4]).map(|i| (i + 4) as usize) + } +} + +impl Slicable for Transaction { + fn from_slice(value: &[u8]) -> Option { + let mut reader = StreamReader::new(value); + Some(Transaction { + signed: reader.read()?, + function: Function::from_u8(reader.read()?)?, + nonce: reader.read()?, + input_data: reader.read()?, + }) + } + + fn set_as_slice bool>(_fill_slice: F) -> Option { + unimplemented!(); + } + + fn to_vec(&self) -> Vec { + vec![] + .join(&self.signed) + .join(&(self.function as u8)) + .join(&self.nonce) + .join(&self.input_data) + } + + fn size_of(data: &[u8]) -> Option { + let first_part = size_of::() + size_of::() + size_of::(); + let second_part = >::size_of(&data[first_part..])?; + Some(first_part + second_part) + } } trait KeyedVec { @@ -436,7 +490,7 @@ pub mod consensus { /// The number of blocks in each session. pub fn session_length() -> BlockNumber { - 10 + storage_into(b"con\0sel") } /// Sets the session key of `_transactor` to `_session`. This doesn't take effect until the next @@ -470,7 +524,7 @@ pub mod staking { /// The length of a staking era in sessions. pub fn sessions_per_era() -> BlockNumber { - 10 + storage_into(b"sta\0spe") } /// The era has changed - enact new staking set. @@ -634,4 +688,33 @@ mod tests { assert_eq!(staking::balance(&two), 69); }); } + + #[test] + fn serialise_transaction_works() { + let one: AccountID = [1u8; 32]; + let two: AccountID = [2u8; 32]; + let tx = Transaction { + signed: one.clone(), + function: Function::StakingTransferStake, + input_data: vec![].join(&two).join(&69u64), + nonce: 0, + }; + let serialised = tx.to_vec(); + assert_eq!(serialised, vec![1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 69, 0, 0, 0, 0, 0, 0, 0]); + } + + #[test] + fn deserialise_transaction_works() { + let one: AccountID = [1u8; 32]; + let two: AccountID = [2u8; 32]; + let tx = Transaction { + signed: one.clone(), + function: Function::StakingTransferStake, + input_data: vec![].join(&two).join(&69u64), + nonce: 0, + }; + let data = [1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 69, 0, 0, 0, 0, 0, 0, 0]; + let deserialised: Transaction = Slicable::from_slice(&data).unwrap(); + assert_eq!(deserialised, tx); + } } From 88f867e053869157cfdd5ed844b28503010469f2 Mon Sep 17 00:00:00 2001 From: Gav Date: Mon, 15 Jan 2018 23:03:38 +0100 Subject: [PATCH 030/112] Add ser/de for header. --- substrate/wasm-runtime/polkadot/src/lib.rs | 73 ++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 39cab5def1..120c5562cd 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -124,11 +124,13 @@ impl Function { } #[derive(Clone)] +#[cfg_attr(test, derive(PartialEq, Debug))] pub struct Digest { pub logs: Vec>, } #[derive(Clone)] +#[cfg_attr(test, derive(PartialEq, Debug))] pub struct Header { pub parent_hash: Hash, pub number: BlockNumber, @@ -145,6 +147,7 @@ pub struct Transaction { pub nonce: TxOrder, } +#[cfg_attr(test, derive(PartialEq, Debug))] pub struct Block { pub header: Header, pub transactions: Vec, @@ -267,6 +270,8 @@ trait Slicable: Sized { fn size_of(_value: &[u8]) -> Option; } +trait NonTrivialSlicable: Slicable {} + impl Slicable for T { fn set_as_slice bool>(fill_slice: F) -> Option { let size = size_of::(); @@ -341,6 +346,72 @@ impl Slicable for Transaction { } } +impl NonTrivialSlicable for Transaction {} + +impl NonTrivialSlicable for Vec where Vec: Slicable {} + +impl Slicable for Vec { + fn from_slice(value: &[u8]) -> Option { + let len = Self::size_of(&value[0..4])?; + let mut off = 4; + let mut r = vec![]; + while off < len { + let element_len = T::size_of(&value[off..])?; + r.push(T::from_slice(&value[off..off + element_len])?); + off += element_len; + } + Some(r) + } + + fn set_as_slice bool>(_fill_slice: F) -> Option { + unimplemented!(); + } + + fn to_vec(&self) -> Vec { + let vecs = self.iter().map(Slicable::to_vec).collect::>(); + let len = vecs.iter().fold(0, |mut a, v| {a += v.len(); a}); + let mut r = vec![].join(&(len as u32)); + vecs.iter().for_each(|v| r.extend_from_slice(v)); + r + } + + fn size_of(data: &[u8]) -> Option { + u32::from_slice(&data[0..4]).map(|i| (i + 4) as usize) + } +} + +impl Slicable for Header { + fn from_slice(value: &[u8]) -> Option { + let mut reader = StreamReader::new(value); + Some(Header { + parent_hash: reader.read()?, + number: reader.read()?, + state_root: reader.read()?, + transaction_root: reader.read()?, + digest: Digest { logs: reader.read()?, }, + }) + } + + fn set_as_slice bool>(_fill_slice: F) -> Option { + unimplemented!(); + } + + fn to_vec(&self) -> Vec { + vec![] + .join(&self.parent_hash) + .join(&self.number) + .join(&self.state_root) + .join(&self.transaction_root) + .join(&self.digest.logs) + } + + fn size_of(data: &[u8]) -> Option { + let first_part = size_of::() + size_of::() + size_of::() + size_of::(); + let second_part = >>::size_of(&data[first_part..])?; + Some(first_part + second_part) + } +} + trait KeyedVec { fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec; } @@ -717,4 +788,6 @@ mod tests { let deserialised: Transaction = Slicable::from_slice(&data).unwrap(); assert_eq!(deserialised, tx); } + + // TODO: Ser/de Header. } From 108b86a56dd8e20888d28eae247289fd3c99ca78 Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 16 Jan 2018 15:56:05 +0100 Subject: [PATCH 031/112] Add tests for header ser/de --- substrate/wasm-runtime/polkadot/src/lib.rs | 77 +++++++++++++++++++--- 1 file changed, 69 insertions(+), 8 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 120c5562cd..ea6030f1cb 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -60,7 +60,9 @@ impl<'a> StreamReader<'a> { Slicable::from_slice(slice) } } - +/* +// Not in use yet +// TODO: introduce fn size_will_be(&self) -> usize; to Slicable trait and implement struct StreamWriter<'a> { data: &'a mut[u8], offset: usize, @@ -87,7 +89,7 @@ impl<'a> StreamWriter<'a> { }) } } - +*/ trait Joiner { fn join(self, value: &T) -> Self; } @@ -768,10 +770,17 @@ mod tests { signed: one.clone(), function: Function::StakingTransferStake, input_data: vec![].join(&two).join(&69u64), - nonce: 0, + nonce: 69, }; let serialised = tx.to_vec(); - assert_eq!(serialised, vec![1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 69, 0, 0, 0, 0, 0, 0, 0]); + assert_eq!(serialised, vec![ + 1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, + 69, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 69, 0, 0, 0, 0, 0, 0, 0 + ]); } #[test] @@ -782,12 +791,64 @@ mod tests { signed: one.clone(), function: Function::StakingTransferStake, input_data: vec![].join(&two).join(&69u64), - nonce: 0, + nonce: 69, }; - let data = [1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 69, 0, 0, 0, 0, 0, 0, 0]; - let deserialised: Transaction = Slicable::from_slice(&data).unwrap(); + let data = [ + 1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, + 69, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 69, 0, 0, 0, 0, 0, 0, 0 + ]; + let deserialised = Transaction::from_slice(&data).unwrap(); assert_eq!(deserialised, tx); } - // TODO: Ser/de Header. + #[test] + fn serialise_header_works() { + let h = Header { + parent_hash: [4u8; 32], + number: 42, + state_root: [5u8; 32], + transaction_root: [6u8; 32], + digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, + }; + let serialised = h.to_vec(); + assert_eq!(serialised, vec![ + 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 42, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 26, 0, 0, 0, + 7, 0, 0, 0, + 111, 110, 101, 32, 108, 111, 103, + 11, 0, 0, 0, + 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103 + ]); + } + + #[test] + fn deserialise_header_works() { + let h = Header { + parent_hash: [4u8; 32], + number: 42, + state_root: [5u8; 32], + transaction_root: [6u8; 32], + digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, + }; + let data = [ + 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 42, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 26, 0, 0, 0, + 7, 0, 0, 0, + 111, 110, 101, 32, 108, 111, 103, + 11, 0, 0, 0, + 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103 + ]; + let deserialised = Header::from_slice(&data).unwrap(); + assert_eq!(deserialised, h); + } } From c382125de5e9fd7847ff4565a9ef1ac3247c40fb Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 16 Jan 2018 16:32:22 +0100 Subject: [PATCH 032/112] Introduce basic block decoding/execution framework. --- substrate/native-runtime/support/src/lib.rs | 2 +- substrate/wasm-runtime/polkadot/src/lib.rs | 189 ++++++++++++++++++-- substrate/wasm-runtime/support/src/lib.rs | 2 +- 3 files changed, 177 insertions(+), 16 deletions(-) diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index 38de2f29b6..c1805d2d22 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -6,7 +6,7 @@ pub use std::vec::Vec; pub use std::rc::Rc; pub use std::cell::RefCell; pub use std::boxed::Box; -pub use std::mem::{size_of, transmute}; +pub use std::mem::{size_of, transmute, swap}; pub use polkadot_state_machine::Externalities; use std::fmt; diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index ea6030f1cb..3b3530fcaa 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -3,8 +3,7 @@ #[macro_use] extern crate runtime_support; -use runtime_support::{Vec, size_of}; -use runtime_support::{Rc, RefCell, transmute, Box}; +use runtime_support::{Vec, size_of, Rc, RefCell, transmute, swap, Box}; /// The hash of an ECDSA pub key which is used to identify an external transactor. pub type AccountID = [u8; 32]; @@ -125,7 +124,7 @@ impl Function { } } -#[derive(Clone)] +#[derive(Clone, Default)] #[cfg_attr(test, derive(PartialEq, Debug))] pub struct Digest { pub logs: Vec>, @@ -176,6 +175,8 @@ impl Block { #[derive(Default)] struct Environment { block_number: BlockNumber, + digest: Digest, + next_log_index: usize, } fn with_env T>(f: F) -> T { @@ -414,6 +415,32 @@ impl Slicable for Header { } } +impl Slicable for Block { + fn from_slice(value: &[u8]) -> Option { + let mut reader = StreamReader::new(value); + Some(Block { + header: reader.read()?, + transactions: reader.read()?, + }) + } + + fn set_as_slice bool>(_fill_slice: F) -> Option { + unimplemented!(); + } + + fn to_vec(&self) -> Vec { + vec![] + .join(&self.header) + .join(&self.transactions) + } + + fn size_of(data: &[u8]) -> Option { + let first_part = Header::size_of(data)?; + let second_part = >::size_of(&data[first_part..])?; + Some(first_part + second_part) + } +} + trait KeyedVec { fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec; } @@ -444,14 +471,12 @@ impl_endians!(u16, u32, u64, usize, i16, i32, i64, isize); // TODO: add keccak256 (or some better hashing scheme) & ECDSA-recover (or some better sig scheme) -pub fn execute_block(_input: Vec) -> Vec { - let block = Block::from_rlp(&_input); - environment::execute_block(&block) +pub fn execute_block(input: Vec) -> Vec { + environment::execute_block(Block::from_slice(&input).unwrap()) } -pub fn execute_transaction(_input: Vec) -> Vec { - let tx = Transaction::from_rlp(&_input); - environment::execute_transaction(&tx) +pub fn execute_transaction(input: Vec) -> Vec { + environment::execute_transaction(&Transaction::from_slice(&input).unwrap()) } impl_stubs!(execute_block, execute_transaction); @@ -470,26 +495,49 @@ pub mod environment { with_env(|e| e.block_number) } - /// Get the block hash of a given block. + /// Get the block hash of a given block (uses storage). pub fn block_hash(_number: BlockNumber) -> Hash { unimplemented!() } - pub fn execute_block(_block: &Block) -> Vec { + /// Deposits a log and ensures it matches the blocks log data. + pub fn deposit_log(log: &[u8]) { + with_env(|e| { + assert_eq!(log, &e.digest.logs[e.next_log_index][..]); + e.next_log_index += 1; + }); + } + + pub fn execute_block(mut block: Block) -> Vec { // populate environment from header. - with_env(|e| e.block_number = _block.header.number); + with_env(|e| { + e.block_number = block.header.number; + swap(&mut e.digest, &mut block.header.digest); + e.next_log_index = 0; + }); + + // TODO: check transaction trie root represents the transactions. + // TODO: store the header in state. staking::pre_transactions(); - // TODO: go through each transaction and use execute_transaction to execute. + block.transactions.iter().for_each(|tx| { execute_transaction(tx); }); staking::post_transactions(); - // TODO: ensure digest in header is what we expect from transactions. + final_checks(&block); + + // TODO: check state root somehow Vec::new() } + fn final_checks(_block: &Block) { + with_env(|e| { + assert_eq!(e.next_log_index, e.digest.logs.len()); + }); + } + /// Execute a given transaction. pub fn execute_transaction(_tx: &Transaction) -> Vec { // TODO: decode data and ensure valid @@ -851,4 +899,117 @@ mod tests { let deserialised = Header::from_slice(&data).unwrap(); assert_eq!(deserialised, h); } + + #[test] + fn serialise_block_works() { + let one: AccountID = [1u8; 32]; + let two: AccountID = [2u8; 32]; + let tx1 = Transaction { + signed: one.clone(), + function: Function::StakingTransferStake, + input_data: vec![].join(&two).join(&69u64), + nonce: 69, + }; + let tx2 = Transaction { + signed: two.clone(), + function: Function::StakingStake, + input_data: vec![], + nonce: 42, + }; + let h = Header { + parent_hash: [4u8; 32], + number: 42, + state_root: [5u8; 32], + transaction_root: [6u8; 32], + digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, + }; + let b = Block { + header: h, + transactions: vec![tx1, tx2], + }; + let serialised = b.to_vec(); + assert_eq!(serialised, vec![ + // header + 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 42, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 26, 0, 0, 0, + 7, 0, 0, 0, + 111, 110, 101, 32, 108, 111, 103, + 11, 0, 0, 0, + 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103, + // transactions + 130, 0, 0, 0, + // tx1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, + 69, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 69, 0, 0, 0, 0, 0, 0, 0, + // tx2 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, + 42, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 + ]); + } + + #[test] + fn deserialise_block_works() { + let one: AccountID = [1u8; 32]; + let two: AccountID = [2u8; 32]; + let tx1 = Transaction { + signed: one.clone(), + function: Function::StakingTransferStake, + input_data: vec![].join(&two).join(&69u64), + nonce: 69, + }; + let tx2 = Transaction { + signed: two.clone(), + function: Function::StakingStake, + input_data: vec![], + nonce: 42, + }; + let h = Header { + parent_hash: [4u8; 32], + number: 42, + state_root: [5u8; 32], + transaction_root: [6u8; 32], + digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, + }; + let b = Block { + header: h, + transactions: vec![tx1, tx2], + }; + let data = [ + // header + 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 42, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 26, 0, 0, 0, + 7, 0, 0, 0, + 111, 110, 101, 32, 108, 111, 103, + 11, 0, 0, 0, + 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103, + // transactions + 130, 0, 0, 0, + // tx1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, + 69, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 69, 0, 0, 0, 0, 0, 0, 0, + // tx2 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, + 42, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 + ]; + let deserialised = Block::from_slice(&data).unwrap(); + assert_eq!(deserialised, b); + } } diff --git a/substrate/wasm-runtime/support/src/lib.rs b/substrate/wasm-runtime/support/src/lib.rs index 3acad5237e..9c64f1a72b 100644 --- a/substrate/wasm-runtime/support/src/lib.rs +++ b/substrate/wasm-runtime/support/src/lib.rs @@ -9,7 +9,7 @@ extern crate alloc; pub use alloc::vec::Vec; pub use alloc::boxed::Box; pub use alloc::rc::Rc; -pub use core::mem::{transmute, size_of, uninitialized}; +pub use core::mem::{transmute, size_of, uninitialized, swap}; pub use core::cell::{RefCell, Ref, RefMut}; extern crate pwasm_libc; From 571ad85cfe6b03c0a27a6215faf593454a59cdcc Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 16 Jan 2018 16:33:05 +0100 Subject: [PATCH 033/112] Introduce block decoding/execution framework (p2) --- substrate/wasm-runtime/polkadot/src/lib.rs | 28 ++++------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 3b3530fcaa..533a6ad927 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -517,7 +517,7 @@ pub mod environment { }); // TODO: check transaction trie root represents the transactions. - // TODO: store the header in state. + // TODO: store the header hash in storage. staking::pre_transactions(); @@ -542,6 +542,8 @@ pub mod environment { pub fn execute_transaction(_tx: &Transaction) -> Vec { // TODO: decode data and ensure valid // TODO: ensure signature valid and recover id (use authentication::authenticate) + // TODO: check nonce + // TODO: increment nonce in storage // TODO: ensure target_function valid // TODO: decode parameters @@ -555,12 +557,6 @@ pub mod environment { pub fn set_code(new: &[u8]) { runtime_support::set_storage(b"\0code", new) } - - /// Set the light-client digest for the header. - pub fn set_digest(_preserialised_rlp_digest: &[u8]) { - // TODO: Mention this to the external environment? - unimplemented!() - } } pub mod consensus { @@ -611,7 +607,7 @@ pub mod consensus { /// The number of blocks in each session. pub fn session_length() -> BlockNumber { - storage_into(b"con\0sel") + storage_into(b"con\0bps") } /// Sets the session key of `_transactor` to `_session`. This doesn't take effect until the next @@ -698,22 +694,6 @@ pub mod staking { } } -pub mod authentication { - use super::*; - - pub fn validate_signature(_tx: Transaction) -> ( AccountID, TxOrder ) { - unimplemented!() - } - - pub fn nonce(_id: AccountID) -> TxOrder { - unimplemented!() - } - - pub fn authenticate(_tx: Transaction) -> AccountID { - unimplemented!() - } -} - pub mod timestamp { use super::*; From caff772b838d6a80256d7c36648380da039c82be Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 16 Jan 2018 17:55:07 +0100 Subject: [PATCH 034/112] Big refactor. --- substrate/native-runtime/support/src/lib.rs | 3 +- .../wasm-runtime/polkadot/src/consensus.rs | 72 ++ .../polkadot/src/endiansensitive.rs | 29 + .../wasm-runtime/polkadot/src/environment.rs | 33 + .../wasm-runtime/polkadot/src/function.rs | 50 + .../wasm-runtime/polkadot/src/keyedvec.rs | 30 + substrate/wasm-runtime/polkadot/src/lib.rs | 994 +----------------- .../wasm-runtime/polkadot/src/primitives.rs | 378 +++++++ .../wasm-runtime/polkadot/src/slicable.rs | 69 ++ .../wasm-runtime/polkadot/src/staking.rs | 109 ++ .../wasm-runtime/polkadot/src/storage.rs | 23 + .../wasm-runtime/polkadot/src/streamreader.rs | 63 ++ substrate/wasm-runtime/polkadot/src/system.rs | 129 +++ .../wasm-runtime/polkadot/src/testing.rs | 19 + .../wasm-runtime/polkadot/src/timestamp.rs | 9 + 15 files changed, 1037 insertions(+), 973 deletions(-) create mode 100644 substrate/wasm-runtime/polkadot/src/consensus.rs create mode 100644 substrate/wasm-runtime/polkadot/src/endiansensitive.rs create mode 100644 substrate/wasm-runtime/polkadot/src/environment.rs create mode 100644 substrate/wasm-runtime/polkadot/src/function.rs create mode 100644 substrate/wasm-runtime/polkadot/src/keyedvec.rs create mode 100644 substrate/wasm-runtime/polkadot/src/primitives.rs create mode 100644 substrate/wasm-runtime/polkadot/src/slicable.rs create mode 100644 substrate/wasm-runtime/polkadot/src/staking.rs create mode 100644 substrate/wasm-runtime/polkadot/src/storage.rs create mode 100644 substrate/wasm-runtime/polkadot/src/streamreader.rs create mode 100644 substrate/wasm-runtime/polkadot/src/system.rs create mode 100644 substrate/wasm-runtime/polkadot/src/testing.rs create mode 100644 substrate/wasm-runtime/polkadot/src/timestamp.rs diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index c1805d2d22..795cae2ffd 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -6,7 +6,8 @@ pub use std::vec::Vec; pub use std::rc::Rc; pub use std::cell::RefCell; pub use std::boxed::Box; -pub use std::mem::{size_of, transmute, swap}; +pub use std::slice; +pub use std::mem::{size_of, transmute, swap, uninitialized}; pub use polkadot_state_machine::Externalities; use std::fmt; diff --git a/substrate/wasm-runtime/polkadot/src/consensus.rs b/substrate/wasm-runtime/polkadot/src/consensus.rs new file mode 100644 index 0000000000..ef4d5a9856 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/consensus.rs @@ -0,0 +1,72 @@ +use keyedvec::KeyedVec; +use storage::Storage; +use primitives::{AccountID, SessionKey, BlockNumber}; +use storage::storage_into; + +pub fn set_authority(index: u32, authority: AccountID) { + authority.store(&index.to_keyed_vec(b"con\0aut\0")); +} + +fn authority(index: u32) -> AccountID { + storage_into(&index.to_keyed_vec(b"con\0aut\0")) +} + +pub fn set_authority_count(count: u32) { + (count..authority_count()).for_each(|i| set_authority(i, SessionKey::default())); + count.store(b"con\0aut\0len"); +} + +fn authority_count() -> u32 { + storage_into(b"con\0aut\0len") +} + +/// Get the current set of authorities. These are the session keys. +pub fn authorities() -> Vec { + (0..authority_count()).into_iter().map(authority).collect() +} + +/// Set the current set of authorities' session keys. +/// +/// Called by `next_session` only. +pub fn set_authorities(authorities: &[AccountID]) { + set_authority_count(authorities.len() as u32); + authorities.iter().enumerate().for_each(|(v, &i)| set_authority(v as u32, i)); +} + +/// Get the current set of validators. These are the long-term identifiers for the validators +/// and will be mapped to a session key with the most recent `set_next_session_key`. +pub fn validators() -> Vec { + unimplemented!() +} + +/// Set the current set of validators. +/// +/// Called by staking::next_era() only. +pub fn set_validators(_new: &[AccountID]) { + unimplemented!() +} + +/// The number of blocks in each session. +pub fn session_length() -> BlockNumber { + storage_into(b"con\0bps") +} + +/// Sets the session key of `_transactor` to `_session`. This doesn't take effect until the next +/// session. +pub fn set_session_key(_transactor: &AccountID, _session: &AccountID) { + unimplemented!() +} + +/// Move onto next session: register the new authority set. +pub fn next_session() { + // TODO: Call set_authorities(). + unimplemented!() +} + +/// Hook to be called prior to transaction processing. +pub fn pre_transactions() {} + +/// Hook to be called after to transaction processing. +pub fn post_transactions() { + // TODO: check block number and call next_session if necessary. +} diff --git a/substrate/wasm-runtime/polkadot/src/endiansensitive.rs b/substrate/wasm-runtime/polkadot/src/endiansensitive.rs new file mode 100644 index 0000000000..c13a96f23d --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/endiansensitive.rs @@ -0,0 +1,29 @@ +pub trait EndianSensitive: Sized { + fn to_le(self) -> Self { self } + fn to_be(self) -> Self { self } + fn from_le(self) -> Self { self } + fn from_be(self) -> Self { self } + fn as_be_then T>(&self, f: F) -> T { f(&self) } + fn as_le_then T>(&self, f: F) -> T { f(&self) } +} + +macro_rules! impl_endians { + ( $( $t:ty ),* ) => { $( + impl EndianSensitive for $t { + fn to_le(self) -> Self { <$t>::to_le(self) } + fn to_be(self) -> Self { <$t>::to_be(self) } + fn from_le(self) -> Self { <$t>::from_le(self) } + fn from_be(self) -> Self { <$t>::from_be(self) } + fn as_be_then T>(&self, f: F) -> T { let d = self.to_be(); f(&d) } + fn as_le_then T>(&self, f: F) -> T { let d = self.to_le(); f(&d) } + } + )* } +} +macro_rules! impl_non_endians { + ( $( $t:ty ),* ) => { $( + impl EndianSensitive for $t {} + )* } +} + +impl_endians!(u16, u32, u64, usize, i16, i32, i64, isize); +impl_non_endians!(u8, i8, [u8; 20], [u8; 32]); diff --git a/substrate/wasm-runtime/polkadot/src/environment.rs b/substrate/wasm-runtime/polkadot/src/environment.rs new file mode 100644 index 0000000000..4d8ac354a8 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/environment.rs @@ -0,0 +1,33 @@ +use runtime_support::{Rc, RefCell, transmute, Box}; +use primitives::{BlockNumber, Digest}; + +#[derive(Default)] +pub struct Environment { + pub block_number: BlockNumber, + pub digest: Digest, + pub next_log_index: usize, +} + +pub fn with_env T>(f: F) -> T { + let e = env(); + let mut eb = e.borrow_mut(); + f(&mut *eb) +} + +pub fn env() -> Rc> { + // Initialize it to a null value + static mut SINGLETON: *const Rc> = 0 as *const Rc>; + + unsafe { + if SINGLETON == 0 as *const Rc> { + // Make it + let singleton: Rc> = Rc::new(RefCell::new(Default::default())); + + // Put it in the heap so it can outlive this call + SINGLETON = transmute(Box::new(singleton)); + } + + // Now we give out a copy of the data that is safe to use concurrently. + (*SINGLETON).clone() + } +} diff --git a/substrate/wasm-runtime/polkadot/src/function.rs b/substrate/wasm-runtime/polkadot/src/function.rs new file mode 100644 index 0000000000..3f6845bfe6 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/function.rs @@ -0,0 +1,50 @@ +use staking; +use consensus; +use primitives::AccountID; +use streamreader::StreamReader; + +/// The functions that a transaction can call (and be dispatched to). +#[cfg_attr(test, derive(PartialEq, Debug))] +#[derive(Clone, Copy)] +pub enum Function { + StakingStake, + StakingUnstake, + StakingTransferStake, + ConsensusSetSessionKey, +} + +impl Function { + pub fn from_u8(value: u8) -> Option { + match value { + x if x == Function::StakingStake as u8 => Some(Function::StakingStake), + x if x == Function::StakingUnstake as u8 => Some(Function::StakingUnstake), + x if x == Function::StakingTransferStake as u8 => Some(Function::StakingTransferStake), + x if x == Function::ConsensusSetSessionKey as u8 => Some(Function::ConsensusSetSessionKey), + _ => None, + } + } +} + +impl Function { + /// Dispatch the function. + pub fn dispatch(&self, transactor: &AccountID, data: &[u8]) { + let mut params = StreamReader::new(data); + match *self { + Function::StakingStake => { + staking::stake(transactor); + } + Function::StakingUnstake => { + staking::unstake(transactor); + } + Function::StakingTransferStake => { + let dest = params.read().unwrap(); + let value = params.read().unwrap(); + staking::transfer_stake(transactor, &dest, value); + } + Function::ConsensusSetSessionKey => { + let session = params.read().unwrap(); + consensus::set_session_key(transactor, &session); + } + } + } +} diff --git a/substrate/wasm-runtime/polkadot/src/keyedvec.rs b/substrate/wasm-runtime/polkadot/src/keyedvec.rs new file mode 100644 index 0000000000..3b0e595628 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/keyedvec.rs @@ -0,0 +1,30 @@ +use primitives::AccountID; +use slicable::Slicable; + +pub trait KeyedVec { + fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec; +} + +impl KeyedVec for AccountID { + fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec { + let mut r = prepend_key.to_vec(); + r.extend_from_slice(self); + r + } +} + +macro_rules! impl_endians { + ( $( $t:ty ),* ) => { $( + impl KeyedVec for $t { + fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec { + self.as_slice_then(|slice| { + let mut r = prepend_key.to_vec(); + r.extend_from_slice(slice); + r + }) + } + } + )* } +} + +impl_endians!(u16, u32, u64, usize, i16, i32, i64, isize); diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 533a6ad927..e64a3c2a6b 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -3,480 +3,37 @@ #[macro_use] extern crate runtime_support; -use runtime_support::{Vec, size_of, Rc, RefCell, transmute, swap, Box}; -/// The hash of an ECDSA pub key which is used to identify an external transactor. -pub type AccountID = [u8; 32]; -/// The ECDSA pub key of an authority. This is what the external environment/consensus algorithm -/// refers to as a "authority". -pub type SessionKey = AccountID; -pub type Balance = u64; -pub type ChainID = u64; -pub type Hash = [u8; 32]; -pub type BlockNumber = u64; -pub type Timestamp = u64; -pub type TxOrder = u64; +mod endiansensitive; +mod streamreader; +mod slicable; +mod primitives; +mod keyedvec; +mod function; +mod environment; +mod storage; +mod testing; +#[allow(unused)] +mod system; +#[allow(unused)] +mod consensus; +#[allow(unused)] +mod staking; +#[allow(unused)] +mod timestamp; -/// The functions that a transaction can call (and be dispatched to). -#[cfg_attr(test, derive(PartialEq, Debug))] -#[derive(Clone, Copy)] -pub enum Function { - StakingStake, - StakingUnstake, - StakingTransferStake, - ConsensusSetSessionKey, -} - -impl Function { - fn from_u8(value: u8) -> Option { - match value { - x if x == Function::StakingStake as u8 => Some(Function::StakingStake), - x if x == Function::StakingUnstake as u8 => Some(Function::StakingUnstake), - x if x == Function::StakingTransferStake as u8 => Some(Function::StakingTransferStake), - x if x == Function::ConsensusSetSessionKey as u8 => Some(Function::ConsensusSetSessionKey), - _ => None, - } - } -} - -struct StreamReader<'a> { - data: &'a[u8], - offset: usize, -} - -impl<'a> StreamReader<'a> { - fn new(data: &'a[u8]) -> Self { - StreamReader { - data: data, - offset: 0, - } - } - fn read(&mut self) -> Option { - let size = T::size_of(&self.data[self.offset..])?; - let new_offset = self.offset + size; - let slice = &self.data[self.offset..new_offset]; - self.offset = new_offset; - Slicable::from_slice(slice) - } -} -/* -// Not in use yet -// TODO: introduce fn size_will_be(&self) -> usize; to Slicable trait and implement -struct StreamWriter<'a> { - data: &'a mut[u8], - offset: usize, -} - -impl<'a> StreamWriter<'a> { - fn new(data: &'a mut[u8]) -> Self { - StreamWriter { - data: data, - offset: 0, - } - } - fn write(&mut self, value: &T) -> bool { - value.as_slice_then(|s| { - let new_offset = self.offset + s.len(); - if self.data.len() <= new_offset { - let slice = &mut self.data[self.offset..new_offset]; - self.offset = new_offset; - slice.copy_from_slice(s); - true - } else { - false - } - }) - } -} -*/ -trait Joiner { - fn join(self, value: &T) -> Self; -} - -impl Joiner for Vec { - fn join(mut self, value: &T) -> Vec { - value.as_slice_then(|s| self.extend_from_slice(s)); - self - } -} - -impl Function { - /// Dispatch the function. - pub fn dispatch(&self, transactor: &AccountID, data: &[u8]) { - let mut params = StreamReader::new(data); - match *self { - Function::StakingStake => { - staking::stake(transactor); - } - Function::StakingUnstake => { - staking::unstake(transactor); - } - Function::StakingTransferStake => { - let dest = params.read().unwrap(); - let value = params.read().unwrap(); - staking::transfer_stake(transactor, &dest, value); - } - Function::ConsensusSetSessionKey => { - let session = params.read().unwrap(); - consensus::set_session_key(transactor, &session); - } - } - } -} - -#[derive(Clone, Default)] -#[cfg_attr(test, derive(PartialEq, Debug))] -pub struct Digest { - pub logs: Vec>, -} - -#[derive(Clone)] -#[cfg_attr(test, derive(PartialEq, Debug))] -pub struct Header { - pub parent_hash: Hash, - pub number: BlockNumber, - pub state_root: Hash, - pub transaction_root: Hash, - pub digest: Digest, -} - -#[cfg_attr(test, derive(PartialEq, Debug))] -pub struct Transaction { - pub signed: AccountID, - pub function: Function, - pub input_data: Vec, - pub nonce: TxOrder, -} - -#[cfg_attr(test, derive(PartialEq, Debug))] -pub struct Block { - pub header: Header, - pub transactions: Vec, -} - -impl Header { - pub fn from_rlp(_rlp: &[u8]) -> Self { - unimplemented!() - } -} - -impl Transaction { - pub fn from_rlp(_rlp: &[u8]) -> Self { - unimplemented!() - } -} - -impl Block { - pub fn from_rlp(_rlp: &[u8]) -> Self { - unimplemented!() - } -} - -#[derive(Default)] -struct Environment { - block_number: BlockNumber, - digest: Digest, - next_log_index: usize, -} - -fn with_env T>(f: F) -> T { - let e = env(); - let mut eb = e.borrow_mut(); - f(&mut *eb) -} - -fn env() -> Rc> { - // Initialize it to a null value - static mut SINGLETON: *const Rc> = 0 as *const Rc>; - - unsafe { - if SINGLETON == 0 as *const Rc> { - // Make it - let singleton: Rc> = Rc::new(RefCell::new(Default::default())); - - // Put it in the heap so it can outlive this call - SINGLETON = transmute(Box::new(singleton)); - } - - // Now we give out a copy of the data that is safe to use concurrently. - (*SINGLETON).clone() - } -} - -trait EndianSensitive: Sized { - fn to_le(self) -> Self { self } - fn to_be(self) -> Self { self } - fn from_le(self) -> Self { self } - fn from_be(self) -> Self { self } - fn as_be_then T>(&self, f: F) -> T { f(&self) } - fn as_le_then T>(&self, f: F) -> T { f(&self) } -} - -macro_rules! impl_endians { - ( $( $t:ty ),* ) => { $( - impl EndianSensitive for $t { - fn to_le(self) -> Self { <$t>::to_le(self) } - fn to_be(self) -> Self { <$t>::to_be(self) } - fn from_le(self) -> Self { <$t>::from_le(self) } - fn from_be(self) -> Self { <$t>::from_be(self) } - fn as_be_then T>(&self, f: F) -> T { let d = self.to_be(); f(&d) } - fn as_le_then T>(&self, f: F) -> T { let d = self.to_le(); f(&d) } - } - )* } -} -macro_rules! impl_non_endians { - ( $( $t:ty ),* ) => { $( - impl EndianSensitive for $t {} - )* } -} - -impl_endians!(u16, u32, u64, usize, i16, i32, i64, isize); -impl_non_endians!(u8, i8, [u8; 20], [u8; 32]); - -trait Storage { - fn storage_into(key: &[u8]) -> Self; - fn store(&self, key: &[u8]); -} - -impl Storage for T { - fn storage_into(key: &[u8]) -> Self { - Slicable::set_as_slice(|out| runtime_support::read_storage(key, out) == out.len()) - .unwrap_or_else(Default::default) - } - - fn store(&self, key: &[u8]) { - self.as_slice_then(|slice| runtime_support::set_storage(key, slice)); - } -} - -fn storage_into(key: &[u8]) -> T { - T::storage_into(key) -} - -/// Trait that allows zero-copy read/write of value-references to/from slices in LE format. -trait Slicable: Sized { - fn from_slice(value: &[u8]) -> Option { - Self::set_as_slice(|out| if value.len() == out.len() { - out.copy_from_slice(&value); - true - } else { - false - }) - } - fn to_vec(&self) -> Vec { - self.as_slice_then(|s| s.to_vec()) - } - fn set_as_slice bool>(set_slice: F) -> Option; - fn as_slice_then R>(&self, f: F) -> R { - f(&self.to_vec()) - } - fn size_of(_value: &[u8]) -> Option; -} - -trait NonTrivialSlicable: Slicable {} - -impl Slicable for T { - fn set_as_slice bool>(fill_slice: F) -> Option { - let size = size_of::(); - let mut result: T = unsafe { std::mem::uninitialized() }; - let result_slice = unsafe { - std::slice::from_raw_parts_mut(transmute::<*mut T, *mut u8>(&mut result), size) - }; - if fill_slice(result_slice) { - Some(result.from_le()) - } else { - None - } - } - fn as_slice_then R>(&self, f: F) -> R { - let size = size_of::(); - self.as_le_then(|le| { - let value_slice = unsafe { - std::slice::from_raw_parts(transmute::<*const Self, *const u8>(le), size) - }; - f(value_slice) - }) - } - fn size_of(_value: &[u8]) -> Option { - Some(size_of::()) - } -} - -impl Slicable for Vec { - fn from_slice(value: &[u8]) -> Option { - Some(value[4..].to_vec()) - } - fn set_as_slice bool>(_fill_slice: F) -> Option { - unimplemented!(); - } - fn to_vec(&self) -> Vec { - let mut r = vec![].join(&(self.len() as u32)); - r.extend_from_slice(&self); - r - } - fn size_of(data: &[u8]) -> Option { - u32::from_slice(&data[0..4]).map(|i| (i + 4) as usize) - } -} - -impl Slicable for Transaction { - fn from_slice(value: &[u8]) -> Option { - let mut reader = StreamReader::new(value); - Some(Transaction { - signed: reader.read()?, - function: Function::from_u8(reader.read()?)?, - nonce: reader.read()?, - input_data: reader.read()?, - }) - } - - fn set_as_slice bool>(_fill_slice: F) -> Option { - unimplemented!(); - } - - fn to_vec(&self) -> Vec { - vec![] - .join(&self.signed) - .join(&(self.function as u8)) - .join(&self.nonce) - .join(&self.input_data) - } - - fn size_of(data: &[u8]) -> Option { - let first_part = size_of::() + size_of::() + size_of::(); - let second_part = >::size_of(&data[first_part..])?; - Some(first_part + second_part) - } -} - -impl NonTrivialSlicable for Transaction {} - -impl NonTrivialSlicable for Vec where Vec: Slicable {} - -impl Slicable for Vec { - fn from_slice(value: &[u8]) -> Option { - let len = Self::size_of(&value[0..4])?; - let mut off = 4; - let mut r = vec![]; - while off < len { - let element_len = T::size_of(&value[off..])?; - r.push(T::from_slice(&value[off..off + element_len])?); - off += element_len; - } - Some(r) - } - - fn set_as_slice bool>(_fill_slice: F) -> Option { - unimplemented!(); - } - - fn to_vec(&self) -> Vec { - let vecs = self.iter().map(Slicable::to_vec).collect::>(); - let len = vecs.iter().fold(0, |mut a, v| {a += v.len(); a}); - let mut r = vec![].join(&(len as u32)); - vecs.iter().for_each(|v| r.extend_from_slice(v)); - r - } - - fn size_of(data: &[u8]) -> Option { - u32::from_slice(&data[0..4]).map(|i| (i + 4) as usize) - } -} - -impl Slicable for Header { - fn from_slice(value: &[u8]) -> Option { - let mut reader = StreamReader::new(value); - Some(Header { - parent_hash: reader.read()?, - number: reader.read()?, - state_root: reader.read()?, - transaction_root: reader.read()?, - digest: Digest { logs: reader.read()?, }, - }) - } - - fn set_as_slice bool>(_fill_slice: F) -> Option { - unimplemented!(); - } - - fn to_vec(&self) -> Vec { - vec![] - .join(&self.parent_hash) - .join(&self.number) - .join(&self.state_root) - .join(&self.transaction_root) - .join(&self.digest.logs) - } - - fn size_of(data: &[u8]) -> Option { - let first_part = size_of::() + size_of::() + size_of::() + size_of::(); - let second_part = >>::size_of(&data[first_part..])?; - Some(first_part + second_part) - } -} - -impl Slicable for Block { - fn from_slice(value: &[u8]) -> Option { - let mut reader = StreamReader::new(value); - Some(Block { - header: reader.read()?, - transactions: reader.read()?, - }) - } - - fn set_as_slice bool>(_fill_slice: F) -> Option { - unimplemented!(); - } - - fn to_vec(&self) -> Vec { - vec![] - .join(&self.header) - .join(&self.transactions) - } - - fn size_of(data: &[u8]) -> Option { - let first_part = Header::size_of(data)?; - let second_part = >::size_of(&data[first_part..])?; - Some(first_part + second_part) - } -} - -trait KeyedVec { - fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec; -} - -impl KeyedVec for AccountID { - fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec { - let mut r = prepend_key.to_vec(); - r.extend_from_slice(self); - r - } -} - -macro_rules! impl_endians { - ( $( $t:ty ),* ) => { $( - impl KeyedVec for $t { - fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec { - self.as_slice_then(|slice| { - let mut r = prepend_key.to_vec(); - r.extend_from_slice(slice); - r - }) - } - } - )* } -} - -impl_endians!(u16, u32, u64, usize, i16, i32, i64, isize); +use runtime_support::Vec; +use slicable::Slicable; +use primitives::{ChainID, Block, Transaction}; // TODO: add keccak256 (or some better hashing scheme) & ECDSA-recover (or some better sig scheme) pub fn execute_block(input: Vec) -> Vec { - environment::execute_block(Block::from_slice(&input).unwrap()) + system::execute_block(Block::from_slice(&input).unwrap()) } pub fn execute_transaction(input: Vec) -> Vec { - environment::execute_transaction(&Transaction::from_slice(&input).unwrap()) + system::execute_transaction(&Transaction::from_slice(&input).unwrap()) } impl_stubs!(execute_block, execute_transaction); @@ -486,510 +43,3 @@ pub fn chain_id() -> ChainID { // TODO: retrieve from external unimplemented!() } - -pub mod environment { - use super::*; - - /// The current block number being processed. Set by `execute_block`. - pub fn block_number() -> BlockNumber { - with_env(|e| e.block_number) - } - - /// Get the block hash of a given block (uses storage). - pub fn block_hash(_number: BlockNumber) -> Hash { - unimplemented!() - } - - /// Deposits a log and ensures it matches the blocks log data. - pub fn deposit_log(log: &[u8]) { - with_env(|e| { - assert_eq!(log, &e.digest.logs[e.next_log_index][..]); - e.next_log_index += 1; - }); - } - - pub fn execute_block(mut block: Block) -> Vec { - // populate environment from header. - with_env(|e| { - e.block_number = block.header.number; - swap(&mut e.digest, &mut block.header.digest); - e.next_log_index = 0; - }); - - // TODO: check transaction trie root represents the transactions. - // TODO: store the header hash in storage. - - staking::pre_transactions(); - - block.transactions.iter().for_each(|tx| { execute_transaction(tx); }); - - staking::post_transactions(); - - final_checks(&block); - - // TODO: check state root somehow - - Vec::new() - } - - fn final_checks(_block: &Block) { - with_env(|e| { - assert_eq!(e.next_log_index, e.digest.logs.len()); - }); - } - - /// Execute a given transaction. - pub fn execute_transaction(_tx: &Transaction) -> Vec { - // TODO: decode data and ensure valid - // TODO: ensure signature valid and recover id (use authentication::authenticate) - // TODO: check nonce - // TODO: increment nonce in storage - // TODO: ensure target_function valid - // TODO: decode parameters - - _tx.function.dispatch(&_tx.signed, &_tx.input_data); - - // TODO: encode any return - Vec::new() - } - - /// Set the new code. - pub fn set_code(new: &[u8]) { - runtime_support::set_storage(b"\0code", new) - } -} - -pub mod consensus { - use super::*; - - pub fn set_authority(index: u32, authority: AccountID) { - authority.store(&index.to_keyed_vec(b"con\0aut\0")); - } - - fn authority(index: u32) -> AccountID { - storage_into(&index.to_keyed_vec(b"con\0aut\0")) - } - - pub fn set_authority_count(count: u32) { - (count..authority_count()).for_each(|i| set_authority(i, SessionKey::default())); - count.store(b"con\0aut\0len"); - } - - fn authority_count() -> u32 { - storage_into(b"con\0aut\0len") - } - - /// Get the current set of authorities. These are the session keys. - pub fn authorities() -> Vec { - (0..authority_count()).into_iter().map(authority).collect() - } - - /// Set the current set of authorities' session keys. - /// - /// Called by `next_session` only. - pub fn set_authorities(authorities: &[AccountID]) { - set_authority_count(authorities.len() as u32); - authorities.iter().enumerate().for_each(|(v, &i)| set_authority(v as u32, i)); - } - - /// Get the current set of validators. These are the long-term identifiers for the validators - /// and will be mapped to a session key with the most recent `set_next_session_key`. - pub fn validators() -> Vec { - unimplemented!() - } - - /// Set the current set of validators. - /// - /// Called by staking::next_era() only. - pub fn set_validators(_new: &[AccountID]) { - unimplemented!() - } - - /// The number of blocks in each session. - pub fn session_length() -> BlockNumber { - storage_into(b"con\0bps") - } - - /// Sets the session key of `_transactor` to `_session`. This doesn't take effect until the next - /// session. - pub fn set_session_key(_transactor: &AccountID, _session: &AccountID) { - unimplemented!() - } - - /// Move onto next session: register the new authority set. - pub fn next_session() { - // TODO: Call set_authorities(). - unimplemented!() - } - - /// Hook to be called prior to transaction processing. - pub fn pre_transactions() {} - - /// Hook to be called after to transaction processing. - pub fn post_transactions() { - // TODO: check block number and call next_session if necessary. - } -} - -pub mod staking { - use super::*; - - /// The length of a staking era in blocks. - pub fn era_length() -> BlockNumber { - sessions_per_era() * consensus::session_length() - } - - /// The length of a staking era in sessions. - pub fn sessions_per_era() -> BlockNumber { - storage_into(b"sta\0spe") - } - - /// The era has changed - enact new staking set. - /// - /// NOTE: This always happens on a session change. - pub fn next_era() { - unimplemented!() - } - - /// The balance of a given account. - pub fn balance(who: &AccountID) -> Balance { - storage_into(&who.to_keyed_vec(b"sta\0bal\0")) - } - - /// Transfer some unlocked staking balance to another staker. - pub fn transfer_stake(transactor: &AccountID, dest: &AccountID, value: Balance) { - let from_key = transactor.to_keyed_vec(b"sta\0bal\0"); - let from_balance: Balance = storage_into(&from_key); - assert!(from_balance >= value); - let to_key = dest.to_keyed_vec(b"sta\0bal\0"); - let to_balance: Balance = storage_into(&to_key); - assert!(to_balance + value > to_balance); // no overflow - (from_balance - value).store(&from_key); - (to_balance + value).store(&to_key); - } - - /// Declare the desire to stake for the transactor. - /// - /// Effects will be felt at the beginning of the next era. - pub fn stake(_transactor: &AccountID) { - unimplemented!() - } - - /// Retract the desire to stake for the transactor. - /// - /// Effects will be felt at the beginning of the next era. - pub fn unstake(_transactor: &AccountID) { - unimplemented!() - } - - /// Hook to be called prior to transaction processing. - pub fn pre_transactions() { - consensus::pre_transactions(); - } - - /// Hook to be called after to transaction processing. - pub fn post_transactions() { - // TODO: check block number and call next_era if necessary. - consensus::post_transactions(); - } -} - -pub mod timestamp { - use super::*; - - pub fn timestamp() -> Timestamp { - unimplemented!() - } - - pub fn set_timestamp(_now: Timestamp) { - unimplemented!() - } -} - -#[cfg(test)] -mod tests { - - use super::*; - - use std::collections::HashMap; - use runtime_support::{NoError, with_externalities, Externalities}; - - #[derive(Debug, Default)] - struct TestExternalities { - storage: HashMap, Vec>, - } - impl Externalities for TestExternalities { - type Error = NoError; - - fn storage(&self, key: &[u8]) -> Result<&[u8], NoError> { - Ok(self.storage.get(&key.to_vec()).map_or(&[] as &[u8], Vec::as_slice)) - } - - fn set_storage(&mut self, key: Vec, value: Vec) { - self.storage.insert(key, value); - } - } - - macro_rules! map { - ($( $name:expr => $value:expr ),*) => ( - vec![ $( ( $name, $value ) ),* ].into_iter().collect() - ) - } - - #[test] - fn staking_balance_works() { - let one: AccountID = [1u8; 32]; - let two: AccountID = [2u8; 32]; - - let mut t = TestExternalities { storage: map![ - { let mut r = b"sta\0bal\0".to_vec(); r.extend_from_slice(&one); r } => vec![42u8, 0, 0, 0, 0, 0, 0, 0] - ], }; - - with_externalities(&mut t, || { - assert_eq!(staking::balance(&one), 42); - assert_eq!(staking::balance(&two), 0); - }); - } - - #[test] - fn staking_balance_transfer_works() { - let one: AccountID = [1u8; 32]; - let two: AccountID = [2u8; 32]; - - let mut t = TestExternalities { storage: map![ - { let mut r = b"sta\0bal\0".to_vec(); r.extend_from_slice(&one); r } => vec![111u8, 0, 0, 0, 0, 0, 0, 0] - ], }; - - with_externalities(&mut t, || { - staking::transfer_stake(&one, &two, 69); - assert_eq!(staking::balance(&one), 42); - assert_eq!(staking::balance(&two), 69); - }); - } - - #[test] - fn staking_balance_transfer_dispatch_works() { - let one: AccountID = [1u8; 32]; - let two: AccountID = [2u8; 32]; - - let mut t = TestExternalities { storage: map![ - { let mut r = b"sta\0bal\0".to_vec(); r.extend_from_slice(&one); r } => vec![111u8, 0, 0, 0, 0, 0, 0, 0] - ], }; - - let tx = Transaction { - signed: one.clone(), - function: Function::StakingTransferStake, - input_data: vec![].join(&two).join(&69u64), - nonce: 0, - }; - - with_externalities(&mut t, || { - environment::execute_transaction(&tx); - assert_eq!(staking::balance(&one), 42); - assert_eq!(staking::balance(&two), 69); - }); - } - - #[test] - fn serialise_transaction_works() { - let one: AccountID = [1u8; 32]; - let two: AccountID = [2u8; 32]; - let tx = Transaction { - signed: one.clone(), - function: Function::StakingTransferStake, - input_data: vec![].join(&two).join(&69u64), - nonce: 69, - }; - let serialised = tx.to_vec(); - assert_eq!(serialised, vec![ - 1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, - 69, 0, 0, 0, 0, 0, 0, 0, - 40, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 69, 0, 0, 0, 0, 0, 0, 0 - ]); - } - - #[test] - fn deserialise_transaction_works() { - let one: AccountID = [1u8; 32]; - let two: AccountID = [2u8; 32]; - let tx = Transaction { - signed: one.clone(), - function: Function::StakingTransferStake, - input_data: vec![].join(&two).join(&69u64), - nonce: 69, - }; - let data = [ - 1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, - 69, 0, 0, 0, 0, 0, 0, 0, - 40, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 69, 0, 0, 0, 0, 0, 0, 0 - ]; - let deserialised = Transaction::from_slice(&data).unwrap(); - assert_eq!(deserialised, tx); - } - - #[test] - fn serialise_header_works() { - let h = Header { - parent_hash: [4u8; 32], - number: 42, - state_root: [5u8; 32], - transaction_root: [6u8; 32], - digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, - }; - let serialised = h.to_vec(); - assert_eq!(serialised, vec![ - 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 42, 0, 0, 0, 0, 0, 0, 0, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 26, 0, 0, 0, - 7, 0, 0, 0, - 111, 110, 101, 32, 108, 111, 103, - 11, 0, 0, 0, - 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103 - ]); - } - - #[test] - fn deserialise_header_works() { - let h = Header { - parent_hash: [4u8; 32], - number: 42, - state_root: [5u8; 32], - transaction_root: [6u8; 32], - digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, - }; - let data = [ - 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 42, 0, 0, 0, 0, 0, 0, 0, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 26, 0, 0, 0, - 7, 0, 0, 0, - 111, 110, 101, 32, 108, 111, 103, - 11, 0, 0, 0, - 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103 - ]; - let deserialised = Header::from_slice(&data).unwrap(); - assert_eq!(deserialised, h); - } - - #[test] - fn serialise_block_works() { - let one: AccountID = [1u8; 32]; - let two: AccountID = [2u8; 32]; - let tx1 = Transaction { - signed: one.clone(), - function: Function::StakingTransferStake, - input_data: vec![].join(&two).join(&69u64), - nonce: 69, - }; - let tx2 = Transaction { - signed: two.clone(), - function: Function::StakingStake, - input_data: vec![], - nonce: 42, - }; - let h = Header { - parent_hash: [4u8; 32], - number: 42, - state_root: [5u8; 32], - transaction_root: [6u8; 32], - digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, - }; - let b = Block { - header: h, - transactions: vec![tx1, tx2], - }; - let serialised = b.to_vec(); - assert_eq!(serialised, vec![ - // header - 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 42, 0, 0, 0, 0, 0, 0, 0, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 26, 0, 0, 0, - 7, 0, 0, 0, - 111, 110, 101, 32, 108, 111, 103, - 11, 0, 0, 0, - 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103, - // transactions - 130, 0, 0, 0, - // tx1 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, - 69, 0, 0, 0, 0, 0, 0, 0, - 40, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 69, 0, 0, 0, 0, 0, 0, 0, - // tx2 - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 0, - 42, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0 - ]); - } - - #[test] - fn deserialise_block_works() { - let one: AccountID = [1u8; 32]; - let two: AccountID = [2u8; 32]; - let tx1 = Transaction { - signed: one.clone(), - function: Function::StakingTransferStake, - input_data: vec![].join(&two).join(&69u64), - nonce: 69, - }; - let tx2 = Transaction { - signed: two.clone(), - function: Function::StakingStake, - input_data: vec![], - nonce: 42, - }; - let h = Header { - parent_hash: [4u8; 32], - number: 42, - state_root: [5u8; 32], - transaction_root: [6u8; 32], - digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, - }; - let b = Block { - header: h, - transactions: vec![tx1, tx2], - }; - let data = [ - // header - 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 42, 0, 0, 0, 0, 0, 0, 0, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 26, 0, 0, 0, - 7, 0, 0, 0, - 111, 110, 101, 32, 108, 111, 103, - 11, 0, 0, 0, - 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103, - // transactions - 130, 0, 0, 0, - // tx1 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, - 69, 0, 0, 0, 0, 0, 0, 0, - 40, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 69, 0, 0, 0, 0, 0, 0, 0, - // tx2 - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 0, - 42, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0 - ]; - let deserialised = Block::from_slice(&data).unwrap(); - assert_eq!(deserialised, b); - } -} diff --git a/substrate/wasm-runtime/polkadot/src/primitives.rs b/substrate/wasm-runtime/polkadot/src/primitives.rs new file mode 100644 index 0000000000..a689eb7dce --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/primitives.rs @@ -0,0 +1,378 @@ +use streamreader::{StreamReader, Joiner}; +use slicable::{Slicable, NonTrivialSlicable}; +use function::Function; +use runtime_support::size_of; + +/// The hash of an ECDSA pub key which is used to identify an external transactor. +pub type AccountID = [u8; 32]; +/// The ECDSA pub key of an authority. This is what the external environment/consensus algorithm +/// refers to as a "authority". +pub type SessionKey = AccountID; +pub type Balance = u64; +pub type ChainID = u64; +pub type Hash = [u8; 32]; +pub type BlockNumber = u64; +pub type Timestamp = u64; +pub type TxOrder = u64; + +#[derive(Clone, Default)] +#[cfg_attr(test, derive(PartialEq, Debug))] +pub struct Digest { + pub logs: Vec>, +} + +#[derive(Clone)] +#[cfg_attr(test, derive(PartialEq, Debug))] +pub struct Header { + pub parent_hash: Hash, + pub number: BlockNumber, + pub state_root: Hash, + pub transaction_root: Hash, + pub digest: Digest, +} + +#[cfg_attr(test, derive(PartialEq, Debug))] +pub struct Transaction { + pub signed: AccountID, + pub function: Function, + pub input_data: Vec, + pub nonce: TxOrder, +} + +#[cfg_attr(test, derive(PartialEq, Debug))] +pub struct Block { + pub header: Header, + pub transactions: Vec, +} + +impl Slicable for Transaction { + fn from_slice(value: &[u8]) -> Option { + let mut reader = StreamReader::new(value); + Some(Transaction { + signed: reader.read()?, + function: Function::from_u8(reader.read()?)?, + nonce: reader.read()?, + input_data: reader.read()?, + }) + } + + fn set_as_slice bool>(_fill_slice: F) -> Option { + unimplemented!(); + } + + fn to_vec(&self) -> Vec { + vec![] + .join(&self.signed) + .join(&(self.function as u8)) + .join(&self.nonce) + .join(&self.input_data) + } + + fn size_of(data: &[u8]) -> Option { + let first_part = size_of::() + size_of::() + size_of::(); + let second_part = >::size_of(&data[first_part..])?; + Some(first_part + second_part) + } +} + +impl NonTrivialSlicable for Transaction {} + +impl NonTrivialSlicable for Vec where Vec: Slicable {} + +impl Slicable for Vec { + fn from_slice(value: &[u8]) -> Option { + let len = Self::size_of(&value[0..4])?; + let mut off = 4; + let mut r = vec![]; + while off < len { + let element_len = T::size_of(&value[off..])?; + r.push(T::from_slice(&value[off..off + element_len])?); + off += element_len; + } + Some(r) + } + + fn set_as_slice bool>(_fill_slice: F) -> Option { + unimplemented!(); + } + + fn to_vec(&self) -> Vec { + let vecs = self.iter().map(Slicable::to_vec).collect::>(); + let len = vecs.iter().fold(0, |mut a, v| {a += v.len(); a}); + let mut r = vec![].join(&(len as u32)); + vecs.iter().for_each(|v| r.extend_from_slice(v)); + r + } + + fn size_of(data: &[u8]) -> Option { + u32::from_slice(&data[0..4]).map(|i| (i + 4) as usize) + } +} + +impl Slicable for Header { + fn from_slice(value: &[u8]) -> Option { + let mut reader = StreamReader::new(value); + Some(Header { + parent_hash: reader.read()?, + number: reader.read()?, + state_root: reader.read()?, + transaction_root: reader.read()?, + digest: Digest { logs: reader.read()?, }, + }) + } + + fn set_as_slice bool>(_fill_slice: F) -> Option { + unimplemented!(); + } + + fn to_vec(&self) -> Vec { + vec![] + .join(&self.parent_hash) + .join(&self.number) + .join(&self.state_root) + .join(&self.transaction_root) + .join(&self.digest.logs) + } + + fn size_of(data: &[u8]) -> Option { + let first_part = size_of::() + size_of::() + size_of::() + size_of::(); + let second_part = >>::size_of(&data[first_part..])?; + Some(first_part + second_part) + } +} + +impl Slicable for Block { + fn from_slice(value: &[u8]) -> Option { + let mut reader = StreamReader::new(value); + Some(Block { + header: reader.read()?, + transactions: reader.read()?, + }) + } + + fn set_as_slice bool>(_fill_slice: F) -> Option { + unimplemented!(); + } + + fn to_vec(&self) -> Vec { + vec![] + .join(&self.header) + .join(&self.transactions) + } + + fn size_of(data: &[u8]) -> Option { + let first_part = Header::size_of(data)?; + let second_part = >::size_of(&data[first_part..])?; + Some(first_part + second_part) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use streamreader::Joiner; + use function::Function; + + #[test] + fn serialise_transaction_works() { + let one: AccountID = [1u8; 32]; + let two: AccountID = [2u8; 32]; + let tx = Transaction { + signed: one.clone(), + function: Function::StakingTransferStake, + input_data: vec![].join(&two).join(&69u64), + nonce: 69, + }; + let serialised = tx.to_vec(); + assert_eq!(serialised, vec![ + 1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, + 69, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 69, 0, 0, 0, 0, 0, 0, 0 + ]); + } + + #[test] + fn deserialise_transaction_works() { + let one: AccountID = [1u8; 32]; + let two: AccountID = [2u8; 32]; + let tx = Transaction { + signed: one.clone(), + function: Function::StakingTransferStake, + input_data: vec![].join(&two).join(&69u64), + nonce: 69, + }; + let data = [ + 1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, + 69, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 69, 0, 0, 0, 0, 0, 0, 0 + ]; + let deserialised = Transaction::from_slice(&data).unwrap(); + assert_eq!(deserialised, tx); + } + + #[test] + fn serialise_header_works() { + let h = Header { + parent_hash: [4u8; 32], + number: 42, + state_root: [5u8; 32], + transaction_root: [6u8; 32], + digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, + }; + let serialised = h.to_vec(); + assert_eq!(serialised, vec![ + 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 42, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 26, 0, 0, 0, + 7, 0, 0, 0, + 111, 110, 101, 32, 108, 111, 103, + 11, 0, 0, 0, + 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103 + ]); + } + + #[test] + fn deserialise_header_works() { + let h = Header { + parent_hash: [4u8; 32], + number: 42, + state_root: [5u8; 32], + transaction_root: [6u8; 32], + digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, + }; + let data = [ + 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 42, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 26, 0, 0, 0, + 7, 0, 0, 0, + 111, 110, 101, 32, 108, 111, 103, + 11, 0, 0, 0, + 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103 + ]; + let deserialised = Header::from_slice(&data).unwrap(); + assert_eq!(deserialised, h); + } + + #[test] + fn serialise_block_works() { + let one: AccountID = [1u8; 32]; + let two: AccountID = [2u8; 32]; + let tx1 = Transaction { + signed: one.clone(), + function: Function::StakingTransferStake, + input_data: vec![].join(&two).join(&69u64), + nonce: 69, + }; + let tx2 = Transaction { + signed: two.clone(), + function: Function::StakingStake, + input_data: vec![], + nonce: 42, + }; + let h = Header { + parent_hash: [4u8; 32], + number: 42, + state_root: [5u8; 32], + transaction_root: [6u8; 32], + digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, + }; + let b = Block { + header: h, + transactions: vec![tx1, tx2], + }; + let serialised = b.to_vec(); + assert_eq!(serialised, vec![ + // header + 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 42, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 26, 0, 0, 0, + 7, 0, 0, 0, + 111, 110, 101, 32, 108, 111, 103, + 11, 0, 0, 0, + 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103, + // transactions + 130, 0, 0, 0, + // tx1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, + 69, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 69, 0, 0, 0, 0, 0, 0, 0, + // tx2 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, + 42, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 + ]); + } + + #[test] + fn deserialise_block_works() { + let one: AccountID = [1u8; 32]; + let two: AccountID = [2u8; 32]; + let tx1 = Transaction { + signed: one.clone(), + function: Function::StakingTransferStake, + input_data: vec![].join(&two).join(&69u64), + nonce: 69, + }; + let tx2 = Transaction { + signed: two.clone(), + function: Function::StakingStake, + input_data: vec![], + nonce: 42, + }; + let h = Header { + parent_hash: [4u8; 32], + number: 42, + state_root: [5u8; 32], + transaction_root: [6u8; 32], + digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, + }; + let b = Block { + header: h, + transactions: vec![tx1, tx2], + }; + let data = [ + // header + 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 42, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 26, 0, 0, 0, + 7, 0, 0, 0, + 111, 110, 101, 32, 108, 111, 103, + 11, 0, 0, 0, + 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103, + // transactions + 130, 0, 0, 0, + // tx1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, + 69, 0, 0, 0, 0, 0, 0, 0, + 40, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 69, 0, 0, 0, 0, 0, 0, 0, + // tx2 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, + 42, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 + ]; + let deserialised = Block::from_slice(&data).unwrap(); + assert_eq!(deserialised, b); + } +} diff --git a/substrate/wasm-runtime/polkadot/src/slicable.rs b/substrate/wasm-runtime/polkadot/src/slicable.rs new file mode 100644 index 0000000000..0459881f0e --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/slicable.rs @@ -0,0 +1,69 @@ +use runtime_support::{Vec, size_of, transmute, uninitialized, slice}; +use streamreader::Joiner; +use endiansensitive::EndianSensitive; + +/// Trait that allows zero-copy read/write of value-references to/from slices in LE format. +pub trait Slicable: Sized { + fn from_slice(value: &[u8]) -> Option { + Self::set_as_slice(|out| if value.len() == out.len() { + out.copy_from_slice(&value); + true + } else { + false + }) + } + fn to_vec(&self) -> Vec { + self.as_slice_then(|s| s.to_vec()) + } + fn set_as_slice bool>(set_slice: F) -> Option; + fn as_slice_then R>(&self, f: F) -> R { + f(&self.to_vec()) + } + fn size_of(_value: &[u8]) -> Option; +} + +pub trait NonTrivialSlicable: Slicable {} + +impl Slicable for T { + fn set_as_slice bool>(fill_slice: F) -> Option { + let size = size_of::(); + let mut result: T = unsafe { uninitialized() }; + let result_slice = unsafe { + slice::from_raw_parts_mut(transmute::<*mut T, *mut u8>(&mut result), size) + }; + if fill_slice(result_slice) { + Some(result.from_le()) + } else { + None + } + } + fn as_slice_then R>(&self, f: F) -> R { + let size = size_of::(); + self.as_le_then(|le| { + let value_slice = unsafe { + slice::from_raw_parts(transmute::<*const Self, *const u8>(le), size) + }; + f(value_slice) + }) + } + fn size_of(_value: &[u8]) -> Option { + Some(size_of::()) + } +} + +impl Slicable for Vec { + fn from_slice(value: &[u8]) -> Option { + Some(value[4..].to_vec()) + } + fn set_as_slice bool>(_fill_slice: F) -> Option { + unimplemented!(); + } + fn to_vec(&self) -> Vec { + let mut r: Vec = vec![].join(&(self.len() as u32)); + r.extend_from_slice(&self); + r + } + fn size_of(data: &[u8]) -> Option { + u32::from_slice(&data[0..4]).map(|i| (i + 4) as usize) + } +} diff --git a/substrate/wasm-runtime/polkadot/src/staking.rs b/substrate/wasm-runtime/polkadot/src/staking.rs new file mode 100644 index 0000000000..d8903504d2 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/staking.rs @@ -0,0 +1,109 @@ +use keyedvec::KeyedVec; +use storage::{Storage, storage_into}; +use primitives::{BlockNumber, Balance, AccountID}; +use consensus; + +/// The length of a staking era in blocks. +pub fn era_length() -> BlockNumber { + sessions_per_era() * consensus::session_length() +} + +/// The length of a staking era in sessions. +pub fn sessions_per_era() -> BlockNumber { + storage_into(b"sta\0spe") +} + +/// The era has changed - enact new staking set. +/// +/// NOTE: This always happens on a session change. +pub fn next_era() { + unimplemented!() +} + +/// The balance of a given account. +pub fn balance(who: &AccountID) -> Balance { + storage_into(&who.to_keyed_vec(b"sta\0bal\0")) +} + +/// Transfer some unlocked staking balance to another staker. +pub fn transfer_stake(transactor: &AccountID, dest: &AccountID, value: Balance) { + let from_key = transactor.to_keyed_vec(b"sta\0bal\0"); + let from_balance: Balance = storage_into(&from_key); + assert!(from_balance >= value); + let to_key = dest.to_keyed_vec(b"sta\0bal\0"); + let to_balance: Balance = storage_into(&to_key); + assert!(to_balance + value > to_balance); // no overflow + (from_balance - value).store(&from_key); + (to_balance + value).store(&to_key); +} + +/// Declare the desire to stake for the transactor. +/// +/// Effects will be felt at the beginning of the next era. +pub fn stake(_transactor: &AccountID) { + unimplemented!() +} + +/// Retract the desire to stake for the transactor. +/// +/// Effects will be felt at the beginning of the next era. +pub fn unstake(_transactor: &AccountID) { + unimplemented!() +} + +/// Hook to be called prior to transaction processing. +pub fn pre_transactions() { + consensus::pre_transactions(); +} + +/// Hook to be called after to transaction processing. +pub fn post_transactions() { + // TODO: check block number and call next_era if necessary. + consensus::post_transactions(); +} + + +#[cfg(test)] +mod tests { + use runtime_support::with_externalities; + use testing::TestExternalities; + use primitives::{AccountID}; + use staking; + + macro_rules! map { + ($( $name:expr => $value:expr ),*) => ( + vec![ $( ( $name, $value ) ),* ].into_iter().collect() + ) + } + + #[test] + fn staking_balance_works() { + let one: AccountID = [1u8; 32]; + let two: AccountID = [2u8; 32]; + + let mut t = TestExternalities { storage: map![ + { let mut r = b"sta\0bal\0".to_vec(); r.extend_from_slice(&one); r } => vec![42u8, 0, 0, 0, 0, 0, 0, 0] + ], }; + + with_externalities(&mut t, || { + assert_eq!(staking::balance(&one), 42); + assert_eq!(staking::balance(&two), 0); + }); + } + + #[test] + fn staking_balance_transfer_works() { + let one: AccountID = [1u8; 32]; + let two: AccountID = [2u8; 32]; + + let mut t = TestExternalities { storage: map![ + { let mut r = b"sta\0bal\0".to_vec(); r.extend_from_slice(&one); r } => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + ], }; + + with_externalities(&mut t, || { + staking::transfer_stake(&one, &two, 69); + assert_eq!(staking::balance(&one), 42); + assert_eq!(staking::balance(&two), 69); + }); + } +} diff --git a/substrate/wasm-runtime/polkadot/src/storage.rs b/substrate/wasm-runtime/polkadot/src/storage.rs new file mode 100644 index 0000000000..13a9074d95 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/storage.rs @@ -0,0 +1,23 @@ +use slicable::Slicable; +use endiansensitive::EndianSensitive; +use runtime_support; + +pub trait Storage { + fn storage_into(key: &[u8]) -> Self; + fn store(&self, key: &[u8]); +} + +impl Storage for T { + fn storage_into(key: &[u8]) -> Self { + Slicable::set_as_slice(|out| runtime_support::read_storage(key, out) == out.len()) + .unwrap_or_else(Default::default) + } + + fn store(&self, key: &[u8]) { + self.as_slice_then(|slice| runtime_support::set_storage(key, slice)); + } +} + +pub fn storage_into(key: &[u8]) -> T { + T::storage_into(key) +} diff --git a/substrate/wasm-runtime/polkadot/src/streamreader.rs b/substrate/wasm-runtime/polkadot/src/streamreader.rs new file mode 100644 index 0000000000..3bb427a1ef --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/streamreader.rs @@ -0,0 +1,63 @@ +use slicable::Slicable; + +pub struct StreamReader<'a> { + data: &'a[u8], + offset: usize, +} + +impl<'a> StreamReader<'a> { + pub fn new(data: &'a[u8]) -> Self { + StreamReader { + data: data, + offset: 0, + } + } + pub fn read(&mut self) -> Option { + let size = T::size_of(&self.data[self.offset..])?; + let new_offset = self.offset + size; + let slice = &self.data[self.offset..new_offset]; + self.offset = new_offset; + Slicable::from_slice(slice) + } +} + +pub trait Joiner { + fn join(self, value: &T) -> Self; +} + +impl Joiner for Vec { + fn join(mut self, value: &T) -> Vec { + value.as_slice_then(|s| self.extend_from_slice(s)); + self + } +} +/* +// Not in use yet +// TODO: introduce fn size_will_be(&self) -> usize; to Slicable trait and implement +struct StreamWriter<'a> { + data: &'a mut[u8], + offset: usize, +} + +impl<'a> StreamWriter<'a> { + pub fn new(data: &'a mut[u8]) -> Self { + StreamWriter { + data: data, + offset: 0, + } + } + pub fn write(&mut self, value: &T) -> bool { + value.as_slice_then(|s| { + let new_offset = self.offset + s.len(); + if self.data.len() <= new_offset { + let slice = &mut self.data[self.offset..new_offset]; + self.offset = new_offset; + slice.copy_from_slice(s); + true + } else { + false + } + }) + } +} +*/ diff --git a/substrate/wasm-runtime/polkadot/src/system.rs b/substrate/wasm-runtime/polkadot/src/system.rs new file mode 100644 index 0000000000..96169d09cc --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/system.rs @@ -0,0 +1,129 @@ +use primitives::{Block, BlockNumber, Hash, Transaction}; +use runtime_support::{Vec, swap}; +use environment::with_env; +use staking; +use runtime_support; + +/// The current block number being processed. Set by `execute_block`. +pub fn block_number() -> BlockNumber { + with_env(|e| e.block_number) +} + +/// Get the block hash of a given block (uses storage). +pub fn block_hash(_number: BlockNumber) -> Hash { + unimplemented!() +} + +/// Deposits a log and ensures it matches the blocks log data. +pub fn deposit_log(log: &[u8]) { + with_env(|e| { + assert_eq!(log, &e.digest.logs[e.next_log_index][..]); + e.next_log_index += 1; + }); +} + +pub fn execute_block(mut block: Block) -> Vec { + // populate environment from header. + with_env(|e| { + e.block_number = block.header.number; + swap(&mut e.digest, &mut block.header.digest); + e.next_log_index = 0; + }); + + // TODO: check transaction trie root represents the transactions. + // TODO: store the header hash in storage. + + staking::pre_transactions(); + + block.transactions.iter().for_each(|tx| { execute_transaction(tx); }); + + staking::post_transactions(); + + final_checks(&block); + + // TODO: check state root somehow + + Vec::new() +} + +fn final_checks(_block: &Block) { + with_env(|e| { + assert_eq!(e.next_log_index, e.digest.logs.len()); + }); +} + +/// Execute a given transaction. +pub fn execute_transaction(_tx: &Transaction) -> Vec { + // TODO: decode data and ensure valid + // TODO: ensure signature valid and recover id (use authentication::authenticate) + // TODO: check nonce + // TODO: increment nonce in storage + // TODO: ensure target_function valid + // TODO: decode parameters + + _tx.function.dispatch(&_tx.signed, &_tx.input_data); + + // TODO: encode any return + Vec::new() +} + +/// Set the new code. +pub fn set_code(new: &[u8]) { + runtime_support::set_storage(b"\0code", new) +} + +#[cfg(test)] +mod tests { + use streamreader::Joiner; + use function::Function; + use std::collections::HashMap; + use runtime_support::{NoError, with_externalities, Externalities}; + use primitives::{AccountID, Transaction}; + use system; + use staking; + + #[derive(Debug, Default)] + struct TestExternalities { + storage: HashMap, Vec>, + } + impl Externalities for TestExternalities { + type Error = NoError; + + fn storage(&self, key: &[u8]) -> Result<&[u8], NoError> { + Ok(self.storage.get(&key.to_vec()).map_or(&[] as &[u8], Vec::as_slice)) + } + + fn set_storage(&mut self, key: Vec, value: Vec) { + self.storage.insert(key, value); + } + } + + macro_rules! map { + ($( $name:expr => $value:expr ),*) => ( + vec![ $( ( $name, $value ) ),* ].into_iter().collect() + ) + } + + #[test] + fn staking_balance_transfer_dispatch_works() { + let one: AccountID = [1u8; 32]; + let two: AccountID = [2u8; 32]; + + let mut t = TestExternalities { storage: map![ + { let mut r = b"sta\0bal\0".to_vec(); r.extend_from_slice(&one); r } => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + ], }; + + let tx = Transaction { + signed: one.clone(), + function: Function::StakingTransferStake, + input_data: vec![].join(&two).join(&69u64), + nonce: 0, + }; + + with_externalities(&mut t, || { + system::execute_transaction(&tx); + assert_eq!(staking::balance(&one), 42); + assert_eq!(staking::balance(&two), 69); + }); + } +} diff --git a/substrate/wasm-runtime/polkadot/src/testing.rs b/substrate/wasm-runtime/polkadot/src/testing.rs new file mode 100644 index 0000000000..d73917eb16 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/testing.rs @@ -0,0 +1,19 @@ +use runtime_support::{NoError, Externalities}; +use std::collections::HashMap; + +#[derive(Debug, Default)] +pub struct TestExternalities { + pub storage: HashMap, Vec>, +} + +impl Externalities for TestExternalities { + type Error = NoError; + + fn storage(&self, key: &[u8]) -> Result<&[u8], NoError> { + Ok(self.storage.get(&key.to_vec()).map_or(&[] as &[u8], Vec::as_slice)) + } + + fn set_storage(&mut self, key: Vec, value: Vec) { + self.storage.insert(key, value); + } +} diff --git a/substrate/wasm-runtime/polkadot/src/timestamp.rs b/substrate/wasm-runtime/polkadot/src/timestamp.rs new file mode 100644 index 0000000000..6a4043651d --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/timestamp.rs @@ -0,0 +1,9 @@ +use primitives::Timestamp; + +pub fn timestamp() -> Timestamp { + unimplemented!() +} + +pub fn set_timestamp(_now: Timestamp) { + unimplemented!() +} From e410a3a665a2b0bc17f7bd50b1a80f92b450273f Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 16 Jan 2018 17:57:42 +0100 Subject: [PATCH 035/112] Split out joiner. --- substrate/wasm-runtime/polkadot/src/joiner.rs | 12 ++++++++++++ substrate/wasm-runtime/polkadot/src/lib.rs | 1 + substrate/wasm-runtime/polkadot/src/primitives.rs | 5 +++-- substrate/wasm-runtime/polkadot/src/slicable.rs | 2 +- substrate/wasm-runtime/polkadot/src/streamreader.rs | 11 ----------- substrate/wasm-runtime/polkadot/src/system.rs | 2 +- 6 files changed, 18 insertions(+), 15 deletions(-) create mode 100644 substrate/wasm-runtime/polkadot/src/joiner.rs diff --git a/substrate/wasm-runtime/polkadot/src/joiner.rs b/substrate/wasm-runtime/polkadot/src/joiner.rs new file mode 100644 index 0000000000..99b38dec57 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/joiner.rs @@ -0,0 +1,12 @@ +use slicable::Slicable; + +pub trait Joiner { + fn join(self, value: &T) -> Self; +} + +impl Joiner for Vec { + fn join(mut self, value: &T) -> Vec { + value.as_slice_then(|s| self.extend_from_slice(s)); + self + } +} diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index e64a3c2a6b..5646c7c322 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -6,6 +6,7 @@ extern crate runtime_support; mod endiansensitive; mod streamreader; +mod joiner; mod slicable; mod primitives; mod keyedvec; diff --git a/substrate/wasm-runtime/polkadot/src/primitives.rs b/substrate/wasm-runtime/polkadot/src/primitives.rs index a689eb7dce..44d3bc4739 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives.rs @@ -1,4 +1,5 @@ -use streamreader::{StreamReader, Joiner}; +use streamreader::StreamReader; +use joiner::Joiner; use slicable::{Slicable, NonTrivialSlicable}; use function::Function; use runtime_support::size_of; @@ -170,7 +171,7 @@ impl Slicable for Block { #[cfg(test)] mod tests { use super::*; - use streamreader::Joiner; + use joiner::Joiner; use function::Function; #[test] diff --git a/substrate/wasm-runtime/polkadot/src/slicable.rs b/substrate/wasm-runtime/polkadot/src/slicable.rs index 0459881f0e..e220eb0f7d 100644 --- a/substrate/wasm-runtime/polkadot/src/slicable.rs +++ b/substrate/wasm-runtime/polkadot/src/slicable.rs @@ -1,5 +1,5 @@ use runtime_support::{Vec, size_of, transmute, uninitialized, slice}; -use streamreader::Joiner; +use joiner::Joiner; use endiansensitive::EndianSensitive; /// Trait that allows zero-copy read/write of value-references to/from slices in LE format. diff --git a/substrate/wasm-runtime/polkadot/src/streamreader.rs b/substrate/wasm-runtime/polkadot/src/streamreader.rs index 3bb427a1ef..33d6fd8bfd 100644 --- a/substrate/wasm-runtime/polkadot/src/streamreader.rs +++ b/substrate/wasm-runtime/polkadot/src/streamreader.rs @@ -20,17 +20,6 @@ impl<'a> StreamReader<'a> { Slicable::from_slice(slice) } } - -pub trait Joiner { - fn join(self, value: &T) -> Self; -} - -impl Joiner for Vec { - fn join(mut self, value: &T) -> Vec { - value.as_slice_then(|s| self.extend_from_slice(s)); - self - } -} /* // Not in use yet // TODO: introduce fn size_will_be(&self) -> usize; to Slicable trait and implement diff --git a/substrate/wasm-runtime/polkadot/src/system.rs b/substrate/wasm-runtime/polkadot/src/system.rs index 96169d09cc..88414fa9a1 100644 --- a/substrate/wasm-runtime/polkadot/src/system.rs +++ b/substrate/wasm-runtime/polkadot/src/system.rs @@ -74,7 +74,7 @@ pub fn set_code(new: &[u8]) { #[cfg(test)] mod tests { - use streamreader::Joiner; + use joiner::Joiner; use function::Function; use std::collections::HashMap; use runtime_support::{NoError, with_externalities, Externalities}; From b62a8f958761cfca25c10d0d5a0990b17f5efe54 Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 16 Jan 2018 18:03:13 +0100 Subject: [PATCH 036/112] Hide away support modules. --- substrate/wasm-runtime/polkadot/src/lib.rs | 14 ++++---------- .../polkadot/src/{ => support}/endiansensitive.rs | 0 .../polkadot/src/{ => support}/environment.rs | 0 .../polkadot/src/{ => support}/function.rs | 0 .../polkadot/src/{ => support}/joiner.rs | 0 .../polkadot/src/{ => support}/keyedvec.rs | 0 substrate/wasm-runtime/polkadot/src/support/mod.rs | 10 ++++++++++ .../polkadot/src/{ => support}/primitives.rs | 0 .../polkadot/src/{ => support}/slicable.rs | 0 .../polkadot/src/{ => support}/storage.rs | 0 .../polkadot/src/{ => support}/streamreader.rs | 0 .../polkadot/src/{ => support}/testing.rs | 0 12 files changed, 14 insertions(+), 10 deletions(-) rename substrate/wasm-runtime/polkadot/src/{ => support}/endiansensitive.rs (100%) rename substrate/wasm-runtime/polkadot/src/{ => support}/environment.rs (100%) rename substrate/wasm-runtime/polkadot/src/{ => support}/function.rs (100%) rename substrate/wasm-runtime/polkadot/src/{ => support}/joiner.rs (100%) rename substrate/wasm-runtime/polkadot/src/{ => support}/keyedvec.rs (100%) create mode 100644 substrate/wasm-runtime/polkadot/src/support/mod.rs rename substrate/wasm-runtime/polkadot/src/{ => support}/primitives.rs (100%) rename substrate/wasm-runtime/polkadot/src/{ => support}/slicable.rs (100%) rename substrate/wasm-runtime/polkadot/src/{ => support}/storage.rs (100%) rename substrate/wasm-runtime/polkadot/src/{ => support}/streamreader.rs (100%) rename substrate/wasm-runtime/polkadot/src/{ => support}/testing.rs (100%) diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 5646c7c322..cc48d8caa6 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -4,16 +4,10 @@ #[macro_use] extern crate runtime_support; -mod endiansensitive; -mod streamreader; -mod joiner; -mod slicable; -mod primitives; -mod keyedvec; -mod function; -mod environment; -mod storage; -mod testing; +mod support; +pub use support::{endiansensitive, streamreader, joiner, slicable, primitives, keyedvec, function, + environment, storage, testing}; + #[allow(unused)] mod system; #[allow(unused)] diff --git a/substrate/wasm-runtime/polkadot/src/endiansensitive.rs b/substrate/wasm-runtime/polkadot/src/support/endiansensitive.rs similarity index 100% rename from substrate/wasm-runtime/polkadot/src/endiansensitive.rs rename to substrate/wasm-runtime/polkadot/src/support/endiansensitive.rs diff --git a/substrate/wasm-runtime/polkadot/src/environment.rs b/substrate/wasm-runtime/polkadot/src/support/environment.rs similarity index 100% rename from substrate/wasm-runtime/polkadot/src/environment.rs rename to substrate/wasm-runtime/polkadot/src/support/environment.rs diff --git a/substrate/wasm-runtime/polkadot/src/function.rs b/substrate/wasm-runtime/polkadot/src/support/function.rs similarity index 100% rename from substrate/wasm-runtime/polkadot/src/function.rs rename to substrate/wasm-runtime/polkadot/src/support/function.rs diff --git a/substrate/wasm-runtime/polkadot/src/joiner.rs b/substrate/wasm-runtime/polkadot/src/support/joiner.rs similarity index 100% rename from substrate/wasm-runtime/polkadot/src/joiner.rs rename to substrate/wasm-runtime/polkadot/src/support/joiner.rs diff --git a/substrate/wasm-runtime/polkadot/src/keyedvec.rs b/substrate/wasm-runtime/polkadot/src/support/keyedvec.rs similarity index 100% rename from substrate/wasm-runtime/polkadot/src/keyedvec.rs rename to substrate/wasm-runtime/polkadot/src/support/keyedvec.rs diff --git a/substrate/wasm-runtime/polkadot/src/support/mod.rs b/substrate/wasm-runtime/polkadot/src/support/mod.rs new file mode 100644 index 0000000000..dd381b1ad2 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/support/mod.rs @@ -0,0 +1,10 @@ +pub mod endiansensitive; +pub mod streamreader; +pub mod joiner; +pub mod slicable; +pub mod primitives; +pub mod keyedvec; +pub mod function; +pub mod environment; +pub mod storage; +pub mod testing; diff --git a/substrate/wasm-runtime/polkadot/src/primitives.rs b/substrate/wasm-runtime/polkadot/src/support/primitives.rs similarity index 100% rename from substrate/wasm-runtime/polkadot/src/primitives.rs rename to substrate/wasm-runtime/polkadot/src/support/primitives.rs diff --git a/substrate/wasm-runtime/polkadot/src/slicable.rs b/substrate/wasm-runtime/polkadot/src/support/slicable.rs similarity index 100% rename from substrate/wasm-runtime/polkadot/src/slicable.rs rename to substrate/wasm-runtime/polkadot/src/support/slicable.rs diff --git a/substrate/wasm-runtime/polkadot/src/storage.rs b/substrate/wasm-runtime/polkadot/src/support/storage.rs similarity index 100% rename from substrate/wasm-runtime/polkadot/src/storage.rs rename to substrate/wasm-runtime/polkadot/src/support/storage.rs diff --git a/substrate/wasm-runtime/polkadot/src/streamreader.rs b/substrate/wasm-runtime/polkadot/src/support/streamreader.rs similarity index 100% rename from substrate/wasm-runtime/polkadot/src/streamreader.rs rename to substrate/wasm-runtime/polkadot/src/support/streamreader.rs diff --git a/substrate/wasm-runtime/polkadot/src/testing.rs b/substrate/wasm-runtime/polkadot/src/support/testing.rs similarity index 100% rename from substrate/wasm-runtime/polkadot/src/testing.rs rename to substrate/wasm-runtime/polkadot/src/support/testing.rs From dc6ebf71cfc7492d81e9ed340b674df9d090801c Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 16 Jan 2018 18:56:57 +0100 Subject: [PATCH 037/112] Fix up wasm runtime. --- substrate/executor/src/wasm_executor.rs | 4 +-- substrate/native-runtime/support/src/lib.rs | 6 +++++ .../wasm-runtime/polkadot/src/consensus.rs | 1 + substrate/wasm-runtime/polkadot/src/lib.rs | 17 ++++++------- .../polkadot/src/support/joiner.rs | 1 + .../polkadot/src/support/keyedvec.rs | 1 + .../wasm-runtime/polkadot/src/support/mod.rs | 2 ++ .../polkadot/src/support/primitives.rs | 23 +++++++++--------- .../polkadot/src/support/slicable.rs | 2 +- substrate/wasm-runtime/support/src/lib.rs | 16 ++++++++---- .../release/runtime_polkadot.compact.wasm | Bin 218 -> 5276 bytes .../release/runtime_polkadot.wasm | Bin 341 -> 5364 bytes 12 files changed, 45 insertions(+), 28 deletions(-) diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index cb2df774d9..41029424fa 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -136,8 +136,8 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, } else { 0 } } else { 0 } }, - ext_deposit_log(_log_data: *const u8, _log_len: u32) => { - // TODO + ext_chain_id() -> u64 => { + 42u64 } => <'e, E: Externalities + 'e> ); diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index 795cae2ffd..9ec5f77bdd 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -68,6 +68,12 @@ pub fn set_storage(_key: &[u8], _value: &[u8]) { ); } +/// The current relay chain identifier. +pub fn chain_id() -> u64 { + // TODO: fetch from Externalities. + 42u64 +} + /// Execute the given closure with global function available whose functionality routes into the /// externalities `ext`. Forwards the value that the closure returns. pub fn with_externalities R>(ext: &mut Externalities, f: F) -> R { diff --git a/substrate/wasm-runtime/polkadot/src/consensus.rs b/substrate/wasm-runtime/polkadot/src/consensus.rs index ef4d5a9856..add87a1808 100644 --- a/substrate/wasm-runtime/polkadot/src/consensus.rs +++ b/substrate/wasm-runtime/polkadot/src/consensus.rs @@ -1,3 +1,4 @@ +use runtime_support::Vec; use keyedvec::KeyedVec; use storage::Storage; use primitives::{AccountID, SessionKey, BlockNumber}; diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index cc48d8caa6..680116b3d9 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -6,7 +6,9 @@ extern crate runtime_support; mod support; pub use support::{endiansensitive, streamreader, joiner, slicable, primitives, keyedvec, function, - environment, storage, testing}; + environment, storage}; +#[cfg(test)] +pub use support::testing; #[allow(unused)] mod system; @@ -19,9 +21,12 @@ mod timestamp; use runtime_support::Vec; use slicable::Slicable; -use primitives::{ChainID, Block, Transaction}; +use primitives::{Block, Transaction}; -// TODO: add keccak256 (or some better hashing scheme) & ECDSA-recover (or some better sig scheme) +// TODO: add externals for: +// - keccak256 (or some better hashing scheme) +// - trie rooting +// - ECDSA-recover (or some better sig scheme) pub fn execute_block(input: Vec) -> Vec { system::execute_block(Block::from_slice(&input).unwrap()) @@ -32,9 +37,3 @@ pub fn execute_transaction(input: Vec) -> Vec { } impl_stubs!(execute_block, execute_transaction); - -/// The current relay chain identifier. -pub fn chain_id() -> ChainID { - // TODO: retrieve from external - unimplemented!() -} diff --git a/substrate/wasm-runtime/polkadot/src/support/joiner.rs b/substrate/wasm-runtime/polkadot/src/support/joiner.rs index 99b38dec57..817df8e4cb 100644 --- a/substrate/wasm-runtime/polkadot/src/support/joiner.rs +++ b/substrate/wasm-runtime/polkadot/src/support/joiner.rs @@ -1,3 +1,4 @@ +use runtime_support::Vec; use slicable::Slicable; pub trait Joiner { diff --git a/substrate/wasm-runtime/polkadot/src/support/keyedvec.rs b/substrate/wasm-runtime/polkadot/src/support/keyedvec.rs index 3b0e595628..fcc410e582 100644 --- a/substrate/wasm-runtime/polkadot/src/support/keyedvec.rs +++ b/substrate/wasm-runtime/polkadot/src/support/keyedvec.rs @@ -1,3 +1,4 @@ +use runtime_support::Vec; use primitives::AccountID; use slicable::Slicable; diff --git a/substrate/wasm-runtime/polkadot/src/support/mod.rs b/substrate/wasm-runtime/polkadot/src/support/mod.rs index dd381b1ad2..47b29194dc 100644 --- a/substrate/wasm-runtime/polkadot/src/support/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/support/mod.rs @@ -7,4 +7,6 @@ pub mod keyedvec; pub mod function; pub mod environment; pub mod storage; + +#[cfg(test)] pub mod testing; diff --git a/substrate/wasm-runtime/polkadot/src/support/primitives.rs b/substrate/wasm-runtime/polkadot/src/support/primitives.rs index 44d3bc4739..f1bd31cc66 100644 --- a/substrate/wasm-runtime/polkadot/src/support/primitives.rs +++ b/substrate/wasm-runtime/polkadot/src/support/primitives.rs @@ -1,3 +1,4 @@ +use runtime_support::Vec; use streamreader::StreamReader; use joiner::Joiner; use slicable::{Slicable, NonTrivialSlicable}; @@ -62,7 +63,7 @@ impl Slicable for Transaction { } fn to_vec(&self) -> Vec { - vec![] + Vec::new() .join(&self.signed) .join(&(self.function as u8)) .join(&self.nonce) @@ -84,7 +85,7 @@ impl Slicable for Vec { fn from_slice(value: &[u8]) -> Option { let len = Self::size_of(&value[0..4])?; let mut off = 4; - let mut r = vec![]; + let mut r = Vec::new(); while off < len { let element_len = T::size_of(&value[off..])?; r.push(T::from_slice(&value[off..off + element_len])?); @@ -100,7 +101,7 @@ impl Slicable for Vec { fn to_vec(&self) -> Vec { let vecs = self.iter().map(Slicable::to_vec).collect::>(); let len = vecs.iter().fold(0, |mut a, v| {a += v.len(); a}); - let mut r = vec![].join(&(len as u32)); + let mut r = Vec::new().join(&(len as u32)); vecs.iter().for_each(|v| r.extend_from_slice(v)); r } @@ -127,7 +128,7 @@ impl Slicable for Header { } fn to_vec(&self) -> Vec { - vec![] + Vec::new() .join(&self.parent_hash) .join(&self.number) .join(&self.state_root) @@ -156,7 +157,7 @@ impl Slicable for Block { } fn to_vec(&self) -> Vec { - vec![] + Vec::new() .join(&self.header) .join(&self.transactions) } @@ -181,7 +182,7 @@ mod tests { let tx = Transaction { signed: one.clone(), function: Function::StakingTransferStake, - input_data: vec![].join(&two).join(&69u64), + input_data: Vec::new().join(&two).join(&69u64), nonce: 69, }; let serialised = tx.to_vec(); @@ -202,7 +203,7 @@ mod tests { let tx = Transaction { signed: one.clone(), function: Function::StakingTransferStake, - input_data: vec![].join(&two).join(&69u64), + input_data: Vec::new().join(&two).join(&69u64), nonce: 69, }; let data = [ @@ -271,13 +272,13 @@ mod tests { let tx1 = Transaction { signed: one.clone(), function: Function::StakingTransferStake, - input_data: vec![].join(&two).join(&69u64), + input_data: Vec::new().join(&two).join(&69u64), nonce: 69, }; let tx2 = Transaction { signed: two.clone(), function: Function::StakingStake, - input_data: vec![], + input_data: Vec::new(), nonce: 42, }; let h = Header { @@ -327,13 +328,13 @@ mod tests { let tx1 = Transaction { signed: one.clone(), function: Function::StakingTransferStake, - input_data: vec![].join(&two).join(&69u64), + input_data: Vec::new().join(&two).join(&69u64), nonce: 69, }; let tx2 = Transaction { signed: two.clone(), function: Function::StakingStake, - input_data: vec![], + input_data: Vec::new(), nonce: 42, }; let h = Header { diff --git a/substrate/wasm-runtime/polkadot/src/support/slicable.rs b/substrate/wasm-runtime/polkadot/src/support/slicable.rs index e220eb0f7d..939d1591ca 100644 --- a/substrate/wasm-runtime/polkadot/src/support/slicable.rs +++ b/substrate/wasm-runtime/polkadot/src/support/slicable.rs @@ -59,7 +59,7 @@ impl Slicable for Vec { unimplemented!(); } fn to_vec(&self) -> Vec { - let mut r: Vec = vec![].join(&(self.len() as u32)); + let mut r: Vec = Vec::new().join(&(self.len() as u32)); r.extend_from_slice(&self); r } diff --git a/substrate/wasm-runtime/support/src/lib.rs b/substrate/wasm-runtime/support/src/lib.rs index 9c64f1a72b..308ab6dd9e 100644 --- a/substrate/wasm-runtime/support/src/lib.rs +++ b/substrate/wasm-runtime/support/src/lib.rs @@ -10,6 +10,7 @@ pub use alloc::vec::Vec; pub use alloc::boxed::Box; pub use alloc::rc::Rc; pub use core::mem::{transmute, size_of, uninitialized, swap}; +pub use core::slice; pub use core::cell::{RefCell, Ref, RefMut}; extern crate pwasm_libc; @@ -27,7 +28,7 @@ extern "C" { fn ext_set_storage(key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32); fn ext_get_allocated_storage(key_data: *const u8, key_len: u32, written_out: *mut u32) -> *mut u8; fn ext_get_storage_into(key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32) -> u32; - fn ext_deposit_log(log_data: *const u8, log_len: u32); + fn ext_chain_id() -> u64; } pub fn storage(key: &[u8]) -> Vec { @@ -64,11 +65,16 @@ pub fn set_storage(key: &[u8], value: &[u8]) { } } -pub fn deposit_log(log: &[u8]) { +pub fn read_storage(key: &[u8], value_out: &mut [u8]) -> usize { unsafe { - ext_deposit_log( - &log[0] as *const u8, log.len() as u32, - ) + ext_get_storage_into(&key[0], key.len() as u32, &mut value_out[0], value_out.len() as u32) as usize + } +} + +/// The current relay chain identifier. +pub fn chain_id() -> u64 { + unsafe { + ext_chain_id() } } diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm index be2ae9b30e8d7d68992f083914c317bed5487e55..658efc37386ac47900dea844825f63fd7c92c24f 100644 GIT binary patch literal 5276 zcmb_gy>A@H6`z^iy$|l~-QL}vMaL@ME{Na=M34*nc(4S6LqJhn7;e(@DC#0S#V!ieD3cy)$3z9xo1$_U_Dg?;R`-mFB56o_e_V;KAX(GPPj-aR2i!l*fV|YaG{$ zmG5=JK&hb7Y_>e3d|!W#H&3g6^Oudr!}-I*qc4n#=8xz5j~4UYTQGfJtqsff#nIlu z@!tO8-r<1?`$vzC7rVFSckUhRK05f#y@T7T(&DV-*MCV_ zKOY;F`FLu{lXsuYXOSY0OrEvKw|bE^sYT7t-b(}WZ$z3DR-_H`DYzLKYNXAM7m9w` za&saGVv{u^&2#cdvVvEA`d%ERJ~d*+_Do2MniHc03i-jx?^`BXnlG)gIJ$3N>ib!5Vtne^mnygG zInD?#wJ}+(MSp(8mB_%DZW>|Hq#g<3@rYQ`u2!`Oob0Sy?s8Ncj zw`pcu=2XMRGiRegUO6iw*l4bpWi8lf)n?hosopZr*vN@9(yq4<5sa)+v$D%tFcMO$ z6tR(KFmfVDoM$@JE~o7?h+rh5wR0jE=~7sV*vJWtY*U*$g>a3c;whx=s^Ye6=2d(6 zmFeJ3i*Qiwm)ada`veMM2`Tklh@T(=JV8r!ZEVna73gpP#?ux9!^31k4=Y%9s1^D6XRI#=f#GXnPMH6{0!)-moY2+P1my{&hQjyo|4Ah18N{}!wKLFZSL`baUt-c@y~uc;5&*Usyq6>88q zm?Qj4)AW{J#VDs>l$aSMwq@Gsv1w(dW)+!%;~HexagJ(42)}__*>8oAj64ynRs2*Y zqZ3I0N&;~r@qWn~F~yq(={bXmf(`0|aUz(gE60goqAnLPF_Zd?rSd_OHGMb{Y}EAO zM6gj)hS+dq5Hroz%n@@A)vOV78TKl^kagS4#eT&cLB$+MvLeGo4;ePY9axfXeW(l1 zQXip4ej#AQfYQF%wk;GDZad_z#dUj|VloqPEYkFD5h6^*0SGT1o4XmNr8(dM2*+l| zq7&_2ZfEU@`HEjKZa8ZkX{4~WNp1;-ux2CmrMU4(87^NWGit7gQ;ZwvCL`MPPINjz zj_#;*5DL`xIjGoUhE;DsEd%ZlLkq?@btQ}3t3!_G8aa9pL5`7;W3E8%VqZaT*3c0I zhTgas`p`iihOjoE{_nPM9<&UP9+t2o;4pfgf;(~w4N;(JY_9e>MvuF*?*e4_F% zh3E;hru7{q|3l^A%aNV3`_h=TtxAU&jkgUVjsUOEy<&H)RF*K%1UVJmhyq3~(NQ#_ zWMZykh$dz#)~JhZpc>Fhb*B4w<|8nEQwpR#$JqMx^QV1aJ^~zE@b~vxWerQx^TSwTjdtZLuz6u zE|n2AuPSv-FR%+os{?t~w*Jp0Tu4%9q%`pa7cEQ-D6H0xuIj}#{RD~0(Zx?JD%Ekn zv3j2dtLjhmHGRhVXf|9}3xFNgrv9q#8FV}JZhDEjX-pAvx(!kR(1F9qxyOlD>>a

      45kB57@SlpcDVEVlarH} z@Al!2+VVi}7T=ERZvL_x$PF9T$7%pFa6Z!z*c>F;32DgK4YL!H5^f_$gb`BV9kB^L zg&oFf9fdwb8?1PT%Xwy)L%_zg{uCXX)1h<#9e<*D-;JDsVl4*Mf;_QHYy(wfS`zV3 zxohy5#|+9GPo6LwX1tpH_{J9YOA!M~kez@H1nk*Zc;B(-I!jn_$fxp)%|OY_t&qcN zgfwI)DikJI7MX)YP2x7D5asJUfpIFkVM@5R%me1ZDzI=LZ$Co#B`_n7bw#CBU`8%5 zBNrH%zwFe=4OL)}DTMp84h(RpOs)+?>=OiTWS8tlzTFgHI;Z084X2LKe#qkDIO}o@ zzFXevUU4248|XL-*N&tb&bfBvTsvURfy?gZTVyv}-{+-Gb~Hd94p*U-M6b& zjwG+{vN>b}?!@xnAGN`6<*JT_e|Ldy(#Hn_k^tXTxR#84g}a9ZcFNa}vESl$5NRQB zB7Q;D$fRVCLEgeeytBdQigStk6%hk5ADZv<4t>p&-|9^N`77>&`0Y=kq@je8H1?%5 zSmcE*W{{k&I B=@I|{ literal 218 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 literal 341 zcmYLE%Wi})3>+unnXSaCx1RWv?nmqySn5`&n}8tf<5GUT3AEy1duC*NY&4T00Q45s zw7>@~wOp1^gwH=UAkL9wdrSG@s?U)b2s97WG}mk2f_8yTJ3JwRpw|vIroZu~Y%^>o zc3#L*DU}d{pcD;2Bnii4$YR5$AD;p*{NQ$WTwT1$H=@^n?#9MWP3yYeB0i4u Date: Tue, 16 Jan 2018 19:04:13 +0100 Subject: [PATCH 038/112] use externalities for chain_id --- substrate/executor/src/wasm_executor.rs | 2 +- substrate/native-runtime/support/src/lib.rs | 7 +++++-- substrate/state_machine/src/ext.rs | 4 ++++ substrate/state_machine/src/lib.rs | 5 ++++- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index 41029424fa..580da80772 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -137,7 +137,7 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, } else { 0 } }, ext_chain_id() -> u64 => { - 42u64 + this.ext.chain_id() } => <'e, E: Externalities + 'e> ); diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index 9ec5f77bdd..498081cd33 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -70,8 +70,9 @@ pub fn set_storage(_key: &[u8], _value: &[u8]) { /// The current relay chain identifier. pub fn chain_id() -> u64 { - // TODO: fetch from Externalities. - 42u64 + ext::with(|holder| + holder.ext.chain_id() + ).unwrap_or(0) } /// Execute the given closure with global function available whose functionality routes into the @@ -105,6 +106,8 @@ mod tests { fn set_storage(&mut self, key: Vec, value: Vec) { self.storage.insert(key, value); } + + fn chain_id(&self) -> u64 { 42 } } macro_rules! map { diff --git a/substrate/state_machine/src/ext.rs b/substrate/state_machine/src/ext.rs index ce7b9a0268..1452558ccd 100644 --- a/substrate/state_machine/src/ext.rs +++ b/substrate/state_machine/src/ext.rs @@ -73,4 +73,8 @@ impl<'a, B: 'a> Externalities for Ext<'a, B> fn set_storage(&mut self, key: Vec, value: Vec) { self.overlay.set_storage(key, value); } + + fn chain_id(&self) -> u64 { + 42 + } } diff --git a/substrate/state_machine/src/lib.rs b/substrate/state_machine/src/lib.rs index 38c481113f..3ff3b69469 100644 --- a/substrate/state_machine/src/lib.rs +++ b/substrate/state_machine/src/lib.rs @@ -130,7 +130,10 @@ pub trait Externalities { /// Set storage of current contract being called (effective immediately). fn set_storage(&mut self, key: Vec, value: Vec); - /// Get the current set of authorities. + /// Get the identity of the chain. + fn chain_id(&self) -> u64 { 42 } // TODO: remove implementation and fix resulting errors. + + /// Get the current set of authorities from storage. fn authorities(&self) -> Result, Self::Error> { (0..self.storage(b"con\0aut\0len")?.into_iter() .rev() From 17c8bad87ce4b888cf662939946243928c056395 Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 16 Jan 2018 19:07:10 +0100 Subject: [PATCH 039/112] Clean up (Test)Externalities. --- substrate/executor/src/wasm_executor.rs | 2 ++ substrate/state_machine/src/lib.rs | 4 +++- substrate/wasm-runtime/polkadot/src/support/testing.rs | 2 ++ substrate/wasm-runtime/polkadot/src/system.rs | 2 ++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index 580da80772..b12986e975 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -208,6 +208,8 @@ mod tests { fn set_storage(&mut self, key: Vec, value: Vec) { self.storage.insert(key, value); } + + fn chain_id(&self) -> u64 { 42 } } #[test] diff --git a/substrate/state_machine/src/lib.rs b/substrate/state_machine/src/lib.rs index 3ff3b69469..e94b2b6078 100644 --- a/substrate/state_machine/src/lib.rs +++ b/substrate/state_machine/src/lib.rs @@ -131,7 +131,7 @@ pub trait Externalities { fn set_storage(&mut self, key: Vec, value: Vec); /// Get the identity of the chain. - fn chain_id(&self) -> u64 { 42 } // TODO: remove implementation and fix resulting errors. + fn chain_id(&self) -> u64; /// Get the current set of authorities from storage. fn authorities(&self) -> Result, Self::Error> { @@ -244,6 +244,8 @@ mod tests { fn set_storage(&mut self, key: Vec, value: Vec) { self.storage.insert(key, value); } + + fn chain_id(&self) -> u64 { 42 } } #[test] diff --git a/substrate/wasm-runtime/polkadot/src/support/testing.rs b/substrate/wasm-runtime/polkadot/src/support/testing.rs index d73917eb16..ec7fac6d6d 100644 --- a/substrate/wasm-runtime/polkadot/src/support/testing.rs +++ b/substrate/wasm-runtime/polkadot/src/support/testing.rs @@ -16,4 +16,6 @@ impl Externalities for TestExternalities { fn set_storage(&mut self, key: Vec, value: Vec) { self.storage.insert(key, value); } + + fn chain_id(&self) -> u64 { 42 } } diff --git a/substrate/wasm-runtime/polkadot/src/system.rs b/substrate/wasm-runtime/polkadot/src/system.rs index 88414fa9a1..de8b814bcf 100644 --- a/substrate/wasm-runtime/polkadot/src/system.rs +++ b/substrate/wasm-runtime/polkadot/src/system.rs @@ -96,6 +96,8 @@ mod tests { fn set_storage(&mut self, key: Vec, value: Vec) { self.storage.insert(key, value); } + + fn chain_id(&self) -> u64 { 42 } } macro_rules! map { From 98faf54ec4ae9e333961eade8674493637b8c460 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 17 Jan 2018 11:45:36 +0100 Subject: [PATCH 040/112] Repot and introduce keccak-256 external. --- substrate/Cargo.lock | 3 + substrate/executor/Cargo.toml | 2 + substrate/executor/src/lib.rs | 2 + substrate/executor/src/wasm_executor.rs | 67 ++++++++---------- substrate/native-runtime/support/Cargo.toml | 1 + substrate/native-runtime/support/src/lib.rs | 4 ++ .../src/{support => codec}/endiansensitive.rs | 0 .../polkadot/src/{support => codec}/joiner.rs | 0 .../src/{support => codec}/keyedvec.rs | 0 .../wasm-runtime/polkadot/src/codec/mod.rs | 5 ++ .../src/{support => codec}/slicable.rs | 0 .../src/{support => codec}/streamreader.rs | 0 substrate/wasm-runtime/polkadot/src/lib.rs | 20 ++---- .../polkadot/src/{ => runtime}/consensus.rs | 0 .../wasm-runtime/polkadot/src/runtime/mod.rs | 8 +++ .../polkadot/src/{ => runtime}/staking.rs | 4 +- .../polkadot/src/{ => runtime}/system.rs | 5 +- .../polkadot/src/{ => runtime}/timestamp.rs | 0 .../polkadot/src/support/function.rs | 3 +- .../wasm-runtime/polkadot/src/support/mod.rs | 5 -- substrate/wasm-runtime/support/src/lib.rs | 11 +++ .../release/runtime_test.compact.wasm | Bin 3392 -> 843 bytes .../release/runtime_test.wasm | Bin 3480 -> 960 bytes substrate/wasm-runtime/test/src/lib.rs | 65 +++-------------- 24 files changed, 88 insertions(+), 117 deletions(-) rename substrate/wasm-runtime/polkadot/src/{support => codec}/endiansensitive.rs (100%) rename substrate/wasm-runtime/polkadot/src/{support => codec}/joiner.rs (100%) rename substrate/wasm-runtime/polkadot/src/{support => codec}/keyedvec.rs (100%) create mode 100644 substrate/wasm-runtime/polkadot/src/codec/mod.rs rename substrate/wasm-runtime/polkadot/src/{support => codec}/slicable.rs (100%) rename substrate/wasm-runtime/polkadot/src/{support => codec}/streamreader.rs (100%) rename substrate/wasm-runtime/polkadot/src/{ => runtime}/consensus.rs (100%) create mode 100644 substrate/wasm-runtime/polkadot/src/runtime/mod.rs rename substrate/wasm-runtime/polkadot/src/{ => runtime}/staking.rs (98%) rename substrate/wasm-runtime/polkadot/src/{ => runtime}/system.rs (98%) rename substrate/wasm-runtime/polkadot/src/{ => runtime}/timestamp.rs (100%) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index d0eee3e39a..2ac1c11912 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -687,8 +687,10 @@ dependencies = [ "polkadot-primitives 0.1.0", "polkadot-serializer 0.1.0", "polkadot-state-machine 0.1.0", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -841,6 +843,7 @@ dependencies = [ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "polkadot-state-machine 0.1.0", + "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/substrate/executor/Cargo.toml b/substrate/executor/Cargo.toml index 8aa72f4327..2d124f60ac 100644 --- a/substrate/executor/Cargo.toml +++ b/substrate/executor/Cargo.toml @@ -12,6 +12,8 @@ serde = "1.0" serde_derive = "1.0" parity-wasm = "0.15.0" byteorder = "1.1" +tiny-keccak = "1.3" +rustc-hex = "1.0.0" [dev-dependencies] assert_matches = "1.1" diff --git a/substrate/executor/src/lib.rs b/substrate/executor/src/lib.rs index 8bf7f42b62..3c54d25efb 100644 --- a/substrate/executor/src/lib.rs +++ b/substrate/executor/src/lib.rs @@ -33,6 +33,8 @@ extern crate polkadot_state_machine as state_machine; extern crate serde; extern crate parity_wasm; extern crate byteorder; +extern crate tiny_keccak; +extern crate rustc_hex; #[macro_use] extern crate error_chain; diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index b12986e975..8597656c51 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -26,6 +26,7 @@ use state_machine::{Externalities, CodeExecutor}; use error::{Error, ErrorKind, Result}; use wasm_utils::{MemoryInstance, UserDefinedElements, AddModuleWithoutFullDependentInstance}; +use tiny_keccak; struct Heap { end: u32, @@ -138,6 +139,15 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, }, ext_chain_id() -> u64 => { this.ext.chain_id() + }, + ext_keccak256(data: *const u8, len: u32, out: *mut u8) => { + let result = + if let Ok(value) = this.memory.get(data, len as usize) { + tiny_keccak::keccak256(&value) + } else { + [0; 32] + }; + let _ = this.memory.set(out, &result); } => <'e, E: Externalities + 'e> ); @@ -193,6 +203,7 @@ impl CodeExecutor for WasmExecutor { mod tests { use super::*; + use rustc_hex::FromHex; #[derive(Debug, Default)] struct TestExternalities { @@ -213,50 +224,34 @@ mod tests { } #[test] - fn should_pass_externalities_at_call() { + fn storage_should_work() { let mut ext = TestExternalities::default(); - ext.set_storage(b"\0code".to_vec(), b"The code".to_vec()); + ext.set_storage(b"foo".to_vec(), b"bar".to_vec()); + let test_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); - let program = ProgramInstance::new().unwrap(); - - let test_module = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); - let module = deserialize_buffer(test_module.to_vec()).expect("Failed to load module"); - let module = program.add_module_by_sigs("test", module, map!["env" => FunctionExecutor::::SIGNATURES]).expect("Failed to initialize module"); - - let output = { - let memory = module.memory(ItemIndex::Internal(0)).unwrap(); - let mut fec = FunctionExecutor::new(&memory, &mut ext); - - let data = b"Hello world"; - let size = data.len() as u32; - let offset = fec.heap.allocate(size); - memory.set(offset, data).unwrap(); - - let returned = program - .params_with_external("env", &mut fec) - .map(|p| p - .add_argument(I32(offset as i32)) - .add_argument(I32(size as i32))) - .and_then(|p| module.execute_export("test_data_in", p)) - .map_err(|_| -> Error { ErrorKind::Runtime.into() }).expect("function should be callable"); - - if let Some(I64(r)) = returned { - println!("returned {:?} ({:?}, {:?})", r, r as u32, (r >> 32) as u32 as usize); - memory.get(r as u32, (r >> 32) as u32 as usize).expect("memory address should be reasonable.") - } else { - panic!("bad return value, not u64"); - } - }; + let output = WasmExecutor.call(&mut ext, &test_code[..], "test_data_in", &CallData(b"Hello world".to_vec())).unwrap(); assert_eq!(output, b"all ok!".to_vec()); let expected: HashMap<_, _> = map![ - b"\0code".to_vec() => b"Hello world".to_vec(), b"input".to_vec() => b"Hello world".to_vec(), - b"code".to_vec() => b"The code".to_vec(), - b"\0authority_count".to_vec() => vec![1], - b"\0authority".to_vec() => b"Hello world".to_vec() + b"foo".to_vec() => b"bar".to_vec(), + b"baz".to_vec() => b"bar".to_vec() ]; assert_eq!(expected, ext.storage); } + + #[test] + fn keccak256_should_work() { + let mut ext = TestExternalities::default(); + let test_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); + assert_eq!( + WasmExecutor.call(&mut ext, &test_code[..], "test_keccak256", &CallData(b"".to_vec())).unwrap(), + FromHex::from_hex("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").unwrap() + ); + assert_eq!( + WasmExecutor.call(&mut ext, &test_code[..], "test_keccak256", &CallData(b"Hello world!".to_vec())).unwrap(), + FromHex::from_hex("ecd0e108a98e192af1d2c25055f4e3bed784b5c877204e73219a5203251feaab").unwrap() + ); + } } diff --git a/substrate/native-runtime/support/Cargo.toml b/substrate/native-runtime/support/Cargo.toml index 3f979bd4ff..185dea5f92 100644 --- a/substrate/native-runtime/support/Cargo.toml +++ b/substrate/native-runtime/support/Cargo.toml @@ -11,3 +11,4 @@ lazy_static = "1.0.0" parking_lot = "0.5" polkadot-state-machine = { path = "../../state_machine" , version = "0.1" } environmental = { path = "../../environmental", version = "0.1.0" } +tiny-keccak = "1.3" diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index 498081cd33..a2fe13eb10 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -1,6 +1,7 @@ #[macro_use] extern crate environmental; extern crate polkadot_state_machine; +extern crate tiny_keccak; pub use std::vec::Vec; pub use std::rc::Rc; @@ -75,6 +76,9 @@ pub fn chain_id() -> u64 { ).unwrap_or(0) } +/// Conduct a Keccak-256 hash of the given data. +pub use tiny_keccak::keccak256; + /// Execute the given closure with global function available whose functionality routes into the /// externalities `ext`. Forwards the value that the closure returns. pub fn with_externalities R>(ext: &mut Externalities, f: F) -> R { diff --git a/substrate/wasm-runtime/polkadot/src/support/endiansensitive.rs b/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs similarity index 100% rename from substrate/wasm-runtime/polkadot/src/support/endiansensitive.rs rename to substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs diff --git a/substrate/wasm-runtime/polkadot/src/support/joiner.rs b/substrate/wasm-runtime/polkadot/src/codec/joiner.rs similarity index 100% rename from substrate/wasm-runtime/polkadot/src/support/joiner.rs rename to substrate/wasm-runtime/polkadot/src/codec/joiner.rs diff --git a/substrate/wasm-runtime/polkadot/src/support/keyedvec.rs b/substrate/wasm-runtime/polkadot/src/codec/keyedvec.rs similarity index 100% rename from substrate/wasm-runtime/polkadot/src/support/keyedvec.rs rename to substrate/wasm-runtime/polkadot/src/codec/keyedvec.rs diff --git a/substrate/wasm-runtime/polkadot/src/codec/mod.rs b/substrate/wasm-runtime/polkadot/src/codec/mod.rs new file mode 100644 index 0000000000..5350dc05c1 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/codec/mod.rs @@ -0,0 +1,5 @@ +pub mod endiansensitive; +pub mod streamreader; +pub mod joiner; +pub mod slicable; +pub mod keyedvec; diff --git a/substrate/wasm-runtime/polkadot/src/support/slicable.rs b/substrate/wasm-runtime/polkadot/src/codec/slicable.rs similarity index 100% rename from substrate/wasm-runtime/polkadot/src/support/slicable.rs rename to substrate/wasm-runtime/polkadot/src/codec/slicable.rs diff --git a/substrate/wasm-runtime/polkadot/src/support/streamreader.rs b/substrate/wasm-runtime/polkadot/src/codec/streamreader.rs similarity index 100% rename from substrate/wasm-runtime/polkadot/src/support/streamreader.rs rename to substrate/wasm-runtime/polkadot/src/codec/streamreader.rs diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 680116b3d9..52b29b05cf 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -4,20 +4,14 @@ #[macro_use] extern crate runtime_support; +mod codec; mod support; -pub use support::{endiansensitive, streamreader, joiner, slicable, primitives, keyedvec, function, - environment, storage}; +mod runtime; +pub use codec::{endiansensitive, streamreader, joiner, slicable, keyedvec}; +pub use support::{primitives, function, environment, storage}; #[cfg(test)] pub use support::testing; - -#[allow(unused)] -mod system; -#[allow(unused)] -mod consensus; -#[allow(unused)] -mod staking; -#[allow(unused)] -mod timestamp; +#[allow(unused_imports)] // TODO: remove in due course use runtime_support::Vec; use slicable::Slicable; @@ -29,11 +23,11 @@ use primitives::{Block, Transaction}; // - ECDSA-recover (or some better sig scheme) pub fn execute_block(input: Vec) -> Vec { - system::execute_block(Block::from_slice(&input).unwrap()) + runtime::system::execute_block(Block::from_slice(&input).unwrap()) } pub fn execute_transaction(input: Vec) -> Vec { - system::execute_transaction(&Transaction::from_slice(&input).unwrap()) + runtime::system::execute_transaction(&Transaction::from_slice(&input).unwrap()) } impl_stubs!(execute_block, execute_transaction); diff --git a/substrate/wasm-runtime/polkadot/src/consensus.rs b/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs similarity index 100% rename from substrate/wasm-runtime/polkadot/src/consensus.rs rename to substrate/wasm-runtime/polkadot/src/runtime/consensus.rs diff --git a/substrate/wasm-runtime/polkadot/src/runtime/mod.rs b/substrate/wasm-runtime/polkadot/src/runtime/mod.rs new file mode 100644 index 0000000000..c73e338a91 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/runtime/mod.rs @@ -0,0 +1,8 @@ +#[allow(unused)] +pub mod system; +#[allow(unused)] +pub mod consensus; +#[allow(unused)] +pub mod staking; +#[allow(unused)] +pub mod timestamp; diff --git a/substrate/wasm-runtime/polkadot/src/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs similarity index 98% rename from substrate/wasm-runtime/polkadot/src/staking.rs rename to substrate/wasm-runtime/polkadot/src/runtime/staking.rs index d8903504d2..ca37e7f6fe 100644 --- a/substrate/wasm-runtime/polkadot/src/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -1,7 +1,7 @@ use keyedvec::KeyedVec; use storage::{Storage, storage_into}; use primitives::{BlockNumber, Balance, AccountID}; -use consensus; +use runtime::consensus; /// The length of a staking era in blocks. pub fn era_length() -> BlockNumber { @@ -68,7 +68,7 @@ mod tests { use runtime_support::with_externalities; use testing::TestExternalities; use primitives::{AccountID}; - use staking; + use runtime::staking; macro_rules! map { ($( $name:expr => $value:expr ),*) => ( diff --git a/substrate/wasm-runtime/polkadot/src/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs similarity index 98% rename from substrate/wasm-runtime/polkadot/src/system.rs rename to substrate/wasm-runtime/polkadot/src/runtime/system.rs index de8b814bcf..27c5eb4fd9 100644 --- a/substrate/wasm-runtime/polkadot/src/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -1,8 +1,8 @@ use primitives::{Block, BlockNumber, Hash, Transaction}; use runtime_support::{Vec, swap}; use environment::with_env; -use staking; use runtime_support; +use runtime::staking; /// The current block number being processed. Set by `execute_block`. pub fn block_number() -> BlockNumber { @@ -79,8 +79,7 @@ mod tests { use std::collections::HashMap; use runtime_support::{NoError, with_externalities, Externalities}; use primitives::{AccountID, Transaction}; - use system; - use staking; + use runtime::{system, staking}; #[derive(Debug, Default)] struct TestExternalities { diff --git a/substrate/wasm-runtime/polkadot/src/timestamp.rs b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs similarity index 100% rename from substrate/wasm-runtime/polkadot/src/timestamp.rs rename to substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs diff --git a/substrate/wasm-runtime/polkadot/src/support/function.rs b/substrate/wasm-runtime/polkadot/src/support/function.rs index 3f6845bfe6..ff54938d47 100644 --- a/substrate/wasm-runtime/polkadot/src/support/function.rs +++ b/substrate/wasm-runtime/polkadot/src/support/function.rs @@ -1,5 +1,4 @@ -use staking; -use consensus; +use runtime::{staking, consensus}; use primitives::AccountID; use streamreader::StreamReader; diff --git a/substrate/wasm-runtime/polkadot/src/support/mod.rs b/substrate/wasm-runtime/polkadot/src/support/mod.rs index 47b29194dc..aa14ad2f5d 100644 --- a/substrate/wasm-runtime/polkadot/src/support/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/support/mod.rs @@ -1,9 +1,4 @@ -pub mod endiansensitive; -pub mod streamreader; -pub mod joiner; -pub mod slicable; pub mod primitives; -pub mod keyedvec; pub mod function; pub mod environment; pub mod storage; diff --git a/substrate/wasm-runtime/support/src/lib.rs b/substrate/wasm-runtime/support/src/lib.rs index 308ab6dd9e..ae3feb14c9 100644 --- a/substrate/wasm-runtime/support/src/lib.rs +++ b/substrate/wasm-runtime/support/src/lib.rs @@ -29,6 +29,7 @@ extern "C" { fn ext_get_allocated_storage(key_data: *const u8, key_len: u32, written_out: *mut u32) -> *mut u8; fn ext_get_storage_into(key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32) -> u32; fn ext_chain_id() -> u64; + fn ext_keccak256(data: *const u8, len: u32, out: *mut u8); } pub fn storage(key: &[u8]) -> Vec { @@ -78,6 +79,16 @@ pub fn chain_id() -> u64 { } } +/// Conduct a keccak256 hash. +pub fn keccak256(data: &[u8]) -> [u8; 32] { + unsafe { + let mut result: [u8; 32] = uninitialized(); + // guaranteed to write into result. + ext_keccak256(&data[0], data.len() as u32, &mut result[0]); + result + } +} + pub trait Printable { fn print(self); } diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm index bac77de7ffc344d73e46f9c32657563efb790174..f4c438ec106e2dad2e662f47d1abbb293e62178c 100644 GIT binary patch literal 843 zcmY*XOKuZE5Pkib_SiiklbzYMy>cWYA|xCMvT#LWi&(RW^M3pN}E z&cGeGK#sr>s2+b3MjBPU_o`l3mm0}>ApnSeI2IMgs;Vkc)d5U!Dl4Wn(;PS#-^PIa zYE)X>hUuqrbh%1Xz{95=&eC#}TwN_ENtsSZ>vFkDW+{Z%54=84CzE9U;^hF+b1ly; z>INuJG(B;>%8C-&<3o?vY`U`wlnIP!C}=INfj|iyHQpMtNEgf1XNjmx*X3xMl*uS7 zV4l?Q;nc>_>W1};be0vPo8n_uOc9#x1WjGvrqvW^{ZYX$A!J1$^rWVE-c7nu;Tg_f z!2`|Uxfs5#0Uv!f;7rDF;9tZ%4j&QcJc|=Q&+qvAi|>aPus@^-_VeCj-Zj36o17t+ z$CATuR&l|$y)kY_oTTPwB+oZLfh z=3VR{x5*(N$qR7%1$Yvt^@ZEH(|Zu-F4%)G-g0$7|*Z~w-`}k#1+Xh*2eN%#*ZS39~^{l#FEx6WhGZifsKMopwNH Lw!yF0E$5woQ|P6l literal 3392 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 IqnC@pKX_xoTmS$7 literal 3480 zcmcgv&2k&Z5$>6t{hisxQldmrq{!K|6U$CyBPoS)B|e~CrsN!4KIcTyA}j+ENEHdv z(IJK^0>pc$I)yyQ!{k&rDvEhm_UQR`sOi_{+r68;qgT_{NwcC%hTbINQRp-d^(&S96o=3 z^5k$jJUTd=o}3;&9g>puLe?i?k@V|{;pEASmz{(S62r;lDz!^zoj+KJ>M^5S%K zJf%o<^kj_HR0on;sk;P7e=8$7I(| z&oTUB_;hr9aDM#t==g}7$ckZQicT=7k|{Bym(0DWP4Ip#S5*9Uqxh3DGd)=Rd15oZ ztEpA{C3!-x(O!AQYTBAdrSiIooVILg-A4PRX44p_tPf)^qDDTSZPjH1;hH=YY3s>H zdm0L%-5d0JmPr18r&K(Hl6YZ&9$aBU3lV*nu&U@)AGnLbe4zat#Z^sZiifL_7{PVq@+PZ(uzAJ)oR zHf|y=8pQ<{kIDdg(Zql%bw-e5jUEsnG|F$0|7rAOz>PLNL+$?7BK2DBzl%3OvRQJ8q>KRErAeZ z0E8$-YS}-p=@K`85z|Y0)|ODheYSPNA90KWRhz{$^WEr zt=im|clDr7eGbEafRT`w^-jqptgVy9W>G%hhub6j5V(Jl9J~_{%$9+KxCi`XN^X|%0lM7^# z^`+1EwChX}kNp^5*|;vC2iE%T;LIoC;F9}etO^2#gfHqItX9=zZ>g zYL>$Bok4JzpgS~5%Bj1Av<$?-6{k%owS?f=Ivv2n%T71bFJRJ^djX@Y#KM zg8T3Y$O}ldAoQWIr{ocQZE#~`Ca4z!67;}h22qn_7pjy@57ePE{x@+CDPqKmqSK&| zpAn*#?W<|Xo@g{iIpS)h}sw9HhUO|C-+ff;GEDG^cmq^K?FlN z)OgSj8qDDK=7NBvloR7J_+%wp3>*j-Vl`psc`|4-NxCd#Nddl?rzbQbJ>lF+dIrft z(i2C02J?g0; z3!j5MF50}@1({avH*ow)offy&7fYR9U~#`*>I|uaHxIA5=tRgb@DASwXIJi5&P$x=(UCtoU@AyAQ_X7|Xl341E9mKP8?}vA2+~6S((Q<4td(V1{$Er!C zAyD=_e|Fem^_N(cG=|0hE1Ty0gq)G2e>1zBoLxfCFRY}Lcerlh)!pS9v+rGvP~q;Z zqQ1iwWbZB!x*GKzUW3#-3xq=aK$=noq=Hbn>vqJ8qMP7rkp3Aa@aSAe_igK)TvQ28 z{HR>#bxgj6+GoGq<{RiE5hBRmL>K7&NSx!HO1olYi#IThorV)!xqI}T>SAZY1^iac z%agnMl|m&Ww)KUFI!==aZSgH=*hSnyV_*w_#haLc$sj5r7LmD)89*bn15>sz+73H} zT63P_B`I(5Hm0`%4EOiTO}>NS?at2~bT?5Ipm38SL4tKjV_{44_m5xU-+$=aP(GrR zsN7Ad1}b->yT0pE4OH%WxW(?8R0EY;vn-ib+kh6T2uY~Q@-CXvvPa`=h#n|Uf>_uP zcRZIpj4~UbMTIm}3s4|-Hl`;hM?>Ou>^VH2esyv>n!Y6VwthW4cye-%9~j)X zcJ-$Pe`Mp)@r!e;d{5SNdVV0AiBLDXB%3aN^q@|$c5%dLct&`YY)@q0nEa7!{^jU+ UboSNos3Cr(Y>MAV{^VKnUuVwX;Q#;t diff --git a/substrate/wasm-runtime/test/src/lib.rs b/substrate/wasm-runtime/test/src/lib.rs index e95844fdb0..a24de0219d 100644 --- a/substrate/wasm-runtime/test/src/lib.rs +++ b/substrate/wasm-runtime/test/src/lib.rs @@ -8,72 +8,25 @@ use alloc::vec::Vec; #[macro_use] extern crate runtime_support; -use runtime_support::{set_storage, storage, print}; +use runtime_support::{set_storage, storage, print, keccak256}; -pub fn code() -> Vec { - storage(b"\0code") +fn test_keccak256(input: Vec) -> Vec { + keccak256(&input).to_vec() } -pub fn set_code(new: &[u8]) { - set_storage(b"\0code", new) -} - -fn value_vec(mut value: usize, initial: Vec) -> Vec { - let mut acc = initial; - while value > 0 { - acc.push(value as u8); - value /= 256; - } - acc -} - -pub fn set_authority(index: usize, authority: &[u8]) { - set_storage(&value_vec(index, b"\0authority".to_vec()), authority); -} - -pub fn authority(index: usize) -> Vec { - storage(&value_vec(index, b"\0authority".to_vec())) -} - -pub fn set_authority_count(count: usize) { - (count..authority_count()).for_each(|i| set_authority(i, &[])); - set_storage(b"\0authority_count", &value_vec(count, Vec::new())); -} - -pub fn authority_count() -> usize { - storage(b"\0authority_count").into_iter().rev().fold(0, |acc, i| (acc << 8) + (i as usize)) -} - -pub fn authorities() -> Vec> { - (0..authority_count()).into_iter().map(authority).collect() -} - -pub fn set_authorities(authorities: &[&[u8]]) { - set_authority_count(authorities.len()); - authorities.iter().enumerate().for_each(|(v, i)| set_authority(v, i)); -} - -impl_stubs!(test_data_in); fn test_data_in(input: Vec) -> Vec { print(b"set_storage" as &[u8]); set_storage(b"input", &input); - print(b"code" as &[u8]); - set_storage(b"code", &code()); - - print(b"set_code" as &[u8]); - set_code(&input); - print(b"storage" as &[u8]); - let copy = storage(b"input"); + let foo = storage(b"foo"); - print(b"authorities" as &[u8]); - let mut v = authorities(); - v.push(copy); - - print(b"set_authorities" as &[u8]); - set_authorities(&v.iter().map(Vec::as_slice).collect::>()); + print(b"set_storage" as &[u8]); + set_storage(b"baz", &foo); print(b"finished!" as &[u8]); b"all ok!".to_vec() } + + +impl_stubs!(test_data_in, test_keccak256); From 65a466434b44fc39f5bb72e7964abdc0daf43b32 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 17 Jan 2018 15:23:22 +0100 Subject: [PATCH 041/112] Signing with crypto. --- substrate/Cargo.lock | 26 ++++++++++ substrate/primitives/Cargo.toml | 2 + substrate/primitives/src/lib.rs | 92 +++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 2ac1c11912..524ec96570 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -261,6 +261,11 @@ dependencies = [ "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "gcc" +version = "0.3.54" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "globset" version = "0.1.4" @@ -701,6 +706,7 @@ dependencies = [ "fixed-hash 0.1.0 (git+https://github.com/paritytech/primitives.git)", "polkadot-serializer 0.1.0", "pretty_assertions 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -846,6 +852,18 @@ dependencies = [ "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rust-crypto" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc-demangle" version = "0.1.5" @@ -856,6 +874,11 @@ name = "rustc-hex" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rustc-serialize" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rustc_version" version = "0.1.7" @@ -1199,6 +1222,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82" "checksum futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "118b49cac82e04121117cbd3121ede3147e885627d82c4546b87c702debb90c1" "checksum futures-cpupool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "e86f49cc0d92fe1b97a5980ec32d56208272cbb00f15044ea9e2799dde766fdf" +"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" "checksum globset 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90d069fe6beb9be359ef505650b3f73228c5591a3c4b1f32be2f4f44459ffa3a" "checksum hashdb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d97be07c358c5b461268b4ce60304024c5fa5acfd4bd8cd743639f0252003cf5" "checksum heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "54fab2624374e5137ae4df13bf32b0b269cb804df42d13a51221bbd431d1a237" @@ -1247,8 +1271,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" "checksum relay 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f301bafeb60867c85170031bdb2fcf24c8041f33aee09e7b116a58d4e9f781c5" "checksum rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "babe6fce20c0ca9b1582998734c4569082d0ad08e43772a1c6c40aef4f106ef9" +"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" "checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" "checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e" +"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" "checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" diff --git a/substrate/primitives/Cargo.toml b/substrate/primitives/Cargo.toml index f31afccf5b..3e2877e073 100644 --- a/substrate/primitives/Cargo.toml +++ b/substrate/primitives/Cargo.toml @@ -11,6 +11,8 @@ serde = "1.0" serde_derive = "1.0" tiny-keccak = "1.3" uint = { git = "https://github.com/paritytech/primitives.git" } +rust-crypto = "0.2.36" +ring = "0.12" [dev-dependencies] polkadot-serializer = { path = "../serializer", version = "0.1" } diff --git a/substrate/primitives/src/lib.rs b/substrate/primitives/src/lib.rs index ca32f302f3..ad4c6efd58 100644 --- a/substrate/primitives/src/lib.rs +++ b/substrate/primitives/src/lib.rs @@ -21,6 +21,7 @@ extern crate rustc_hex; extern crate serde; extern crate tiny_keccak; +extern crate crypto; #[macro_use] extern crate crunchy; @@ -59,3 +60,94 @@ pub use self::uint::{U256, U512}; pub fn hash(data: &[u8]) -> hash::H256 { tiny_keccak::keccak256(data).into() } + +/// Cool module. +pub mod ed25519 { + use crypto; + use rustc_hex::FromHex; + + #[derive(PartialEq, Clone)] + struct Public ([u8; 32]); + #[derive(Clone)] + struct Pair ([u8; 64]); + #[derive(Clone)] + struct Signature ([u8; 64]); + impl Pair { + pub fn from_seed(seed: &[u8]) -> Pair { + let (secret_public, public) = crypto::ed25519::keypair(seed); + assert_eq!(&secret_public[32..64], &public[0..32]); + Pair(secret_public) + } + pub fn sign(&self, message: &[u8]) -> Signature { + Signature(crypto::ed25519::signature(message, &self.0)) + } + pub fn public(&self) -> Public { + let mut r = [0u8; 32]; + r.copy_from_slice(&self.0[32..64]); + Public(r) + } + } + impl From<&'static str> for Public { + fn from(hex: &'static str) -> Self { + let mut r = [0u8; 32]; + r.copy_from_slice(&FromHex::from_hex(hex).unwrap()[0..32]); + Public(r) + } + } + impl From<&'static str> for Pair { + fn from(hex: &'static str) -> Self { + let mut r = [0u8; 64]; + r.copy_from_slice(&FromHex::from_hex(hex).unwrap()[0..64]); + Pair(r) + } + } + impl From<&'static str> for Signature { + fn from(hex: &'static str) -> Self { + let mut r = [0u8; 64]; + r.copy_from_slice(&FromHex::from_hex(hex).unwrap()[0..64]); + Signature(r) + } + } + + impl PartialEq for Signature { + fn eq(&self, other: &Signature) -> bool { + self.0.iter().eq(other.0.iter()) + } + } + + impl PartialEq for Pair { + fn eq(&self, other: &Pair) -> bool { + self.0.iter().eq(other.0.iter()) + } + } + + impl Signature { + fn verify(&self, message: &[u8], public: &Public) -> bool { + crypto::ed25519::verify(message, &public.0, &self.0) + } + } + + #[cfg(test)] + mod test { + use super::*; + + #[test] + fn test_vector_should_work() { + let pair: Pair = "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a".into(); + let public = pair.public(); + let message = b""; + let signature: Signature = "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b".into(); + assert!(&pair.sign(&message[..]) == &signature); + assert!(signature.verify(&message[..], &public)); + } + + #[test] + fn generated_pair_should_work() { + let pair = Pair::from_seed(b"test"); + let public = pair.public(); + let message = b"Something important"; + let signature = pair.sign(&message[..]); + assert!(signature.verify(&message[..], &public)); + } + } +} From 3c67ac115b305f77019df4f000ce13e5a6407d3a Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Wed, 17 Jan 2018 18:12:06 +0100 Subject: [PATCH 042/112] fix unsafety hole in environmental using function --- substrate/environmental/src/lib.rs | 80 ++++++++++++++++-------------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/substrate/environmental/src/lib.rs b/substrate/environmental/src/lib.rs index 239a2fb90f..18dc10d10f 100644 --- a/substrate/environmental/src/lib.rs +++ b/substrate/environmental/src/lib.rs @@ -44,10 +44,12 @@ pub use std::cell::RefCell; use std::thread::LocalKey; +// invoking this function asserts that T and S are both instantiations +// of the same lifetime-parametric type. #[doc(hidden)] -pub fn using<'a, T: 'a, R, S, F: FnOnce() -> R>( +pub unsafe fn using R>( global: &'static LocalKey>, - protected: &'a mut T, + protected: &mut T, f: F ) -> R { // store the `protected` reference as a pointer so we can provide it to logic running within @@ -57,19 +59,22 @@ pub fn using<'a, T: 'a, R, S, F: FnOnce() -> R>( // - that no other thread will use it; and // - that we do not use the original mutating reference while the pointer. // exists. - let original = global.with(|r| { - let mut b = r.borrow_mut(); - let o = *b; - *b = protected as *mut T as *mut S; - o - }); - let r = f(); - global.with(|r| *r.borrow_mut() = original); - r + global.with(|r| { + let original = { + let mut global = r.borrow_mut(); + ::std::mem::replace(&mut *global, protected as *mut _ as *mut S) + }; + + let res = f(); + *r.borrow_mut() = original; + res + }) } +// invoking this function asserts that T and S are both instantiations +// of the same lifetime-parametric type. #[doc(hidden)] -pub fn with<'r, R, S, T: 'r, F: FnOnce(&'r mut T) -> R>( +pub unsafe fn with R>( global: &'static LocalKey>, mutator: F, ) -> Option { @@ -78,9 +83,7 @@ pub fn with<'r, R, S, T: 'r, F: FnOnce(&'r mut T) -> R>( if *br != 0 as *mut S { // safe because it's only non-zero when it's being called from using, which // is holding on to the underlying reference (and not using it itself) safely. - unsafe { - Some(mutator(&mut *(*br as *mut S as *mut T))) - } + Some(mutator(&mut *(*br as *mut S as *mut T))) } else { None } @@ -130,32 +133,24 @@ macro_rules! decl { /// ``` #[macro_export] macro_rules! declare_simple { - ($name:ident : $t:tt) => { + ($name:ident : $t:ty) => { mod $name { #[allow(unused_imports)] use super::*; decl!(GLOBAL: $t); - pub fn using<'a: 'b, 'b, R, F: FnOnce() -> R, T: 'a>( - protected: &'b mut T, + pub fn using R>( + protected: &mut $t, f: F ) -> R { - $crate::using(&GLOBAL, protected, f) + unsafe { $crate::using(&GLOBAL, protected, f) } } - pub fn with FnOnce(&'r mut $t) -> R>( + pub fn with R>( f: F ) -> Option { - let dummy = (); - with_closed(f, &dummy) - } - - fn with_closed<'d: 'r, 'r, R, F: FnOnce(&'r mut $t) -> R>( - f: F, - _dummy: &'d (), - ) -> Option { - $crate::with(&GLOBAL, f) + unsafe { $crate::with(&GLOBAL, f) } } } } @@ -230,20 +225,33 @@ macro_rules! declare_generic { #[cfg(test)] mod tests { - declare_simple!(counter: u32); - - fn stuff() { - // do some stuff, accessing the named reference as desired. - counter::with(|value| *value += 1); - } #[test] fn simple_works() { + declare_simple!(counter: u32); + + let stuff = || counter::with(|value| *value += 1); + // declare a stack variable of the same type as our global declaration. let mut local = 41u32; + // call stuff, setting up our `counter` environment as a refrence to our local counter var. counter::using(&mut local, stuff); - println!("The answer is {:?}", local); // will print 42! + assert_eq!(local, 42); + stuff(); // safe! doesn't do anything. } + + #[test] + fn overwrite_with_lesser_lifetime() { + declare_simple!(items: Vec); + + let mut local_items = vec![1, 2, 3]; + items::using(&mut local_items, || { + let dies_at_end = vec![4, 5, 6]; + items::with(|items| *items = dies_at_end); + }); + + assert_eq!(local_items, vec![4, 5, 6]); + } } From 435c4ac71ae4e8006979f70152cf980760246ed6 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 17 Jan 2018 18:33:20 +0100 Subject: [PATCH 043/112] Introduce Ed25519 crypto. --- substrate/Cargo.lock | 85 ++++++++++++++++----- substrate/ed25519.pk8 | Bin 0 -> 85 bytes substrate/pkcs8.key | 28 +++++++ substrate/primitives/Cargo.toml | 2 +- substrate/primitives/src/lib.rs | 127 ++++++++++++++++++++++++-------- 5 files changed, 191 insertions(+), 51 deletions(-) create mode 100644 substrate/ed25519.pk8 create mode 100644 substrate/pkcs8.key diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 524ec96570..ce227ffe4b 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -129,6 +129,15 @@ dependencies = [ "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "coco" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crunchy" version = "0.1.6" @@ -153,6 +162,11 @@ name = "dtoa" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "either" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "elastic-array" version = "0.9.0" @@ -706,12 +720,13 @@ dependencies = [ "fixed-hash 0.1.0 (git+https://github.com/paritytech/primitives.git)", "polkadot-serializer 0.1.0", "pretty_assertions 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "uint 0.1.0 (git+https://github.com/paritytech/primitives.git)", + "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -791,6 +806,26 @@ dependencies = [ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rayon" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon-core" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "redox_syscall" version = "0.1.31" @@ -829,6 +864,18 @@ dependencies = [ "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ring" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rlp" version = "0.2.1" @@ -852,18 +899,6 @@ dependencies = [ "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rust-crypto" -version = "0.2.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rustc-demangle" version = "0.1.5" @@ -874,11 +909,6 @@ name = "rustc-hex" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "rustc-serialize" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "rustc_version" version = "0.1.7" @@ -905,6 +935,11 @@ name = "scoped-tls" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "scopeguard" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "semver" version = "0.1.20" @@ -1150,6 +1185,11 @@ dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "untrusted" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "utf8-ranges" version = "1.0.0" @@ -1206,10 +1246,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b13a57efd6b30ecd6598ebdb302cca617930b5470647570468a65d12ef9719" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" "checksum clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1b8c532887f1a292d17de05ae858a8fe50a301e196f9ef0ddb7ccd0d1d00f180" +"checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd" "checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" "checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" +"checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3" "checksum elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "258ff6a9a94f648d0379dbd79110e057edbb53eb85cc237e33eadf8e5a30df85" "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" @@ -1265,20 +1307,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum pretty_assertions 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94b6bbc8a323d89a019c4cdde21850522fb8405e97add70827177fc2f86c1495" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6475140dfd8655aeb72e1fd4b7a1cc1c202be65d71669476e392fe62532b9edd" +"checksum rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b614fe08b6665cb9a231d07ac1364b0ef3cb3698f1239ee0c4c3a88a524f54c8" +"checksum rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e64b609139d83da75902f88fd6c01820046840a18471e4dfcd5ac7c0f46bea53" "checksum redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "8dde11f18c108289bef24469638a04dce49da56084f2d50618b226e47eb04509" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" "checksum relay 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f301bafeb60867c85170031bdb2fcf24c8041f33aee09e7b116a58d4e9f781c5" +"checksum ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6f7d28b30a72c01b458428e0ae988d4149c20d902346902be881e3edc4bb325c" "checksum rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "babe6fce20c0ca9b1582998734c4569082d0ad08e43772a1c6c40aef4f106ef9" -"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" "checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" "checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e" -"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" "checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" +"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" "checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" @@ -1310,6 +1354,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" diff --git a/substrate/ed25519.pk8 b/substrate/ed25519.pk8 new file mode 100644 index 0000000000000000000000000000000000000000..57a8e9f84df1dc3175d02132f88bf7d03563ed8a GIT binary patch literal 85 zcmV-b0IL5mQvv}2Fa-t!D`jv5A_O2jp9~yh%qqhDL7XlV#y11mAEmT)YK|2S8mY`X rKcB~;BLg7-wIOt@fg3EC6j=CGA>0MTxofFio@CXjjO!~zYbh_!erz9j literal 0 HcmV?d00001 diff --git a/substrate/pkcs8.key b/substrate/pkcs8.key new file mode 100644 index 0000000000..250fbac646 --- /dev/null +++ b/substrate/pkcs8.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDMpfNjaigc9FKC +8owWoKvAua3O1es2CB7Gq6pFI4Ctv34Wt5XSk83XkSXLOsf2ib1zCpzLUQSVLtH1 +c05uTH6rXLmjbH3lFOUCqD41dIveqo72sekHnYjS23ME2v5JCkg9YFmn32FffHGt +2Uaho+MQZWbpT3SD5tKRdaUUx1f/i16oB4Fnk8zCdQ7NPFru+WUV0cvQnK3rOpOo +KbK59Jo04bHmf/EPeVmxonwt/nmAJRUemuQXPl1cH8sk+t6Bxxp9FLzX6rtmpGDk +mBwrYBNC5auT3L1V2xabI2TKobd/qa+9/Sz41PeHsYLX/cu9Iplvj+LU85gYwv5d +kjvMEI7pAgMBAAECggEBAID7z21HSUUGkMLL0JOqbNYpsWx906PYdl1NcSHmgIIC +AZyb1ShF1CUb7LAsuj+fDPLnK2/R/otwWRDUvggy2ltzM+XWyXqLMtP76kmSzV1o +Lnc6Jt+P4N7VRac3x7GNc36LrbZqylp+er/SA/x46PI6lyRR2eQQpYLcnVF9Wu9K +bbTQ9nH+hxJiRG85GXKjeFkIj7PXBYAiYYcgiPF1RfB3o2R0cXZI24Y5/Ufc3OKg +Jws/VsTIzoxoLd3u6rDKX/N40/VBrGqv76HFqVwgnbxeG+i6HZNIAvZn+6m3a6l5 +APIZp7FfLJ1vZaHP7S7GeNmcz+eJ9Y/FanItohJGfqECgYEA5d17o9Ol3H+6wkQk +a3LU03NfvcdU5TqTOGvzx6yGGASjlByZWb7rMsRMyQ/wP60j+2Hd/G4rXbkF6vee +5uen7geJ6bzhUev1nd1NDcVdZay8x0r3huePUV96k+wU1IrOZrZddlqPyUJMctDy +VbwbDPM0saGx0xIlx/JOC1kEEr0CgYEA4+p/TSEq9DWH5QaMlVxBp48HY4Yrv/gQ +UmNUbCyd7J21Re+7cY3ZGF5IoC2l4K4yPM6ovNipkX9WDZrw8T68sD8yTQzL/tDE +CuXxG+X0b81k5UiZBFIGXiBb8JpoHRKNNGjZTZyBNhOKc902oKoNyTKILX3qI/aL +M2v/SELm5Z0CgYEAx+XZnPn09pF5t3GM/ogpPw3Jh/+t+376AooWwWFuZ7q5Cpfo +YFygq1B8uimLM8T9UqKkat7gBaxe0hyvanyw1FZoAAXLKPP7cGLAnKYzd7VFoka2 +hfIf95MBxVv8LW3c2wPiuYc+HbbzRrIg3KAuIg/qlkNYoobYpk44wrOR0D0CgYB0 +RNeGaGo6ROi7nHixZWwU57FUQ0kkWI8zCHsz6Br0b4vfTqooBr3+YXLZTBA4K4Vz +YdXQ6RKwJ+6laCqMV334x3SIvAOBTc0E5kL3AXuOYZCcK0nsW0/mSsm8V3jPg/xH +BUn9/t4n0RYrf2lz0uzPfBjeZELC7+4ZYHnNyltyPQKBgQCvT40UwZ5yHAt3leWG +stGRTkbupenh2z23hXY0Cio8Zqa7KE5jBWdF4uu27ScK4rhFdS1sgQJFghj6SxRO +VT5PQuRP9ETJIVwNgNQbAxbfeg8DADKGAWX9W5r//WlW1xH0/tSAxX6Pp/IiT9or +cRljrhP8zW6qhj3BKjdivPDgPw== +-----END PRIVATE KEY----- diff --git a/substrate/primitives/Cargo.toml b/substrate/primitives/Cargo.toml index 3e2877e073..045afba827 100644 --- a/substrate/primitives/Cargo.toml +++ b/substrate/primitives/Cargo.toml @@ -11,8 +11,8 @@ serde = "1.0" serde_derive = "1.0" tiny-keccak = "1.3" uint = { git = "https://github.com/paritytech/primitives.git" } -rust-crypto = "0.2.36" ring = "0.12" +untrusted = "0.5" [dev-dependencies] polkadot-serializer = { path = "../serializer", version = "0.1" } diff --git a/substrate/primitives/src/lib.rs b/substrate/primitives/src/lib.rs index ad4c6efd58..cd166f0a54 100644 --- a/substrate/primitives/src/lib.rs +++ b/substrate/primitives/src/lib.rs @@ -21,7 +21,8 @@ extern crate rustc_hex; extern crate serde; extern crate tiny_keccak; -extern crate crypto; +extern crate ring; +extern crate untrusted; #[macro_use] extern crate crunchy; @@ -63,30 +64,85 @@ pub fn hash(data: &[u8]) -> hash::H256 { /// Cool module. pub mod ed25519 { - use crypto; + use untrusted; + use ring::{rand, signature}; use rustc_hex::FromHex; - #[derive(PartialEq, Clone)] - struct Public ([u8; 32]); + struct HexDisplay<'a>(&'a [u8]); + + impl<'a> ::std::fmt::Display for HexDisplay<'a> { + fn fmt(&self, fmtr: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { + for byte in self.0 { + try!( fmtr.write_fmt(format_args!("{:02x}", byte))); + } + Ok(()) + } + } + + /// A public key. + #[derive(PartialEq, Clone, Debug)] + pub struct Public ([u8; 32]); + + /// A key pair. + pub struct Pair(signature::Ed25519KeyPair); + + /// A signature. #[derive(Clone)] - struct Pair ([u8; 64]); - #[derive(Clone)] - struct Signature ([u8; 64]); + pub struct Signature ([u8; 64]); + impl Pair { - pub fn from_seed(seed: &[u8]) -> Pair { - let (secret_public, public) = crypto::ed25519::keypair(seed); - assert_eq!(&secret_public[32..64], &public[0..32]); - Pair(secret_public) + /// Generate new secure (random) key pair. + pub fn new() -> Pair { + let rng = rand::SystemRandom::new(); + let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng).unwrap(); + Pair(signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8_bytes)).unwrap()) } + /// Make a new key pair from a seed phrase. + pub fn from_seed(seed: &[u8; 32]) -> Pair { + Pair(signature::Ed25519KeyPair::from_seed_unchecked(untrusted::Input::from(&seed[..])).unwrap()) + } + /// Make a new key pair from the raw secret. + pub fn from_secret(secret: &[u8; 32]) -> Pair { + let mut pkcs8_bytes = FromHex::from_hex("302e020100300506032b657004220420").unwrap(); + pkcs8_bytes.extend_from_slice(&secret[..]); + Pair(signature::Ed25519KeyPair::from_pkcs8_maybe_unchecked(untrusted::Input::from(&pkcs8_bytes)).unwrap()) + } + /// Make a new key pair from the raw secret and public key (it will check to make sure + /// they correspond to each other). + pub fn from_both(secret_public: &[u8; 64]) -> Option { + let mut pkcs8_bytes = FromHex::from_hex("3053020101300506032b657004220420").unwrap(); + pkcs8_bytes.extend_from_slice(&secret_public[0..32]); + pkcs8_bytes.extend_from_slice(&[0xa1u8, 0x23, 0x03, 0x21, 0x00]); + pkcs8_bytes.extend_from_slice(&secret_public[32..64]); + signature::Ed25519KeyPair::from_pkcs8_maybe_unchecked(untrusted::Input::from(&pkcs8_bytes)).ok().map(Pair) + } + /// Sign a message. pub fn sign(&self, message: &[u8]) -> Signature { - Signature(crypto::ed25519::signature(message, &self.0)) + let mut r = [0u8; 64]; + r.copy_from_slice(self.0.sign(message).as_ref()); + Signature(r) } + /// Get the public key. pub fn public(&self) -> Public { let mut r = [0u8; 32]; - r.copy_from_slice(&self.0[32..64]); + let pk = self.0.public_key_bytes(); + r.copy_from_slice(pk); Public(r) } } + impl Signature { + /// Verify a message. + pub fn verify(&self, message: &[u8], public: &Public) -> bool { + let peer_public_key = untrusted::Input::from(&public.0[..]); + let msg = untrusted::Input::from(message); + let sig = untrusted::Input::from(&self.0[..]); + + match signature::verify(&signature::ED25519, peer_public_key, msg, sig) { + Ok(_) => true, + _ => false, + } + } + } impl From<&'static str> for Public { fn from(hex: &'static str) -> Self { let mut r = [0u8; 32]; @@ -96,9 +152,22 @@ pub mod ed25519 { } impl From<&'static str> for Pair { fn from(hex: &'static str) -> Self { - let mut r = [0u8; 64]; - r.copy_from_slice(&FromHex::from_hex(hex).unwrap()[0..64]); - Pair(r) + let data = FromHex::from_hex(hex).expect("Key pair given is static so hex should be good."); + match data.len() { + 32 => { + let mut r = [0u8; 32]; + r.copy_from_slice(&data[0..32]); + Pair::from_secret(&r) + } + 64 => { + let mut r = [0u8; 64]; + r.copy_from_slice(&data[0..64]); + Pair::from_both(&r).expect("Key pair given is static so should be good.") + } + _ => { + panic!("Key pair given is static so should be correct length."); + } + } } } impl From<&'static str> for Signature { @@ -115,26 +184,15 @@ pub mod ed25519 { } } - impl PartialEq for Pair { - fn eq(&self, other: &Pair) -> bool { - self.0.iter().eq(other.0.iter()) - } - } - - impl Signature { - fn verify(&self, message: &[u8], public: &Public) -> bool { - crypto::ed25519::verify(message, &public.0, &self.0) - } - } - #[cfg(test)] mod test { use super::*; #[test] fn test_vector_should_work() { - let pair: Pair = "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a".into(); + let pair: Pair = "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60".into(); let public = pair.public(); + assert_eq!(public, "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a".into()); let message = b""; let signature: Signature = "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b".into(); assert!(&pair.sign(&message[..]) == &signature); @@ -143,7 +201,16 @@ pub mod ed25519 { #[test] fn generated_pair_should_work() { - let pair = Pair::from_seed(b"test"); + let pair = Pair::new(); + let public = pair.public(); + let message = b"Something important"; + let signature = pair.sign(&message[..]); + assert!(signature.verify(&message[..], &public)); + } + + #[test] + fn seeded_pair_should_work() { + let pair = Pair::from_seed(b"12345678901234567890123456789012"); let public = pair.public(); let message = b"Something important"; let signature = pair.sign(&message[..]); From 6360a56e725bd8b4026c587db3ea5dc02b9f4076 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 17 Jan 2018 18:34:40 +0100 Subject: [PATCH 044/112] Repotting. --- substrate/primitives/src/ed25519.rs | 155 +++++++++++++++++++++++++++ substrate/primitives/src/lib.rs | 158 +--------------------------- 2 files changed, 156 insertions(+), 157 deletions(-) create mode 100644 substrate/primitives/src/ed25519.rs diff --git a/substrate/primitives/src/ed25519.rs b/substrate/primitives/src/ed25519.rs new file mode 100644 index 0000000000..676f8ef266 --- /dev/null +++ b/substrate/primitives/src/ed25519.rs @@ -0,0 +1,155 @@ +//! Simple Ed25519 API. + +use untrusted; +use ring::{rand, signature}; +use rustc_hex::FromHex; + +struct HexDisplay<'a>(&'a [u8]); + +impl<'a> ::std::fmt::Display for HexDisplay<'a> { + fn fmt(&self, fmtr: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { + for byte in self.0 { + try!( fmtr.write_fmt(format_args!("{:02x}", byte))); + } + Ok(()) + } +} + +/// A public key. +#[derive(PartialEq, Clone, Debug)] +pub struct Public ([u8; 32]); + +/// A key pair. +pub struct Pair(signature::Ed25519KeyPair); + +/// A signature. +#[derive(Clone)] +pub struct Signature ([u8; 64]); + +impl Pair { + /// Generate new secure (random) key pair. + pub fn new() -> Pair { + let rng = rand::SystemRandom::new(); + let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng).unwrap(); + Pair(signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8_bytes)).unwrap()) + } + /// Make a new key pair from a seed phrase. + pub fn from_seed(seed: &[u8; 32]) -> Pair { + Pair(signature::Ed25519KeyPair::from_seed_unchecked(untrusted::Input::from(&seed[..])).unwrap()) + } + /// Make a new key pair from the raw secret. + pub fn from_secret(secret: &[u8; 32]) -> Pair { + let mut pkcs8_bytes = FromHex::from_hex("302e020100300506032b657004220420").unwrap(); + pkcs8_bytes.extend_from_slice(&secret[..]); + Pair(signature::Ed25519KeyPair::from_pkcs8_maybe_unchecked(untrusted::Input::from(&pkcs8_bytes)).unwrap()) + } + /// Make a new key pair from the raw secret and public key (it will check to make sure + /// they correspond to each other). + pub fn from_both(secret_public: &[u8; 64]) -> Option { + let mut pkcs8_bytes = FromHex::from_hex("3053020101300506032b657004220420").unwrap(); + pkcs8_bytes.extend_from_slice(&secret_public[0..32]); + pkcs8_bytes.extend_from_slice(&[0xa1u8, 0x23, 0x03, 0x21, 0x00]); + pkcs8_bytes.extend_from_slice(&secret_public[32..64]); + signature::Ed25519KeyPair::from_pkcs8_maybe_unchecked(untrusted::Input::from(&pkcs8_bytes)).ok().map(Pair) + } + /// Sign a message. + pub fn sign(&self, message: &[u8]) -> Signature { + let mut r = [0u8; 64]; + r.copy_from_slice(self.0.sign(message).as_ref()); + Signature(r) + } + /// Get the public key. + pub fn public(&self) -> Public { + let mut r = [0u8; 32]; + let pk = self.0.public_key_bytes(); + r.copy_from_slice(pk); + Public(r) + } +} +impl Signature { + /// Verify a message. + pub fn verify(&self, message: &[u8], public: &Public) -> bool { + let peer_public_key = untrusted::Input::from(&public.0[..]); + let msg = untrusted::Input::from(message); + let sig = untrusted::Input::from(&self.0[..]); + + match signature::verify(&signature::ED25519, peer_public_key, msg, sig) { + Ok(_) => true, + _ => false, + } + } +} +impl From<&'static str> for Public { + fn from(hex: &'static str) -> Self { + let mut r = [0u8; 32]; + r.copy_from_slice(&FromHex::from_hex(hex).unwrap()[0..32]); + Public(r) + } +} +impl From<&'static str> for Pair { + fn from(hex: &'static str) -> Self { + let data = FromHex::from_hex(hex).expect("Key pair given is static so hex should be good."); + match data.len() { + 32 => { + let mut r = [0u8; 32]; + r.copy_from_slice(&data[0..32]); + Pair::from_secret(&r) + } + 64 => { + let mut r = [0u8; 64]; + r.copy_from_slice(&data[0..64]); + Pair::from_both(&r).expect("Key pair given is static so should be good.") + } + _ => { + panic!("Key pair given is static so should be correct length."); + } + } + } +} +impl From<&'static str> for Signature { + fn from(hex: &'static str) -> Self { + let mut r = [0u8; 64]; + r.copy_from_slice(&FromHex::from_hex(hex).unwrap()[0..64]); + Signature(r) + } +} + +impl PartialEq for Signature { + fn eq(&self, other: &Signature) -> bool { + self.0.iter().eq(other.0.iter()) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_vector_should_work() { + let pair: Pair = "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60".into(); + let public = pair.public(); + assert_eq!(public, "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a".into()); + let message = b""; + let signature: Signature = "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b".into(); + assert!(&pair.sign(&message[..]) == &signature); + assert!(signature.verify(&message[..], &public)); + } + + #[test] + fn generated_pair_should_work() { + let pair = Pair::new(); + let public = pair.public(); + let message = b"Something important"; + let signature = pair.sign(&message[..]); + assert!(signature.verify(&message[..], &public)); + } + + #[test] + fn seeded_pair_should_work() { + let pair = Pair::from_seed(b"12345678901234567890123456789012"); + let public = pair.public(); + let message = b"Something important"; + let signature = pair.sign(&message[..]); + assert!(signature.verify(&message[..], &public)); + } +} diff --git a/substrate/primitives/src/lib.rs b/substrate/primitives/src/lib.rs index cd166f0a54..fc26658200 100644 --- a/substrate/primitives/src/lib.rs +++ b/substrate/primitives/src/lib.rs @@ -48,6 +48,7 @@ pub mod hash; pub mod parachain; pub mod uint; pub mod validator; +pub mod ed25519; /// Alias to 160-bit hash when used in the context of an account address. pub type Address = hash::H160; @@ -61,160 +62,3 @@ pub use self::uint::{U256, U512}; pub fn hash(data: &[u8]) -> hash::H256 { tiny_keccak::keccak256(data).into() } - -/// Cool module. -pub mod ed25519 { - use untrusted; - use ring::{rand, signature}; - use rustc_hex::FromHex; - - struct HexDisplay<'a>(&'a [u8]); - - impl<'a> ::std::fmt::Display for HexDisplay<'a> { - fn fmt(&self, fmtr: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { - for byte in self.0 { - try!( fmtr.write_fmt(format_args!("{:02x}", byte))); - } - Ok(()) - } - } - - /// A public key. - #[derive(PartialEq, Clone, Debug)] - pub struct Public ([u8; 32]); - - /// A key pair. - pub struct Pair(signature::Ed25519KeyPair); - - /// A signature. - #[derive(Clone)] - pub struct Signature ([u8; 64]); - - impl Pair { - /// Generate new secure (random) key pair. - pub fn new() -> Pair { - let rng = rand::SystemRandom::new(); - let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng).unwrap(); - Pair(signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8_bytes)).unwrap()) - } - /// Make a new key pair from a seed phrase. - pub fn from_seed(seed: &[u8; 32]) -> Pair { - Pair(signature::Ed25519KeyPair::from_seed_unchecked(untrusted::Input::from(&seed[..])).unwrap()) - } - /// Make a new key pair from the raw secret. - pub fn from_secret(secret: &[u8; 32]) -> Pair { - let mut pkcs8_bytes = FromHex::from_hex("302e020100300506032b657004220420").unwrap(); - pkcs8_bytes.extend_from_slice(&secret[..]); - Pair(signature::Ed25519KeyPair::from_pkcs8_maybe_unchecked(untrusted::Input::from(&pkcs8_bytes)).unwrap()) - } - /// Make a new key pair from the raw secret and public key (it will check to make sure - /// they correspond to each other). - pub fn from_both(secret_public: &[u8; 64]) -> Option { - let mut pkcs8_bytes = FromHex::from_hex("3053020101300506032b657004220420").unwrap(); - pkcs8_bytes.extend_from_slice(&secret_public[0..32]); - pkcs8_bytes.extend_from_slice(&[0xa1u8, 0x23, 0x03, 0x21, 0x00]); - pkcs8_bytes.extend_from_slice(&secret_public[32..64]); - signature::Ed25519KeyPair::from_pkcs8_maybe_unchecked(untrusted::Input::from(&pkcs8_bytes)).ok().map(Pair) - } - /// Sign a message. - pub fn sign(&self, message: &[u8]) -> Signature { - let mut r = [0u8; 64]; - r.copy_from_slice(self.0.sign(message).as_ref()); - Signature(r) - } - /// Get the public key. - pub fn public(&self) -> Public { - let mut r = [0u8; 32]; - let pk = self.0.public_key_bytes(); - r.copy_from_slice(pk); - Public(r) - } - } - impl Signature { - /// Verify a message. - pub fn verify(&self, message: &[u8], public: &Public) -> bool { - let peer_public_key = untrusted::Input::from(&public.0[..]); - let msg = untrusted::Input::from(message); - let sig = untrusted::Input::from(&self.0[..]); - - match signature::verify(&signature::ED25519, peer_public_key, msg, sig) { - Ok(_) => true, - _ => false, - } - } - } - impl From<&'static str> for Public { - fn from(hex: &'static str) -> Self { - let mut r = [0u8; 32]; - r.copy_from_slice(&FromHex::from_hex(hex).unwrap()[0..32]); - Public(r) - } - } - impl From<&'static str> for Pair { - fn from(hex: &'static str) -> Self { - let data = FromHex::from_hex(hex).expect("Key pair given is static so hex should be good."); - match data.len() { - 32 => { - let mut r = [0u8; 32]; - r.copy_from_slice(&data[0..32]); - Pair::from_secret(&r) - } - 64 => { - let mut r = [0u8; 64]; - r.copy_from_slice(&data[0..64]); - Pair::from_both(&r).expect("Key pair given is static so should be good.") - } - _ => { - panic!("Key pair given is static so should be correct length."); - } - } - } - } - impl From<&'static str> for Signature { - fn from(hex: &'static str) -> Self { - let mut r = [0u8; 64]; - r.copy_from_slice(&FromHex::from_hex(hex).unwrap()[0..64]); - Signature(r) - } - } - - impl PartialEq for Signature { - fn eq(&self, other: &Signature) -> bool { - self.0.iter().eq(other.0.iter()) - } - } - - #[cfg(test)] - mod test { - use super::*; - - #[test] - fn test_vector_should_work() { - let pair: Pair = "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60".into(); - let public = pair.public(); - assert_eq!(public, "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a".into()); - let message = b""; - let signature: Signature = "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b".into(); - assert!(&pair.sign(&message[..]) == &signature); - assert!(signature.verify(&message[..], &public)); - } - - #[test] - fn generated_pair_should_work() { - let pair = Pair::new(); - let public = pair.public(); - let message = b"Something important"; - let signature = pair.sign(&message[..]); - assert!(signature.verify(&message[..], &public)); - } - - #[test] - fn seeded_pair_should_work() { - let pair = Pair::from_seed(b"12345678901234567890123456789012"); - let public = pair.public(); - let message = b"Something important"; - let signature = pair.sign(&message[..]); - assert!(signature.verify(&message[..], &public)); - } - } -} From 6b1153d9757f98d7a8d226bd319f52bb2bcbc215 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 17 Jan 2018 19:05:31 +0100 Subject: [PATCH 045/112] Add ed25519_verify external. --- substrate/executor/src/wasm_executor.rs | 19 +++++++++++++++++++ substrate/primitives/src/ed25519.rs | 22 ++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index 8597656c51..719343f8fa 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -27,6 +27,7 @@ use error::{Error, ErrorKind, Result}; use wasm_utils::{MemoryInstance, UserDefinedElements, AddModuleWithoutFullDependentInstance}; use tiny_keccak; +use primitives::ed25519; struct Heap { end: u32, @@ -148,6 +149,24 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, [0; 32] }; let _ = this.memory.set(out, &result); + }, + ext_ed25519_verify(msg_data: *const u8, msg_len: u32, sig_data: *const u8, pubkey_data: *const u8) -> u32 => { + (||{ + let mut sig = [0u8; 64]; + if let Err(_) = this.memory.get_into(sig_data, &mut sig[..]) { + return 0; + }; + let mut pubkey = [0u8; 32]; + if let Err(_) = this.memory.get_into(pubkey_data, &mut pubkey[..]) { + return 0; + }; + + if let Ok(msg) = this.memory.get(msg_data, msg_len as usize) { + if ed25519::Signature::from(sig).verify(&msg, &ed25519::Public::from(pubkey)) { 1 } else { 0 } + } else { + 0 + } + })() } => <'e, E: Externalities + 'e> ); diff --git a/substrate/primitives/src/ed25519.rs b/substrate/primitives/src/ed25519.rs index 676f8ef266..576d1a409a 100644 --- a/substrate/primitives/src/ed25519.rs +++ b/substrate/primitives/src/ed25519.rs @@ -26,6 +26,28 @@ pub struct Pair(signature::Ed25519KeyPair); #[derive(Clone)] pub struct Signature ([u8; 64]); +impl Signature { + pub fn from(data: [u8; 64]) -> Self { + Signature(data) + } + pub fn from_slice(data: &[u8]) -> Self { + let mut r = [0u8; 64]; + r.copy_from_slice(data); + Signature(r) + } +} + +impl Public { + pub fn from(data: [u8; 32]) -> Self { + Public(data) + } + pub fn from_slice(data: &[u8]) -> Self { + let mut r = [0u8; 32]; + r.copy_from_slice(data); + Public(r) + } +} + impl Pair { /// Generate new secure (random) key pair. pub fn new() -> Pair { From ec78b7244a6c8355257d7b0f01fc390f0d9cd28b Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 17 Jan 2018 19:17:34 +0100 Subject: [PATCH 046/112] Introduce Ed25519 verify as an external. --- substrate/native-runtime/support/src/lib.rs | 13 ++++++++++--- substrate/primitives/src/ed25519.rs | 11 +++++++++++ substrate/wasm-runtime/support/src/lib.rs | 11 +++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index a2fe13eb10..7f2de2d103 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -3,6 +3,9 @@ extern crate environmental; extern crate polkadot_state_machine; extern crate tiny_keccak; +use std::fmt; +use primitives::ed25519; + pub use std::vec::Vec; pub use std::rc::Rc; pub use std::cell::RefCell; @@ -11,7 +14,6 @@ pub use std::slice; pub use std::mem::{size_of, transmute, swap, uninitialized}; pub use polkadot_state_machine::Externalities; -use std::fmt; // TODO: use the real error, not NoError. @@ -63,9 +65,9 @@ pub fn storage_into(_key: &[u8]) -> Option { }).unwrap_or(None) } -pub fn set_storage(_key: &[u8], _value: &[u8]) { +pub fn set_storage(key: &[u8], value: &[u8]) { ext::with(|holder| - holder.ext.set_storage(_key.to_vec(), _value.to_vec()) + holder.ext.set_storage(key.to_vec(), value.to_vec()) ); } @@ -79,6 +81,11 @@ pub fn chain_id() -> u64 { /// Conduct a Keccak-256 hash of the given data. pub use tiny_keccak::keccak256; +/// Verify a ed25519 signature. +pub fn ed25519_verify(sig: &[u8; 64], msg: &[u8], pubkey: &[u8; 32]) -> bool { + ed25519::verify(&sig[..], msg, &pubkey[..]) +} + /// Execute the given closure with global function available whose functionality routes into the /// externalities `ext`. Forwards the value that the closure returns. pub fn with_externalities R>(ext: &mut Externalities, f: F) -> R { diff --git a/substrate/primitives/src/ed25519.rs b/substrate/primitives/src/ed25519.rs index 576d1a409a..58556b6669 100644 --- a/substrate/primitives/src/ed25519.rs +++ b/substrate/primitives/src/ed25519.rs @@ -15,6 +15,17 @@ impl<'a> ::std::fmt::Display for HexDisplay<'a> { } } +pub fn verify(sig: &[u8], message: &[u8], public: &[u8]) -> bool { + let public_key = untrusted::Input::from(public); + let msg = untrusted::Input::from(message); + let sig = untrusted::Input::from(sig); + + match signature::verify(&signature::ED25519, public_key, msg, sig) { + Ok(_) => true, + _ => false, + } +} + /// A public key. #[derive(PartialEq, Clone, Debug)] pub struct Public ([u8; 32]); diff --git a/substrate/wasm-runtime/support/src/lib.rs b/substrate/wasm-runtime/support/src/lib.rs index ae3feb14c9..9f75504513 100644 --- a/substrate/wasm-runtime/support/src/lib.rs +++ b/substrate/wasm-runtime/support/src/lib.rs @@ -30,6 +30,7 @@ extern "C" { fn ext_get_storage_into(key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32) -> u32; fn ext_chain_id() -> u64; fn ext_keccak256(data: *const u8, len: u32, out: *mut u8); + fn ext_ed25519_verify(msg_data: *const u8, msg_len: u32, sig_data: *const u8, pubkey_data: *const u8) -> u32; } pub fn storage(key: &[u8]) -> Vec { @@ -89,6 +90,16 @@ pub fn keccak256(data: &[u8]) -> [u8; 32] { } } +/// Verify a ed25519 signature. +pub fn ed25519_verify(sig: &[u8; 64], msg: &[u8], pubkey: &[u8; 32]) -> bool { + unsafe { + match ext_ed25519_verify(&msg[0], msg.len() as u32, &sig[0], &pubkey[0]) { + 0 => false, + _ => true, + } + } +} + pub trait Printable { fn print(self); } From 21ab1935e7816b7ecb627c6590f051e3c82dbf2b Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Wed, 17 Jan 2018 19:20:38 +0100 Subject: [PATCH 047/112] fix unsafety hole around unwinding --- substrate/environmental/src/lib.rs | 249 +++++++++++++++-------------- 1 file changed, 132 insertions(+), 117 deletions(-) diff --git a/substrate/environmental/src/lib.rs b/substrate/environmental/src/lib.rs index 18dc10d10f..ef5b5967be 100644 --- a/substrate/environmental/src/lib.rs +++ b/substrate/environmental/src/lib.rs @@ -16,7 +16,7 @@ //! Safe global references to stack variables. //! -//! Set up a global reference with declare_simple! macro giving it a name and type. +//! Set up a global reference with environmental! macro giving it a name and type. //! Use the `using` function scoped under its name to name a reference and call a function that //! takes no parameters yet can access said reference through the similarly placed `with` function. //! @@ -25,7 +25,7 @@ //! ``` //! #[macro_use] extern crate environmental; //! // create a place for the global reference to exist. -//! declare_simple!(counter: u32); +//! environmental!(counter: u32); //! fn stuff() { //! // do some stuff, accessing the named reference as desired. //! counter::with(|i| *i += 1); @@ -40,15 +40,12 @@ //! } //! ``` -#[doc(hidden)] -pub use std::cell::RefCell; +use std::cell::RefCell; use std::thread::LocalKey; -// invoking this function asserts that T and S are both instantiations -// of the same lifetime-parametric type. #[doc(hidden)] -pub unsafe fn using R>( - global: &'static LocalKey>, +pub fn using R>( + global: &'static LocalKey>>, protected: &mut T, f: F ) -> R { @@ -62,60 +59,66 @@ pub unsafe fn using R>( global.with(|r| { let original = { let mut global = r.borrow_mut(); - ::std::mem::replace(&mut *global, protected as *mut _ as *mut S) + ::std::mem::replace(&mut *global, Some(protected as _)) }; - let res = f(); - *r.borrow_mut() = original; - res + // even if `f` panics the original will be replaced. + struct ReplaceOriginal<'a, T: 'a + ?Sized> { + original: Option<*mut T>, + global: &'a RefCell>, + } + + impl<'a, T: 'a + ?Sized> Drop for ReplaceOriginal<'a, T> { + fn drop(&mut self) { + *self.global.borrow_mut() = self.original.take(); + } + } + + let _guard = ReplaceOriginal { + original, + global: r, + }; + + f() }) } -// invoking this function asserts that T and S are both instantiations -// of the same lifetime-parametric type. #[doc(hidden)] -pub unsafe fn with R>( - global: &'static LocalKey>, +pub fn with R>( + global: &'static LocalKey>>, mutator: F, ) -> Option { - global.with(|r| { - let br = r.borrow_mut(); - if *br != 0 as *mut S { - // safe because it's only non-zero when it's being called from using, which - // is holding on to the underlying reference (and not using it itself) safely. - Some(mutator(&mut *(*br as *mut S as *mut T))) - } else { - None + global.with(|r| unsafe { + let ptr = r.borrow_mut(); + match *ptr { + Some(ptr) => { + // safe because it's only non-zero when it's being called from using, which + // is holding on to the underlying reference (and not using it itself) safely. + Some(mutator(&mut *ptr)) + } + None => None, } }) } -#[doc(hidden)] -#[macro_export] -macro_rules! decl { - ($name:ident : $t:ty) => { - thread_local! { - static $name: $crate::RefCell<*mut $t> = $crate::RefCell::new(0 as *mut $t); - } - } -} - /// Declare a new global reference module whose underlying value does not contain references. /// /// Will create a module of a given name that contains two functions: -/// * `pub fn using<'a: 'b, 'b, R, F: FnOnce() -> R, T: 'a>(protected: &'b mut T, f: F) -> R` +/// * `pub fn using R>(protected: &mut $t, f: F) -> R` /// This executes `f`, returning its value. During the call, the module's reference is set to /// be equal to `protected`. -/// * `pub fn with FnOnce(&'r mut $t<'t>) -> R>(f: F) -> Option` +/// * `pub fn with R>(f: F) -> Option` /// This executes `f`, returning `Some` of its value if called from code that is being executed /// as part of a `using` call. If not, it returns `None`. `f` is provided with one argument: the /// same reference as provided to the most recent `using` call. /// /// # Examples /// -/// ``` +/// Initializing the global context with a given value. +/// +/// ```rust /// #[macro_use] extern crate environmental; -/// declare_simple!(counter: u32); +/// environmental!(counter: u32); /// fn main() { /// let mut counter_value = 41u32; /// counter::using(&mut counter_value, || { @@ -131,96 +134,55 @@ macro_rules! decl { /// println!("The answer is {:?}", counter_value); // 42 /// } /// ``` +/// +/// Roughly the same, but with a trait object: +/// +/// ```rust +/// #[macro_use] extern crate environmental; +/// +/// trait Increment { fn increment(&mut self); } +/// +/// impl Increment for i32 { +/// fn increment(&mut self) { *self += 1 } +/// } +/// +/// environmental!(val: Increment + 'static); +/// +/// fn main() { +/// let mut local = 0i32; +/// val::using(&mut local, || { +/// val::with(|v| for _ in 0..5 { v.increment() }); +/// }); +/// +/// assert_eq!(local, 5); +/// } +/// ``` #[macro_export] -macro_rules! declare_simple { +macro_rules! environmental { ($name:ident : $t:ty) => { - mod $name { - #[allow(unused_imports)] - use super::*; + #[allow(non_camel_case_types)] + struct $name { __private_field: () } - decl!(GLOBAL: $t); + thread_local!(static GLOBAL: ::std::cell::RefCell> + = ::std::cell::RefCell::new(None)); + + impl $name { + #[allow(unused_imports)] pub fn using R>( protected: &mut $t, f: F ) -> R { - unsafe { $crate::using(&GLOBAL, protected, f) } + $crate::using(&GLOBAL, protected, f) } pub fn with R>( f: F ) -> Option { - unsafe { $crate::with(&GLOBAL, f) } + $crate::with(&GLOBAL, |x| f(x)) } } - } -} - -/// Declare a new global reference module whose underlying value is generic over a reference. -/// -/// Will create a module of a given name that contains two functions: -/// -/// * `pub fn using<'a: 'b, 'b, R, F: FnOnce() -> R, T: 'a>(protected: &'b mut T, f: F) -> R` -/// This executes `f`, returning its value. During the call, the module's reference is set to -/// be equal to `protected`. -/// * `pub fn with FnOnce(&'r mut $t<'t>) -> R>(f: F) -> Option` -/// This executes `f`, returning `Some` of its value if called from code that is being executed -/// as part of a `using` call. If not, it returns `None`. `f` is provided with one argument: the -/// same reference as provided to the most recent `using` call. -/// -/// # Examples -/// -/// ``` -/// #[macro_use] extern crate environmental; -/// // a type that we want to reference from a temp global; it has a reference in it. -/// struct WithReference<'a> { answer_ref: &'a mut u32, } -/// // create a place for the global reference to exist. -/// declare_generic!(counter: WithReference); -/// fn stuff() { -/// // do some stuff, accessing the named reference as desired. -/// counter::with(|i| *i.answer_ref += 1); -/// } -/// fn main() { -/// // declare a stack variable of the same type as our global declaration. -/// let mut answer = 41u32; -/// { -/// let mut ref_struct = WithReference { answer_ref: &mut answer, }; -/// counter::using(&mut ref_struct, stuff); -/// } -/// println!("The answer is {:?}", answer); // will print 42! -/// } -/// ``` -#[macro_export] -macro_rules! declare_generic { - ($name:ident : $t:tt) => { - mod $name { - #[allow(unused_imports)] - use super::*; - - decl!(GLOBAL: $t<'static> ); - - pub fn using<'a: 'b, 'b, R, F: FnOnce() -> R, T: 'a>( - protected: &'b mut T, - f: F - ) -> R { - $crate::using(&GLOBAL, protected, f) - } - - pub fn with FnOnce(&'r mut $t<'t>) -> R>( - f: F - ) -> Option { - let dummy = (); - with_closed(f, &dummy) - } - - fn with_closed<'d: 't, 't: 'r, 'r, R, F: FnOnce(&'r mut $t<'t>) -> R>( - f: F, - _dummy: &'d (), - ) -> Option { - $crate::with(&GLOBAL, f) - } - } - } + }; } #[cfg(test)] @@ -228,9 +190,9 @@ mod tests { #[test] fn simple_works() { - declare_simple!(counter: u32); + environmental!(counter: u32); - let stuff = || counter::with(|value| *value += 1); + fn stuff() { counter::with(|value| *value += 1); }; // declare a stack variable of the same type as our global declaration. let mut local = 41u32; @@ -238,13 +200,12 @@ mod tests { // call stuff, setting up our `counter` environment as a refrence to our local counter var. counter::using(&mut local, stuff); assert_eq!(local, 42); - stuff(); // safe! doesn't do anything. } #[test] fn overwrite_with_lesser_lifetime() { - declare_simple!(items: Vec); + environmental!(items: Vec); let mut local_items = vec![1, 2, 3]; items::using(&mut local_items, || { @@ -254,4 +215,58 @@ mod tests { assert_eq!(local_items, vec![4, 5, 6]); } + + #[test] + fn declare_with_trait_object() { + trait Foo { + fn get(&self) -> i32; + fn set(&mut self, x: i32); + } + + impl Foo for i32 { + fn get(&self) -> i32 { *self } + fn set(&mut self, x: i32) { *self = x } + } + + environmental!(foo: Foo + 'static); + + fn stuff() { + foo::with(|value| { + let new_val = value.get() + 1; + value.set(new_val); + }); + } + + let mut local = 41i32; + foo::using(&mut local, stuff); + + assert_eq!(local, 42); + + stuff(); // doesn't do anything. + } + + #[test] + fn unwind_recursive() { + use std::panic; + + environmental!(items: Vec); + + let panicked = panic::catch_unwind(|| { + let mut local_outer = vec![1, 2, 3]; + + items::using(&mut local_outer, || { + let mut local_inner = vec![4, 5, 6]; + items::using(&mut local_inner, || { + panic!("are you unsafe?"); + }) + }); + }).is_err(); + + assert!(panicked); + + let mut was_cleared = true; + items::with(|_items| was_cleared = false); + + assert!(was_cleared); + } } From 3b850c7ed1208268b248782d001e1438d34eb69b Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 17 Jan 2018 19:20:48 +0100 Subject: [PATCH 048/112] Compile fixes. --- substrate/Cargo.lock | 1 + substrate/native-runtime/support/Cargo.toml | 1 + substrate/native-runtime/support/src/lib.rs | 1 + 3 files changed, 3 insertions(+) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index ce227ffe4b..f886c60be5 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -895,6 +895,7 @@ dependencies = [ "environmental 0.1.0", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "polkadot-primitives 0.1.0", "polkadot-state-machine 0.1.0", "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/substrate/native-runtime/support/Cargo.toml b/substrate/native-runtime/support/Cargo.toml index 185dea5f92..f576037bd2 100644 --- a/substrate/native-runtime/support/Cargo.toml +++ b/substrate/native-runtime/support/Cargo.toml @@ -12,3 +12,4 @@ parking_lot = "0.5" polkadot-state-machine = { path = "../../state_machine" , version = "0.1" } environmental = { path = "../../environmental", version = "0.1.0" } tiny-keccak = "1.3" +polkadot-primitives = { path = "../../primitives", version = "0.1.0" } diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index 7f2de2d103..02a4b8b2ed 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -2,6 +2,7 @@ extern crate environmental; extern crate polkadot_state_machine; extern crate tiny_keccak; +extern crate polkadot_primitives as primitives; use std::fmt; use primitives::ed25519; From 3ed67849117f2bc584c939e3e4c6670f2e487d29 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Wed, 17 Jan 2018 19:27:38 +0100 Subject: [PATCH 049/112] use new environmental API --- substrate/native-runtime/support/src/lib.rs | 29 +++++++++------------ 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index a2fe13eb10..d929b699de 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -21,21 +21,17 @@ impl fmt::Display for NoError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "") } } -pub struct ExternalitiesHolder<'a> { - ext: &'a mut Externalities, -} - -declare_generic!(ext : ExternalitiesHolder); +environmental!(ext : Externalities + 'static); pub fn storage(key: &[u8]) -> Vec { - ext::with(|holder| holder.ext.storage(key).ok().map(|s| s.to_vec())) + ext::with(|ext| ext.storage(key).ok().map(|s| s.to_vec())) .unwrap_or(None) .unwrap_or_else(|| vec![]) } pub fn read_storage(key: &[u8], value_out: &mut [u8]) -> usize { - ext::with(|holder| { - if let Ok(value) = holder.ext.storage(key) { + ext::with(|ext| { + if let Ok(value) = ext.storage(key) { let written = ::std::cmp::min(value.len(), value_out.len()); value_out[0..written].copy_from_slice(&value[0..written]); value.len() @@ -48,8 +44,8 @@ pub fn read_storage(key: &[u8], value_out: &mut [u8]) -> usize { pub fn storage_into(_key: &[u8]) -> Option { let size = size_of::(); - ext::with(|holder| { - if let Ok(value) = holder.ext.storage(_key) { + ext::with(|ext| { + if let Ok(value) = ext.storage(_key) { if value.len() == size { unsafe { let mut result: T = std::mem::uninitialized(); @@ -64,15 +60,15 @@ pub fn storage_into(_key: &[u8]) -> Option { } pub fn set_storage(_key: &[u8], _value: &[u8]) { - ext::with(|holder| - holder.ext.set_storage(_key.to_vec(), _value.to_vec()) + ext::with(|ext| + ext.set_storage(_key.to_vec(), _value.to_vec()) ); } /// The current relay chain identifier. pub fn chain_id() -> u64 { - ext::with(|holder| - holder.ext.chain_id() + ext::with(|ext| + ext.chain_id() ).unwrap_or(0) } @@ -81,9 +77,8 @@ pub use tiny_keccak::keccak256; /// Execute the given closure with global function available whose functionality routes into the /// externalities `ext`. Forwards the value that the closure returns. -pub fn with_externalities R>(ext: &mut Externalities, f: F) -> R { - let mut h = ExternalitiesHolder { ext }; - ext::using(&mut h, f) +pub fn with_externalities R>(ext: &mut (Externalities + 'static), f: F) -> R { + ext::using(ext, f) } #[macro_export] From 07c14104f70a277bc5a866346e615e4fdafbe6cb Mon Sep 17 00:00:00 2001 From: Gav Date: Thu, 18 Jan 2018 12:31:34 +0100 Subject: [PATCH 050/112] Tests for ed25519 verify. --- substrate/executor/src/wasm_executor.rs | 15 +++++++++++ substrate/primitives/src/ed25519.rs | 24 ++++++++++++++++++ substrate/wasm-runtime/support/src/lib.rs | 11 +++----- .../release/runtime_test.compact.wasm | Bin 843 -> 1193 bytes .../release/runtime_test.wasm | Bin 960 -> 1281 bytes substrate/wasm-runtime/test/src/lib.rs | 13 ++++++++-- 6 files changed, 54 insertions(+), 9 deletions(-) diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index 719343f8fa..07056b1df7 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -273,4 +273,19 @@ mod tests { FromHex::from_hex("ecd0e108a98e192af1d2c25055f4e3bed784b5c877204e73219a5203251feaab").unwrap() ); } + + #[test] + fn ed25519_verify_should_work() { + let mut ext = TestExternalities::default(); + let test_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); + let key = ed25519::Pair::from_seed(&tiny_keccak::keccak256(b"test")); + let sig = key.sign(b"all ok!"); + let mut calldata = vec![]; + calldata.extend_from_slice(key.public().as_ref()); + calldata.extend_from_slice(sig.as_ref()); + assert_eq!( + WasmExecutor.call(&mut ext, &test_code[..], "test_ed25519_verify", &CallData(calldata)).unwrap(), + vec![1] + ); + } } diff --git a/substrate/primitives/src/ed25519.rs b/substrate/primitives/src/ed25519.rs index 58556b6669..f6a02a735b 100644 --- a/substrate/primitives/src/ed25519.rs +++ b/substrate/primitives/src/ed25519.rs @@ -48,6 +48,18 @@ impl Signature { } } +impl AsRef<[u8; 64]> for Signature { + fn as_ref(&self) -> &[u8; 64] { + &self.0 + } +} + +impl AsRef<[u8]> for Signature { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} + impl Public { pub fn from(data: [u8; 32]) -> Self { Public(data) @@ -59,6 +71,18 @@ impl Public { } } +impl AsRef<[u8; 32]> for Public { + fn as_ref(&self) -> &[u8; 32] { + &self.0 + } +} + +impl AsRef<[u8]> for Public { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} + impl Pair { /// Generate new secure (random) key pair. pub fn new() -> Pair { diff --git a/substrate/wasm-runtime/support/src/lib.rs b/substrate/wasm-runtime/support/src/lib.rs index 9f75504513..57606a3f1b 100644 --- a/substrate/wasm-runtime/support/src/lib.rs +++ b/substrate/wasm-runtime/support/src/lib.rs @@ -91,13 +91,10 @@ pub fn keccak256(data: &[u8]) -> [u8; 32] { } /// Verify a ed25519 signature. -pub fn ed25519_verify(sig: &[u8; 64], msg: &[u8], pubkey: &[u8; 32]) -> bool { - unsafe { - match ext_ed25519_verify(&msg[0], msg.len() as u32, &sig[0], &pubkey[0]) { - 0 => false, - _ => true, - } - } +pub fn ed25519_verify(sig: &[u8], msg: &[u8], pubkey: &[u8]) -> bool { + sig.len() != 64 || pubkey.len() != 32 || unsafe { + ext_ed25519_verify(&msg[0], msg.len() as u32, &sig[0], &pubkey[0]) + } == 0 } pub trait Printable { diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm index f4c438ec106e2dad2e662f47d1abbb293e62178c..e4431c2606a6e09c8aabfc4baf815ebe5c296a54 100644 GIT binary patch literal 1193 zcmZ8g%Tg0T6uteJN755$kOh{To>_&3B~p-}ZgQ!jTv_GXO)?|{&V)=-$$(;&h6SbN zhq%OV@Ke~h_Y=H5lLR!6>iask&wVt+vk?OTwqNVXIepl?$L7!zm1qwj16jG1$`G(J z`_cp8KbS9){Bkq-Sag%Y-oe517v0Nbnx0+(Sch*Nr_&?>X4S`5Jxhvie11Oe$3-&e z&WiCgK1+aGf5ZBRNxvTt_YPVhtgUWsqY?n}-jIy?ldB3vF2KC>L|Cz}-?<~ItP-aaI5j$>x0g^&)m|@6@NWN|` z!$T2pg;L8%95*=1PzFqyQa3hK+W(s;x)D;aCMZQI14gtsC8X>|lC-V>?C&RIe2##0 zlSDm?C`#fMD(#{{hhR*5*hEjeMj*6!fV(J23^L7$nP~DLWDCGPd58f44zZ?P-XWN* z3SsDG2v1@2B~VHtf$)s!SEWK%2Q88;S+ImPL!yg1BQA#B9$nMt58RZLzjNlS_};-V za%~XhG(O5XqN?V(+F0I&Wy8C{H#h!VfUSI@eUrg;#yX% z_{O-T*Y;p|j_rkG$K)I5h_wY^fF5-RY*RFZ!Z?~-cE7ki{D{^;9NVEdMk1pglvrAZ zkh)64;I~HH9+|HuB|{;2UF^uPn)OY zThKt9lt-`DjE5oMmQoKNBpT(U`Q)MiY$|X0OmSC<)A1N^Ux}0W6X2n$ou+v@d!G!# Ezbf6@Qvd(} delta 503 zcmYk3&2G~`6ot?Hcx-1}a0IB`G3hFcASxs*6}rf+#G;$3i>}y2ZaOJWT04pzKp+$r zynvObU;$emf(;Tcz?;ySw5mGN=-%^<&be2b@9}S?k=IuY02@T@qe1tx61IFF*^kX= zval9tr%yBH*_LNBJ09n=7cVn#&pMu6<(HS$7{Y_tgZZK;8_4$0lkGsLK&enbN;U@q z!O#tlRr`N?r5-f4zMmL&7fT1u>_t(ImgR?{JV&H%(_^_=rxP=D{)*ryV|+y*^tq&T zwktAM6Vj=q9SRH#O9L_#rqT#P#uMt3aBVV8S&tjh=ch@J-8u&DiEkWx6sM98oloqt zH(M@-)RgcHhp*s;bmBQ1zTOBo`yg{2PhsFLOR@gK_ZeUR;w=;FBeB2QP=ZnP4^y|J zVLuMP`Xj$R)PRm4h6yyZ@)_c$K=NNRcFazTmKwQWXqQ!Vlf3);~^QO=hQ$msBn j_O+N)6=Thi8FuB?aAF5s$Jm24c_Of>sX2Y{<07;~hIGcq4DDDs9o`X)s|t z4^>mrl9G$ra8f}eJvPMW>}va1+cqXik}9PP8iN34YuQP7*A){3bHE9tKOhr z^?Sn!*hjUy=9_KTf&U57*_>T6>TNh5PI{M<_ru8m9!X0%z(&GGP25RH2ye#A({7ns zx$PE0``@Vj3C%)v@4p_%lsgIvJnn!8wsPgsBVkpTHy!jU*O{_poGJ8iN0G@*hSt}< zmr^7DUw(8OITt&Ia+USq^?~As+}#_tHY|Yrz9Omx0r5_T+^FCxLyyV2lsrWYL)W4m zN?htS!GX%?DQPyd(kW)9cT|?+60pY^X25_K)N-lnGR!mwL5fR)pJ3}1a7!jZ@H4vC zwZmIy2W$yh5W)_L>5?m%i^sd88~*$Qw>9NI6-Fz*-(Xb4Qp7!dOulrQm%pH-CuPw@ z*xCg+L0SrH@ulS~g9&Y^_90-{7GXH>Q!|4^)Pq*9XIkM2kqql=|oh z4>eFm39ADlii2GH$hCbW_e;r=7JMD_u?!{hhLAO=v3wbFR+WdL?!3M`@?UQASarRT zOUZMxJfLVfpxCCMyBXgm+vc5k63RtuGhUmCjpbaXSfgc5PiGr&#X(gw{Y9!luAWZNTd?Gndp&w#82EM2TA{2iyY}ehlyz z_$mDf9QXmu+No0_Su^jwc{AftjC4~l0PH9_XEn}6UDvE`0*IiL*F<|nQ=puEJqP$N z77JV6M)q?xy+9t#t?Ycdsg~>X%7Qt4&*=+0o283augBny>p8Ay z3=liQ7PHk|>yk}{EsEvswomJ^#l}``N$g5i>#VHcxgPrtliH2wz z&rxo#XTkQR_PypnDrV^Y712+|cx_-X;+|29p%_z4j8viN8(%{+6&Y4EH=7|{@ zL1~gJHsD%}crsvH!x1UGF&vv%g?vIbF=X%dsEY}5gBLh^0|z_;FWKa618DT=m@=-Q zK@U^34vkPb?V{O_vwQme!MA-0$nTu_-M$Z432tq^sB4i2GD_=I?BNV^>JZ7XWyYu-UJ(=8q$+4zJ;(gAdL07v4a zdEtJpy$+~c`yGh#wkehEE)kdqJUzv|*PbGRm?V&pJ*uVyaOLe%f0qU_aP34JAmxV$ z#*^NA8Ud3?`ShP@`qIzJ)lCJXW%&5Hn2{8h%O%W_6c_0im}41VW@WbdXy*f%QyJ11 IqnC@pKX_xoTmS$7 diff --git a/substrate/wasm-runtime/test/src/lib.rs b/substrate/wasm-runtime/test/src/lib.rs index a24de0219d..8bbba9e7a8 100644 --- a/substrate/wasm-runtime/test/src/lib.rs +++ b/substrate/wasm-runtime/test/src/lib.rs @@ -8,12 +8,21 @@ use alloc::vec::Vec; #[macro_use] extern crate runtime_support; -use runtime_support::{set_storage, storage, print, keccak256}; +use runtime_support::{set_storage, storage, print, keccak256, ed25519_verify}; fn test_keccak256(input: Vec) -> Vec { keccak256(&input).to_vec() } +fn test_ed25519_verify(input: Vec) -> Vec { + let sig = &input[0..64]; + let pubkey = &input[64..96]; + let msg = b"all ok!"; + let mut r = Vec::new(); + r.push(ed25519_verify(sig, &msg[..], pubkey) as u8); + r +} + fn test_data_in(input: Vec) -> Vec { print(b"set_storage" as &[u8]); set_storage(b"input", &input); @@ -29,4 +38,4 @@ fn test_data_in(input: Vec) -> Vec { } -impl_stubs!(test_data_in, test_keccak256); +impl_stubs!(test_data_in, test_keccak256, test_ed25519_verify); From 712becb205d96755a45057a31dc62d3c4039ae70 Mon Sep 17 00:00:00 2001 From: Gav Date: Thu, 18 Jan 2018 12:34:14 +0100 Subject: [PATCH 051/112] Polish --- .../release/runtime_test.compact.wasm | Bin 1193 -> 962 bytes .../release/runtime_test.wasm | Bin 1281 -> 1079 bytes substrate/wasm-runtime/test/src/lib.rs | 4 +--- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm index e4431c2606a6e09c8aabfc4baf815ebe5c296a54..69e547cd117a8e644a910fd360ae972b4a6efa6b 100644 GIT binary patch delta 256 zcmW+uO-{l<82#qIWvULrwHa|CTZtuVqVhGtYg8%2^7R4@HQK4 gfc2BX3HZ92cp(BHUIzs delta 487 zcmYjNyKYlK5S`h_eR%IpHXH$>2Q9N5>c7Hs)sndlg=fW`ncY z`_b$Oie!3ta`I*fYvyfTsTl*eFjycp#mLmu&@#R(wJ0;K zl7UCCs1&FyDK$MaFTOOdJTotaftM{eH8;7Sl7WvM$jHqvOJ(2(2^FW7FbJ^aCg$Yi zCo>4Lq!p#6G6-=pGH`8T;atba$W-sh;K-oC#NsHBt+d&aX*Hv*El7~ZkzIj7fx+Bb5S`iGJK#R#kkV%EDmxn3&zozMXmV-rLXez4Pv%bRFDyc$B+)nOS7rvFZ1F<3=+Euf8joL8I9` zKJBi|d^B8xUz;zPc4@9g)9!M5Gnx)y&rVI+zg|PN#2}rm3T%_^oQs2?8ZtTHQD(UWBxAvXtWJti)deW_8=}ZHXm(OM7)SEs3tusRLZNcJ``55y zp~%t@i!xblJdvP1U1D9(-;e|lO0ointRlN8u5!dyvU3JN7AcKM#0hwojY37h$;6iA cwoQ)@p)FdZiVt&OR|8cn9VCUJy?K$(zffRE) -> Vec { let sig = &input[0..64]; let pubkey = &input[64..96]; let msg = b"all ok!"; - let mut r = Vec::new(); - r.push(ed25519_verify(sig, &msg[..], pubkey) as u8); - r + [ed25519_verify(sig, &msg[..], pubkey) as u8].to_vec() } fn test_data_in(input: Vec) -> Vec { From 92d8712b2b76bd2d30232029e17f18aba36bd251 Mon Sep 17 00:00:00 2001 From: Gav Date: Thu, 18 Jan 2018 15:14:01 +0100 Subject: [PATCH 052/112] Introduce UncheckedTransaction & test. --- .../polkadot/src/codec/endiansensitive.rs | 4 +- substrate/wasm-runtime/polkadot/src/lib.rs | 7 +- .../polkadot/src/runtime/consensus.rs | 7 +- .../polkadot/src/runtime/staking.rs | 10 +- .../polkadot/src/runtime/system.rs | 21 +-- .../polkadot/src/runtime/timestamp.rs | 7 +- .../polkadot/src/support/primitives.rs | 152 +++++++++++++----- .../polkadot/src/support/storage.rs | 6 +- 8 files changed, 143 insertions(+), 71 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs b/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs index c13a96f23d..f1e042d886 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs +++ b/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs @@ -26,4 +26,6 @@ macro_rules! impl_non_endians { } impl_endians!(u16, u32, u64, usize, i16, i32, i64, isize); -impl_non_endians!(u8, i8, [u8; 20], [u8; 32]); +impl_non_endians!(u8, i8, [u8; 1], [u8; 2], [u8; 3], [u8; 4], [u8; 5], [u8; 6], [u8; 7], [u8; 8], + [u8; 10], [u8; 12], [u8; 14], [u8; 16], [u8; 20], [u8; 24], [u8; 28], [u8; 32], [u8; 40], + [u8; 48], [u8; 56], [u8; 64], [u8; 80], [u8; 96], [u8; 112], [u8; 128]); diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 52b29b05cf..18ce4059a8 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -11,11 +11,12 @@ pub use codec::{endiansensitive, streamreader, joiner, slicable, keyedvec}; pub use support::{primitives, function, environment, storage}; #[cfg(test)] pub use support::testing; -#[allow(unused_imports)] // TODO: remove in due course + +#[allow(unused_imports)] // TODO: remove in due course use runtime_support::Vec; use slicable::Slicable; -use primitives::{Block, Transaction}; +use primitives::{Block, UncheckedTransaction}; // TODO: add externals for: // - keccak256 (or some better hashing scheme) @@ -27,7 +28,7 @@ pub fn execute_block(input: Vec) -> Vec { } pub fn execute_transaction(input: Vec) -> Vec { - runtime::system::execute_transaction(&Transaction::from_slice(&input).unwrap()) + runtime::system::execute_transaction(&UncheckedTransaction::from_slice(&input).unwrap()) } impl_stubs!(execute_block, execute_transaction); diff --git a/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs b/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs index add87a1808..0d2531cea4 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs @@ -2,14 +2,13 @@ use runtime_support::Vec; use keyedvec::KeyedVec; use storage::Storage; use primitives::{AccountID, SessionKey, BlockNumber}; -use storage::storage_into; pub fn set_authority(index: u32, authority: AccountID) { authority.store(&index.to_keyed_vec(b"con\0aut\0")); } fn authority(index: u32) -> AccountID { - storage_into(&index.to_keyed_vec(b"con\0aut\0")) + Storage::into(&index.to_keyed_vec(b"con\0aut\0")) } pub fn set_authority_count(count: u32) { @@ -18,7 +17,7 @@ pub fn set_authority_count(count: u32) { } fn authority_count() -> u32 { - storage_into(b"con\0aut\0len") + Storage::into(b"con\0aut\0len") } /// Get the current set of authorities. These are the session keys. @@ -49,7 +48,7 @@ pub fn set_validators(_new: &[AccountID]) { /// The number of blocks in each session. pub fn session_length() -> BlockNumber { - storage_into(b"con\0bps") + Storage::into(b"con\0bps") } /// Sets the session key of `_transactor` to `_session`. This doesn't take effect until the next diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index ca37e7f6fe..6e22cfcd5f 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -1,5 +1,5 @@ use keyedvec::KeyedVec; -use storage::{Storage, storage_into}; +use storage::Storage; use primitives::{BlockNumber, Balance, AccountID}; use runtime::consensus; @@ -10,7 +10,7 @@ pub fn era_length() -> BlockNumber { /// The length of a staking era in sessions. pub fn sessions_per_era() -> BlockNumber { - storage_into(b"sta\0spe") + Storage::into(b"sta\0spe") } /// The era has changed - enact new staking set. @@ -22,16 +22,16 @@ pub fn next_era() { /// The balance of a given account. pub fn balance(who: &AccountID) -> Balance { - storage_into(&who.to_keyed_vec(b"sta\0bal\0")) + Storage::into(&who.to_keyed_vec(b"sta\0bal\0")) } /// Transfer some unlocked staking balance to another staker. pub fn transfer_stake(transactor: &AccountID, dest: &AccountID, value: Balance) { let from_key = transactor.to_keyed_vec(b"sta\0bal\0"); - let from_balance: Balance = storage_into(&from_key); + let from_balance: Balance = Storage::into(&from_key); assert!(from_balance >= value); let to_key = dest.to_keyed_vec(b"sta\0bal\0"); - let to_balance: Balance = storage_into(&to_key); + let to_balance: Balance = Storage::into(&to_key); assert!(to_balance + value > to_balance); // no overflow (from_balance - value).store(&from_key); (to_balance + value).store(&to_key); diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 27c5eb4fd9..3c4d020dee 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -1,4 +1,4 @@ -use primitives::{Block, BlockNumber, Hash, Transaction}; +use primitives::{Block, BlockNumber, Hash, UncheckedTransaction}; use runtime_support::{Vec, swap}; use environment::with_env; use runtime_support; @@ -53,7 +53,7 @@ fn final_checks(_block: &Block) { } /// Execute a given transaction. -pub fn execute_transaction(_tx: &Transaction) -> Vec { +pub fn execute_transaction(_tx: &UncheckedTransaction) -> Vec { // TODO: decode data and ensure valid // TODO: ensure signature valid and recover id (use authentication::authenticate) // TODO: check nonce @@ -61,7 +61,7 @@ pub fn execute_transaction(_tx: &Transaction) -> Vec { // TODO: ensure target_function valid // TODO: decode parameters - _tx.function.dispatch(&_tx.signed, &_tx.input_data); + _tx.transaction.function.dispatch(&_tx.transaction.signed, &_tx.transaction.input_data); // TODO: encode any return Vec::new() @@ -78,7 +78,7 @@ mod tests { use function::Function; use std::collections::HashMap; use runtime_support::{NoError, with_externalities, Externalities}; - use primitives::{AccountID, Transaction}; + use primitives::{AccountID, UncheckedTransaction, Transaction}; use runtime::{system, staking}; #[derive(Debug, Default)] @@ -114,11 +114,14 @@ mod tests { { let mut r = b"sta\0bal\0".to_vec(); r.extend_from_slice(&one); r } => vec![111u8, 0, 0, 0, 0, 0, 0, 0] ], }; - let tx = Transaction { - signed: one.clone(), - function: Function::StakingTransferStake, - input_data: vec![].join(&two).join(&69u64), - nonce: 0, + let tx = UncheckedTransaction { + transaction: Transaction { + signed: one.clone(), + nonce: 0, + function: Function::StakingTransferStake, + input_data: vec![].join(&two).join(&69u64), + }, + signature: [1u8; 64], }; with_externalities(&mut t, || { diff --git a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs index 6a4043651d..6d694c88ae 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs @@ -1,9 +1,10 @@ use primitives::Timestamp; +use storage::Storage; pub fn timestamp() -> Timestamp { - unimplemented!() + Storage::into(b"tim\0val") } -pub fn set_timestamp(_now: Timestamp) { - unimplemented!() +pub fn set_timestamp(now: Timestamp) { + now.store(b"tim\0val") } diff --git a/substrate/wasm-runtime/polkadot/src/support/primitives.rs b/substrate/wasm-runtime/polkadot/src/support/primitives.rs index f1bd31cc66..bb82da8f3b 100644 --- a/substrate/wasm-runtime/polkadot/src/support/primitives.rs +++ b/substrate/wasm-runtime/polkadot/src/support/primitives.rs @@ -5,10 +5,13 @@ use slicable::{Slicable, NonTrivialSlicable}; use function::Function; use runtime_support::size_of; -/// The hash of an ECDSA pub key which is used to identify an external transactor. +#[cfg(test)] +use std::fmt; + +/// The Ed25519 pubkey that identifies an account. pub type AccountID = [u8; 32]; -/// The ECDSA pub key of an authority. This is what the external environment/consensus algorithm -/// refers to as a "authority". +/// The Ed25519 pub key of an session that belongs to an authority. This is used as what the +/// external environment/consensus algorithm calls an "authority". pub type SessionKey = AccountID; pub type Balance = u64; pub type ChainID = u64; @@ -36,15 +39,9 @@ pub struct Header { #[cfg_attr(test, derive(PartialEq, Debug))] pub struct Transaction { pub signed: AccountID, + pub nonce: TxOrder, pub function: Function, pub input_data: Vec, - pub nonce: TxOrder, -} - -#[cfg_attr(test, derive(PartialEq, Debug))] -pub struct Block { - pub header: Header, - pub transactions: Vec, } impl Slicable for Transaction { @@ -52,8 +49,8 @@ impl Slicable for Transaction { let mut reader = StreamReader::new(value); Some(Transaction { signed: reader.read()?, - function: Function::from_u8(reader.read()?)?, nonce: reader.read()?, + function: Function::from_u8(reader.read()?)?, input_data: reader.read()?, }) } @@ -65,13 +62,13 @@ impl Slicable for Transaction { fn to_vec(&self) -> Vec { Vec::new() .join(&self.signed) - .join(&(self.function as u8)) .join(&self.nonce) + .join(&(self.function as u8)) .join(&self.input_data) } fn size_of(data: &[u8]) -> Option { - let first_part = size_of::() + size_of::() + size_of::(); + let first_part = size_of::() + size_of::() + size_of::(); let second_part = >::size_of(&data[first_part..])?; Some(first_part + second_part) } @@ -79,6 +76,59 @@ impl Slicable for Transaction { impl NonTrivialSlicable for Transaction {} +pub struct UncheckedTransaction { + pub transaction: Transaction, + pub signature: [u8; 64], +} + +#[cfg(test)] +impl PartialEq for UncheckedTransaction { + fn eq(&self, other: &Self) -> bool { + self.signature.iter().eq(other.signature.iter()) && self.transaction == other.transaction + } +} + +#[cfg(test)] +impl fmt::Debug for UncheckedTransaction { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "UncheckedTransaction({:?})", self.transaction) + } +} + +impl Slicable for UncheckedTransaction { + fn from_slice(value: &[u8]) -> Option { + let mut reader = StreamReader::new(value); + Some(UncheckedTransaction { + signature: reader.read()?, + transaction: reader.read()?, + }) + } + + fn set_as_slice bool>(_fill_slice: F) -> Option { + unimplemented!(); + } + + fn to_vec(&self) -> Vec { + Vec::new() + .join(&self.signature) + .join(&self.transaction) + } + + fn size_of(data: &[u8]) -> Option { + let first_part = size_of::<[u8; 64]>(); + let second_part = ::size_of(&data[first_part..])?; + Some(first_part + second_part) + } +} + +impl NonTrivialSlicable for UncheckedTransaction {} + +#[cfg_attr(test, derive(PartialEq, Debug))] +pub struct Block { + pub header: Header, + pub transactions: Vec, +} + impl NonTrivialSlicable for Vec where Vec: Slicable {} impl Slicable for Vec { @@ -181,15 +231,15 @@ mod tests { let two: AccountID = [2u8; 32]; let tx = Transaction { signed: one.clone(), + nonce: 69, function: Function::StakingTransferStake, input_data: Vec::new().join(&two).join(&69u64), - nonce: 69, }; let serialised = tx.to_vec(); assert_eq!(serialised, vec![ 1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 69, 0, 0, 0, 0, 0, 0, 0, + 2, 40, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 69, 0, 0, 0, 0, 0, 0, 0 @@ -202,14 +252,14 @@ mod tests { let two: AccountID = [2u8; 32]; let tx = Transaction { signed: one.clone(), + nonce: 69, function: Function::StakingTransferStake, input_data: Vec::new().join(&two).join(&69u64), - nonce: 69, }; let data = [ 1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 69, 0, 0, 0, 0, 0, 0, 0, + 2, 40, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 69, 0, 0, 0, 0, 0, 0, 0 @@ -269,17 +319,23 @@ mod tests { fn serialise_block_works() { let one: AccountID = [1u8; 32]; let two: AccountID = [2u8; 32]; - let tx1 = Transaction { - signed: one.clone(), - function: Function::StakingTransferStake, - input_data: Vec::new().join(&two).join(&69u64), - nonce: 69, + let tx1 = UncheckedTransaction { + transaction: Transaction { + signed: one.clone(), + nonce: 69, + function: Function::StakingTransferStake, + input_data: Vec::new().join(&two).join(&69u64), + }, + signature: [1u8; 64], }; - let tx2 = Transaction { - signed: two.clone(), - function: Function::StakingStake, - input_data: Vec::new(), - nonce: 42, + let tx2 = UncheckedTransaction { + transaction: Transaction { + signed: two.clone(), + nonce: 42, + function: Function::StakingStake, + input_data: Vec::new(), + }, + signature: [2u8; 64], }; let h = Header { parent_hash: [4u8; 32], @@ -305,18 +361,20 @@ mod tests { 11, 0, 0, 0, 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103, // transactions - 130, 0, 0, 0, + 2, 1, 0, 0, // tx1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 69, 0, 0, 0, 0, 0, 0, 0, + 2, 40, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 69, 0, 0, 0, 0, 0, 0, 0, // tx2 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 0, 42, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0 ]); } @@ -325,17 +383,23 @@ mod tests { fn deserialise_block_works() { let one: AccountID = [1u8; 32]; let two: AccountID = [2u8; 32]; - let tx1 = Transaction { - signed: one.clone(), - function: Function::StakingTransferStake, - input_data: Vec::new().join(&two).join(&69u64), - nonce: 69, + let tx1 = UncheckedTransaction { + transaction: Transaction { + signed: one.clone(), + nonce: 69, + function: Function::StakingTransferStake, + input_data: Vec::new().join(&two).join(&69u64), + }, + signature: [1u8; 64], }; - let tx2 = Transaction { - signed: two.clone(), - function: Function::StakingStake, - input_data: Vec::new(), - nonce: 42, + let tx2 = UncheckedTransaction { + transaction: Transaction { + signed: two.clone(), + nonce: 42, + function: Function::StakingStake, + input_data: Vec::new(), + }, + signature: [2u8; 64], }; let h = Header { parent_hash: [4u8; 32], @@ -360,18 +424,20 @@ mod tests { 11, 0, 0, 0, 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103, // transactions - 130, 0, 0, 0, + 2, 1, 0, 0, // tx1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 69, 0, 0, 0, 0, 0, 0, 0, + 2, 40, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 69, 0, 0, 0, 0, 0, 0, 0, // tx2 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 0, 42, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0 ]; let deserialised = Block::from_slice(&data).unwrap(); diff --git a/substrate/wasm-runtime/polkadot/src/support/storage.rs b/substrate/wasm-runtime/polkadot/src/support/storage.rs index 13a9074d95..99c8bab880 100644 --- a/substrate/wasm-runtime/polkadot/src/support/storage.rs +++ b/substrate/wasm-runtime/polkadot/src/support/storage.rs @@ -3,12 +3,12 @@ use endiansensitive::EndianSensitive; use runtime_support; pub trait Storage { - fn storage_into(key: &[u8]) -> Self; + fn into(key: &[u8]) -> Self; fn store(&self, key: &[u8]); } impl Storage for T { - fn storage_into(key: &[u8]) -> Self { + fn into(key: &[u8]) -> Self { Slicable::set_as_slice(|out| runtime_support::read_storage(key, out) == out.len()) .unwrap_or_else(Default::default) } @@ -19,5 +19,5 @@ impl Storage for T { } pub fn storage_into(key: &[u8]) -> T { - T::storage_into(key) + T::into(key) } From 7f8949bed1808e1c82661e17f4370b6c0293c969 Mon Sep 17 00:00:00 2001 From: Gav Date: Thu, 18 Jan 2018 16:24:53 +0100 Subject: [PATCH 053/112] Implement basic block and tx processing --- .../polkadot/src/codec/keyedvec.rs | 22 ++- substrate/wasm-runtime/polkadot/src/lib.rs | 8 +- .../polkadot/src/runtime/system.rs | 63 +++++--- .../polkadot/src/support/primitives.rs | 139 ++++++++++-------- .../polkadot/src/support/storage.rs | 9 +- 5 files changed, 142 insertions(+), 99 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/codec/keyedvec.rs b/substrate/wasm-runtime/polkadot/src/codec/keyedvec.rs index fcc410e582..fad6b1956f 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/keyedvec.rs +++ b/substrate/wasm-runtime/polkadot/src/codec/keyedvec.rs @@ -1,17 +1,20 @@ use runtime_support::Vec; -use primitives::AccountID; use slicable::Slicable; pub trait KeyedVec { fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec; } -impl KeyedVec for AccountID { - fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec { - let mut r = prepend_key.to_vec(); - r.extend_from_slice(self); - r - } +macro_rules! impl_non_endians { + ( $( $t:ty ),* ) => { $( + impl KeyedVec for $t { + fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec { + let mut r = prepend_key.to_vec(); + r.extend_from_slice(&self[..]); + r + } + } + )* } } macro_rules! impl_endians { @@ -28,4 +31,7 @@ macro_rules! impl_endians { )* } } -impl_endians!(u16, u32, u64, usize, i16, i32, i64, isize); +impl_endians!(u8, i8, u16, u32, u64, usize, i16, i32, i64, isize); +impl_non_endians!([u8; 1], [u8; 2], [u8; 3], [u8; 4], [u8; 5], [u8; 6], [u8; 7], [u8; 8], + [u8; 10], [u8; 12], [u8; 14], [u8; 16], [u8; 20], [u8; 24], [u8; 28], [u8; 32], [u8; 40], + [u8; 48], [u8; 56], [u8; 64], [u8; 80], [u8; 96], [u8; 112], [u8; 128]); diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 18ce4059a8..7653aaff9b 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -19,16 +19,16 @@ use slicable::Slicable; use primitives::{Block, UncheckedTransaction}; // TODO: add externals for: -// - keccak256 (or some better hashing scheme) // - trie rooting -// - ECDSA-recover (or some better sig scheme) pub fn execute_block(input: Vec) -> Vec { - runtime::system::execute_block(Block::from_slice(&input).unwrap()) + runtime::system::execute_block(Block::from_slice(&input).unwrap()); + Vec::new() } pub fn execute_transaction(input: Vec) -> Vec { - runtime::system::execute_transaction(&UncheckedTransaction::from_slice(&input).unwrap()) + runtime::system::execute_transaction(&UncheckedTransaction::from_slice(&input).unwrap()); + Vec::new() } impl_stubs!(execute_block, execute_transaction); diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 3c4d020dee..2ddc83bdb2 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -1,7 +1,8 @@ -use primitives::{Block, BlockNumber, Hash, UncheckedTransaction}; +use primitives::{Block, BlockNumber, Hash, UncheckedTransaction, TxOrder, Hashable}; use runtime_support::{Vec, swap}; +use storage::Storage; +use keyedvec::KeyedVec; use environment::with_env; -use runtime_support; use runtime::staking; /// The current block number being processed. Set by `execute_block`. @@ -10,8 +11,8 @@ pub fn block_number() -> BlockNumber { } /// Get the block hash of a given block (uses storage). -pub fn block_hash(_number: BlockNumber) -> Hash { - unimplemented!() +pub fn block_hash(number: BlockNumber) -> Hash { + Storage::into(&number.to_keyed_vec(b"sys\0old\0")) } /// Deposits a log and ensures it matches the blocks log data. @@ -22,7 +23,7 @@ pub fn deposit_log(log: &[u8]) { }); } -pub fn execute_block(mut block: Block) -> Vec { +pub fn execute_block(mut block: Block) { // populate environment from header. with_env(|e| { e.block_number = block.header.number; @@ -30,20 +31,29 @@ pub fn execute_block(mut block: Block) -> Vec { e.next_log_index = 0; }); + let ref header = block.header; + + // check parent_hash is correct. + assert!( + header.number > 0 && block_hash(header.number - 1) == header.parent_hash, + "Parent hash should be valid." + ); + // TODO: check transaction trie root represents the transactions. - // TODO: store the header hash in storage. + // store the header hash in storage. + let header_hash_key = header.number.to_keyed_vec(b"sys\0old\0"); + header.keccak256().store(&header_hash_key); + + // execute transactions staking::pre_transactions(); - - block.transactions.iter().for_each(|tx| { execute_transaction(tx); }); - + block.transactions.iter().for_each(execute_transaction); staking::post_transactions(); + // any final checks final_checks(&block); - // TODO: check state root somehow - - Vec::new() + // TODO: check storage root somehow } fn final_checks(_block: &Block) { @@ -53,29 +63,34 @@ fn final_checks(_block: &Block) { } /// Execute a given transaction. -pub fn execute_transaction(_tx: &UncheckedTransaction) -> Vec { - // TODO: decode data and ensure valid - // TODO: ensure signature valid and recover id (use authentication::authenticate) - // TODO: check nonce - // TODO: increment nonce in storage - // TODO: ensure target_function valid - // TODO: decode parameters +pub fn execute_transaction(utx: &UncheckedTransaction) { + // Verify the signature is good. + assert!(utx.ed25519_verify(), "All transactions should be properly signed"); - _tx.transaction.function.dispatch(&_tx.transaction.signed, &_tx.transaction.input_data); + let ref tx = utx.transaction; - // TODO: encode any return - Vec::new() + // check nonce + let nonce_key = tx.signed.to_keyed_vec(b"sys\0non\0"); + let expected_nonce: TxOrder = Storage::into(&nonce_key); + assert!(tx.nonce == expected_nonce, "All transactions should have the correct nonce"); + + // increment nonce in storage + (expected_nonce + 1).store(&nonce_key); + + // decode parameters and dispatch + tx.function.dispatch(&tx.signed, &tx.input_data); } /// Set the new code. pub fn set_code(new: &[u8]) { - runtime_support::set_storage(b"\0code", new) + new.store(b"\0code"); } #[cfg(test)] mod tests { use joiner::Joiner; use function::Function; + use codec::keyedvec::KeyedVec; use std::collections::HashMap; use runtime_support::{NoError, with_externalities, Externalities}; use primitives::{AccountID, UncheckedTransaction, Transaction}; @@ -111,7 +126,7 @@ mod tests { let two: AccountID = [2u8; 32]; let mut t = TestExternalities { storage: map![ - { let mut r = b"sta\0bal\0".to_vec(); r.extend_from_slice(&one); r } => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + one.to_keyed_vec(b"sta\0bal\0") => vec![111u8, 0, 0, 0, 0, 0, 0, 0] ], }; let tx = UncheckedTransaction { diff --git a/substrate/wasm-runtime/polkadot/src/support/primitives.rs b/substrate/wasm-runtime/polkadot/src/support/primitives.rs index bb82da8f3b..4cf9dd9d32 100644 --- a/substrate/wasm-runtime/polkadot/src/support/primitives.rs +++ b/substrate/wasm-runtime/polkadot/src/support/primitives.rs @@ -3,7 +3,7 @@ use streamreader::StreamReader; use joiner::Joiner; use slicable::{Slicable, NonTrivialSlicable}; use function::Function; -use runtime_support::size_of; +use runtime_support::{size_of, keccak256, ed25519_verify}; #[cfg(test)] use std::fmt; @@ -36,6 +36,40 @@ pub struct Header { pub digest: Digest, } +impl Slicable for Header { + fn from_slice(value: &[u8]) -> Option { + let mut reader = StreamReader::new(value); + Some(Header { + parent_hash: reader.read()?, + number: reader.read()?, + state_root: reader.read()?, + transaction_root: reader.read()?, + digest: Digest { logs: reader.read()?, }, + }) + } + + fn set_as_slice bool>(_fill_slice: F) -> Option { + unimplemented!(); + } + + fn to_vec(&self) -> Vec { + Vec::new() + .join(&self.parent_hash) + .join(&self.number) + .join(&self.state_root) + .join(&self.transaction_root) + .join(&self.digest.logs) + } + + fn size_of(data: &[u8]) -> Option { + let first_part = size_of::() + size_of::() + size_of::() + size_of::(); + let second_part = >>::size_of(&data[first_part..])?; + Some(first_part + second_part) + } +} + +impl NonTrivialSlicable for Header {} + #[cfg_attr(test, derive(PartialEq, Debug))] pub struct Transaction { pub signed: AccountID, @@ -74,6 +108,16 @@ impl Slicable for Transaction { } } +pub trait Hashable: Sized { + fn keccak256(&self) -> [u8; 32]; +} + +impl Hashable for T { + fn keccak256(&self) -> [u8; 32] { + keccak256(&self.to_vec()) + } +} + impl NonTrivialSlicable for Transaction {} pub struct UncheckedTransaction { @@ -81,6 +125,13 @@ pub struct UncheckedTransaction { pub signature: [u8; 64], } +impl UncheckedTransaction { + pub fn ed25519_verify(&self) -> bool { + let msg = self.transaction.to_vec(); + ed25519_verify(&self.signature, &msg, &self.transaction.signed) + } +} + #[cfg(test)] impl PartialEq for UncheckedTransaction { fn eq(&self, other: &Self) -> bool { @@ -129,6 +180,34 @@ pub struct Block { pub transactions: Vec, } +impl Slicable for Block { + fn from_slice(value: &[u8]) -> Option { + let mut reader = StreamReader::new(value); + Some(Block { + header: reader.read()?, + transactions: reader.read()?, + }) + } + + fn set_as_slice bool>(_fill_slice: F) -> Option { + unimplemented!(); + } + + fn to_vec(&self) -> Vec { + Vec::new() + .join(&self.header) + .join(&self.transactions) + } + + fn size_of(data: &[u8]) -> Option { + let first_part = Header::size_of(data)?; + let second_part = >::size_of(&data[first_part..])?; + Some(first_part + second_part) + } +} + +impl NonTrivialSlicable for Block {} + impl NonTrivialSlicable for Vec where Vec: Slicable {} impl Slicable for Vec { @@ -161,64 +240,6 @@ impl Slicable for Vec { } } -impl Slicable for Header { - fn from_slice(value: &[u8]) -> Option { - let mut reader = StreamReader::new(value); - Some(Header { - parent_hash: reader.read()?, - number: reader.read()?, - state_root: reader.read()?, - transaction_root: reader.read()?, - digest: Digest { logs: reader.read()?, }, - }) - } - - fn set_as_slice bool>(_fill_slice: F) -> Option { - unimplemented!(); - } - - fn to_vec(&self) -> Vec { - Vec::new() - .join(&self.parent_hash) - .join(&self.number) - .join(&self.state_root) - .join(&self.transaction_root) - .join(&self.digest.logs) - } - - fn size_of(data: &[u8]) -> Option { - let first_part = size_of::() + size_of::() + size_of::() + size_of::(); - let second_part = >>::size_of(&data[first_part..])?; - Some(first_part + second_part) - } -} - -impl Slicable for Block { - fn from_slice(value: &[u8]) -> Option { - let mut reader = StreamReader::new(value); - Some(Block { - header: reader.read()?, - transactions: reader.read()?, - }) - } - - fn set_as_slice bool>(_fill_slice: F) -> Option { - unimplemented!(); - } - - fn to_vec(&self) -> Vec { - Vec::new() - .join(&self.header) - .join(&self.transactions) - } - - fn size_of(data: &[u8]) -> Option { - let first_part = Header::size_of(data)?; - let second_part = >::size_of(&data[first_part..])?; - Some(first_part + second_part) - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/substrate/wasm-runtime/polkadot/src/support/storage.rs b/substrate/wasm-runtime/polkadot/src/support/storage.rs index 99c8bab880..becb4f7fb2 100644 --- a/substrate/wasm-runtime/polkadot/src/support/storage.rs +++ b/substrate/wasm-runtime/polkadot/src/support/storage.rs @@ -3,7 +3,7 @@ use endiansensitive::EndianSensitive; use runtime_support; pub trait Storage { - fn into(key: &[u8]) -> Self; + fn into(_key: &[u8]) -> Self where Self: Sized { unimplemented!() } fn store(&self, key: &[u8]); } @@ -12,12 +12,13 @@ impl Storage for T { Slicable::set_as_slice(|out| runtime_support::read_storage(key, out) == out.len()) .unwrap_or_else(Default::default) } - fn store(&self, key: &[u8]) { self.as_slice_then(|slice| runtime_support::set_storage(key, slice)); } } -pub fn storage_into(key: &[u8]) -> T { - T::into(key) +impl Storage for [u8] { + fn store(&self, key: &[u8]) { + runtime_support::set_storage(key, self) + } } From abb83043891c239ec0178274c003ad5372a5f97e Mon Sep 17 00:00:00 2001 From: Gav Date: Thu, 18 Jan 2018 17:35:18 +0100 Subject: [PATCH 054/112] Introduce static hex and valid signature for block test. --- substrate/Cargo.lock | 1 + substrate/native-runtime/Cargo.toml | 1 + substrate/primitives/src/ed25519.rs | 60 +++++++++++++++---- substrate/wasm-runtime/polkadot/src/lib.rs | 5 +- .../polkadot/src/runtime/system.rs | 20 +++++-- .../wasm-runtime/polkadot/src/support/mod.rs | 2 + .../polkadot/src/support/statichex.rs | 29 +++++++++ .../polkadot/src/support/testing.rs | 43 +++++++++++++ 8 files changed, 144 insertions(+), 17 deletions(-) create mode 100644 substrate/wasm-runtime/polkadot/src/support/statichex.rs diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index f886c60be5..7d5f50ddc4 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -532,6 +532,7 @@ name = "native-runtime" version = "0.1.0" dependencies = [ "runtime-support 0.1.0", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/substrate/native-runtime/Cargo.toml b/substrate/native-runtime/Cargo.toml index c971a6d694..eb5eb82408 100644 --- a/substrate/native-runtime/Cargo.toml +++ b/substrate/native-runtime/Cargo.toml @@ -10,3 +10,4 @@ without-std = [] [dependencies] runtime-support = { path = "./support", version = "0.1" } +rustc-hex = "1.0" diff --git a/substrate/primitives/src/ed25519.rs b/substrate/primitives/src/ed25519.rs index f6a02a735b..2630f858d2 100644 --- a/substrate/primitives/src/ed25519.rs +++ b/substrate/primitives/src/ed25519.rs @@ -4,17 +4,6 @@ use untrusted; use ring::{rand, signature}; use rustc_hex::FromHex; -struct HexDisplay<'a>(&'a [u8]); - -impl<'a> ::std::fmt::Display for HexDisplay<'a> { - fn fmt(&self, fmtr: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { - for byte in self.0 { - try!( fmtr.write_fmt(format_args!("{:02x}", byte))); - } - Ok(()) - } -} - pub fn verify(sig: &[u8], message: &[u8], public: &[u8]) -> bool { let public_key = untrusted::Input::from(public); let msg = untrusted::Input::from(message); @@ -181,6 +170,41 @@ impl PartialEq for Signature { mod test { use super::*; +pub struct HexDisplay<'a>(&'a [u8]); + +impl<'a> HexDisplay<'a> { + pub fn from(d: &'a AsBytesRef) -> Self { HexDisplay(d.as_bytes_ref()) } +} + +impl<'a> ::std::fmt::Display for HexDisplay<'a> { + fn fmt(&self, fmtr: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { + for byte in self.0 { + try!( fmtr.write_fmt(format_args!("{:02x}", byte))); + } + Ok(()) + } +} + +pub trait AsBytesRef { + fn as_bytes_ref(&self) -> &[u8]; +} + +impl AsBytesRef for [u8] { + fn as_bytes_ref(&self) -> &[u8] { &self } +} + +macro_rules! impl_non_endians { + ( $( $t:ty ),* ) => { $( + impl AsBytesRef for $t { + fn as_bytes_ref(&self) -> &[u8] { &self[..] } + } + )* } +} + +impl_non_endians!([u8; 1], [u8; 2], [u8; 3], [u8; 4], [u8; 5], [u8; 6], [u8; 7], [u8; 8], + [u8; 10], [u8; 12], [u8; 14], [u8; 16], [u8; 20], [u8; 24], [u8; 28], [u8; 32], [u8; 40], + [u8; 48], [u8; 56], [u8; 64], [u8; 80], [u8; 96], [u8; 112], [u8; 128]); + #[test] fn test_vector_should_work() { let pair: Pair = "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60".into(); @@ -205,8 +229,22 @@ mod test { fn seeded_pair_should_work() { let pair = Pair::from_seed(b"12345678901234567890123456789012"); let public = pair.public(); + println!("{}", HexDisplay::from(&public.0)); + assert_eq!(public, "2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee".into()); let message = b"Something important"; let signature = pair.sign(&message[..]); assert!(signature.verify(&message[..], &public)); } + + #[test] + fn can_sign_transaction() { + let pair = Pair::from_seed(b"12345678901234567890123456789012"); + let public = pair.public(); + assert_eq!(public, "2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee".into()); + let message = FromHex::from_hex("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000").unwrap(); + let signature = pair.sign(&message[..]); + println!("pub: {}", HexDisplay::from(&public.0)); + println!("sig: {}", HexDisplay::from(&signature.0)); + assert!(signature.verify(&message[..], &public)); + } } diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 7653aaff9b..6a6201945d 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -4,13 +4,16 @@ #[macro_use] extern crate runtime_support; +#[cfg(test)] +extern crate rustc_hex; + mod codec; mod support; mod runtime; pub use codec::{endiansensitive, streamreader, joiner, slicable, keyedvec}; pub use support::{primitives, function, environment, storage}; #[cfg(test)] -pub use support::testing; +pub use support::{testing, statichex}; #[allow(unused_imports)] // TODO: remove in due course diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 2ddc83bdb2..fe0e835608 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -90,11 +90,14 @@ pub fn set_code(new: &[u8]) { mod tests { use joiner::Joiner; use function::Function; - use codec::keyedvec::KeyedVec; + use keyedvec::KeyedVec; + use slicable::Slicable; use std::collections::HashMap; use runtime_support::{NoError, with_externalities, Externalities}; - use primitives::{AccountID, UncheckedTransaction, Transaction}; + use primitives::{AccountID, UncheckedTransaction, Transaction, Hashable}; + use statichex::StaticHexInto; use runtime::{system, staking}; + use testing::HexDisplay; #[derive(Debug, Default)] struct TestExternalities { @@ -120,10 +123,13 @@ mod tests { ) } + fn one() -> AccountID { "2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee".convert() } + fn two() -> AccountID { "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a".convert() } + #[test] fn staking_balance_transfer_dispatch_works() { - let one: AccountID = [1u8; 32]; - let two: AccountID = [2u8; 32]; + let one = one(); + let two = two(); let mut t = TestExternalities { storage: map![ one.to_keyed_vec(b"sta\0bal\0") => vec![111u8, 0, 0, 0, 0, 0, 0, 0] @@ -136,8 +142,12 @@ mod tests { function: Function::StakingTransferStake, input_data: vec![].join(&two).join(&69u64), }, - signature: [1u8; 64], + signature: "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a".convert(), }; + // tx: 2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000 + // sig: 679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a + + println!("tx is {}", HexDisplay::from(&tx.transaction.to_vec())); with_externalities(&mut t, || { system::execute_transaction(&tx); diff --git a/substrate/wasm-runtime/polkadot/src/support/mod.rs b/substrate/wasm-runtime/polkadot/src/support/mod.rs index aa14ad2f5d..732552effd 100644 --- a/substrate/wasm-runtime/polkadot/src/support/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/support/mod.rs @@ -3,5 +3,7 @@ pub mod function; pub mod environment; pub mod storage; +#[cfg(test)] +pub mod statichex; #[cfg(test)] pub mod testing; diff --git a/substrate/wasm-runtime/polkadot/src/support/statichex.rs b/substrate/wasm-runtime/polkadot/src/support/statichex.rs new file mode 100644 index 0000000000..774cb82538 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/support/statichex.rs @@ -0,0 +1,29 @@ +use rustc_hex::FromHex; + +pub trait StaticHexConversion: Sized { + fn from_static_hex(hex: &'static str) -> Self; +} + +macro_rules! impl_sizes { + ( $( $t:expr ),* ) => { $( + impl StaticHexConversion for [u8; $t] { + fn from_static_hex(hex: &'static str) -> Self { + let mut r = [0u8; $t]; + r.copy_from_slice(&FromHex::from_hex(hex).unwrap()); + r + } + } + )* } +} + +impl_sizes!(1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128); + +pub trait StaticHexInto { + fn convert(self) -> T; +} + +impl StaticHexInto for &'static str { + fn convert(self) -> T { + T::from_static_hex(self) + } +} diff --git a/substrate/wasm-runtime/polkadot/src/support/testing.rs b/substrate/wasm-runtime/polkadot/src/support/testing.rs index ec7fac6d6d..5338add635 100644 --- a/substrate/wasm-runtime/polkadot/src/support/testing.rs +++ b/substrate/wasm-runtime/polkadot/src/support/testing.rs @@ -19,3 +19,46 @@ impl Externalities for TestExternalities { fn chain_id(&self) -> u64 { 42 } } + +pub struct HexDisplay<'a>(&'a [u8]); + +impl<'a> HexDisplay<'a> { + pub fn from(d: &'a AsBytesRef) -> Self { HexDisplay(d.as_bytes_ref()) } +} + +impl<'a> ::std::fmt::Display for HexDisplay<'a> { + fn fmt(&self, fmtr: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { + for byte in self.0 { + try!( fmtr.write_fmt(format_args!("{:02x}", byte))); + } + Ok(()) + } +} + +pub trait AsBytesRef { + fn as_bytes_ref(&self) -> &[u8]; +} + +impl AsBytesRef for [u8] { + fn as_bytes_ref(&self) -> &[u8] { &self } +} + +impl<'a> AsBytesRef for &'a[u8] { + fn as_bytes_ref(&self) -> &[u8] { self } +} + +impl AsBytesRef for Vec { + fn as_bytes_ref(&self) -> &[u8] { &self[..] } +} + +macro_rules! impl_non_endians { + ( $( $t:ty ),* ) => { $( + impl AsBytesRef for $t { + fn as_bytes_ref(&self) -> &[u8] { &self[..] } + } + )* } +} + +impl_non_endians!([u8; 1], [u8; 2], [u8; 3], [u8; 4], [u8; 5], [u8; 6], [u8; 7], [u8; 8], + [u8; 10], [u8; 12], [u8; 14], [u8; 16], [u8; 20], [u8; 24], [u8; 28], [u8; 32], [u8; 40], + [u8; 48], [u8; 56], [u8; 64], [u8; 80], [u8; 96], [u8; 112], [u8; 128]); From 78a197f63202619f9d01b4894ffcb7cb196de132 Mon Sep 17 00:00:00 2001 From: Gav Date: Thu, 18 Jan 2018 18:42:33 +0100 Subject: [PATCH 055/112] Repot session. --- substrate/wasm-runtime/polkadot/src/lib.rs | 5 -- .../polkadot/src/runtime/consensus.rs | 39 +------------- .../wasm-runtime/polkadot/src/runtime/mod.rs | 2 + .../polkadot/src/runtime/session.rs | 51 +++++++++++++++++++ .../polkadot/src/runtime/staking.rs | 14 ++--- .../polkadot/src/runtime/system.rs | 12 +++-- .../polkadot/src/support/function.rs | 10 ++-- 7 files changed, 75 insertions(+), 58 deletions(-) create mode 100644 substrate/wasm-runtime/polkadot/src/runtime/session.rs diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 6a6201945d..500594e31a 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -15,15 +15,10 @@ pub use support::{primitives, function, environment, storage}; #[cfg(test)] pub use support::{testing, statichex}; - -#[allow(unused_imports)] // TODO: remove in due course use runtime_support::Vec; use slicable::Slicable; use primitives::{Block, UncheckedTransaction}; -// TODO: add externals for: -// - trie rooting - pub fn execute_block(input: Vec) -> Vec { runtime::system::execute_block(Block::from_slice(&input).unwrap()); Vec::new() diff --git a/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs b/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs index 0d2531cea4..f8991e8871 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs @@ -2,6 +2,7 @@ use runtime_support::Vec; use keyedvec::KeyedVec; use storage::Storage; use primitives::{AccountID, SessionKey, BlockNumber}; +use runtime::{system, staking}; pub fn set_authority(index: u32, authority: AccountID) { authority.store(&index.to_keyed_vec(b"con\0aut\0")); @@ -32,41 +33,3 @@ pub fn set_authorities(authorities: &[AccountID]) { set_authority_count(authorities.len() as u32); authorities.iter().enumerate().for_each(|(v, &i)| set_authority(v as u32, i)); } - -/// Get the current set of validators. These are the long-term identifiers for the validators -/// and will be mapped to a session key with the most recent `set_next_session_key`. -pub fn validators() -> Vec { - unimplemented!() -} - -/// Set the current set of validators. -/// -/// Called by staking::next_era() only. -pub fn set_validators(_new: &[AccountID]) { - unimplemented!() -} - -/// The number of blocks in each session. -pub fn session_length() -> BlockNumber { - Storage::into(b"con\0bps") -} - -/// Sets the session key of `_transactor` to `_session`. This doesn't take effect until the next -/// session. -pub fn set_session_key(_transactor: &AccountID, _session: &AccountID) { - unimplemented!() -} - -/// Move onto next session: register the new authority set. -pub fn next_session() { - // TODO: Call set_authorities(). - unimplemented!() -} - -/// Hook to be called prior to transaction processing. -pub fn pre_transactions() {} - -/// Hook to be called after to transaction processing. -pub fn post_transactions() { - // TODO: check block number and call next_session if necessary. -} diff --git a/substrate/wasm-runtime/polkadot/src/runtime/mod.rs b/substrate/wasm-runtime/polkadot/src/runtime/mod.rs index c73e338a91..8e60ec431c 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/mod.rs @@ -6,3 +6,5 @@ pub mod consensus; pub mod staking; #[allow(unused)] pub mod timestamp; +#[allow(unused)] +pub mod session; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs new file mode 100644 index 0000000000..f72ef0b5c6 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -0,0 +1,51 @@ +use runtime_support::Vec; +use keyedvec::KeyedVec; +use storage::Storage; +use primitives::{AccountID, SessionKey, BlockNumber}; +use runtime::{system, staking, consensus}; + +/// Get the current set of validators. These are the long-term identifiers for the validators +/// and will be mapped to a session key with the most recent `set_next_session_key`. +pub fn validators() -> Vec { + consensus::authorities() +} + +/// Set the current set of validators. +/// +/// Called by staking::next_era() only. +pub fn set_validators(new: &[AccountID]) { + consensus::set_authorities(new); +} + +/// The number of blocks in each session. +pub fn length() -> BlockNumber { + Storage::into(b"con\0bps") +} + +/// Sets the session key of `_transactor` to `_session`. This doesn't take effect until the next +/// session. +pub fn set_key(_transactor: &AccountID, _session: &AccountID) { + // TODO: record the new session key for `_transactor`, ready for the next session. +} + +/// Move onto next session: register the new authority set. +pub fn next_session() { + // TODO: Call set_authorities() with any new authorities. +} + +/// Hook to be called prior to transaction processing. +pub fn pre_transactions() { + staking::pre_transactions(); +} + +/// Hook to be called after to transaction processing. +pub fn post_transactions() { + staking::post_transactions(); + + // do this last, after the staking system has had chance to switch out the authorities for the + // new set. + // check block number and call next_session if necessary. + if system::block_number() % length() == 0 { + next_session(); + } +} diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index 6e22cfcd5f..366ad0668b 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -1,11 +1,11 @@ use keyedvec::KeyedVec; use storage::Storage; use primitives::{BlockNumber, Balance, AccountID}; -use runtime::consensus; +use runtime::{system, session}; /// The length of a staking era in blocks. pub fn era_length() -> BlockNumber { - sessions_per_era() * consensus::session_length() + sessions_per_era() * session::length() } /// The length of a staking era in sessions. @@ -17,7 +17,8 @@ pub fn sessions_per_era() -> BlockNumber { /// /// NOTE: This always happens on a session change. pub fn next_era() { - unimplemented!() + // TODO: evaluate desired staking amounts and nominations and optimise to find the best + // combination of validators, then use session::set_validators(). } /// The balance of a given account. @@ -53,13 +54,14 @@ pub fn unstake(_transactor: &AccountID) { /// Hook to be called prior to transaction processing. pub fn pre_transactions() { - consensus::pre_transactions(); } /// Hook to be called after to transaction processing. pub fn post_transactions() { - // TODO: check block number and call next_era if necessary. - consensus::post_transactions(); + // check block number and call next_era if necessary. + if system::block_number() % era_length() == 0 { + next_era(); + } } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index fe0e835608..690e1db527 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -3,7 +3,7 @@ use runtime_support::{Vec, swap}; use storage::Storage; use keyedvec::KeyedVec; use environment::with_env; -use runtime::staking; +use runtime::session; /// The current block number being processed. Set by `execute_block`. pub fn block_number() -> BlockNumber { @@ -40,20 +40,24 @@ pub fn execute_block(mut block: Block) { ); // TODO: check transaction trie root represents the transactions. + // this requires non-trivial changes to the externals API or compiling trie rooting into wasm + // so will wait until a little later. // store the header hash in storage. let header_hash_key = header.number.to_keyed_vec(b"sys\0old\0"); header.keccak256().store(&header_hash_key); // execute transactions - staking::pre_transactions(); + session::pre_transactions(); block.transactions.iter().for_each(execute_transaction); - staking::post_transactions(); + session::post_transactions(); // any final checks final_checks(&block); - // TODO: check storage root somehow + // TODO: check storage root. + // this requires non-trivial changes to the externals API or compiling trie rooting into wasm + // so will wait until a little later. } fn final_checks(_block: &Block) { diff --git a/substrate/wasm-runtime/polkadot/src/support/function.rs b/substrate/wasm-runtime/polkadot/src/support/function.rs index ff54938d47..995ec3c459 100644 --- a/substrate/wasm-runtime/polkadot/src/support/function.rs +++ b/substrate/wasm-runtime/polkadot/src/support/function.rs @@ -1,4 +1,4 @@ -use runtime::{staking, consensus}; +use runtime::{staking, session}; use primitives::AccountID; use streamreader::StreamReader; @@ -9,7 +9,7 @@ pub enum Function { StakingStake, StakingUnstake, StakingTransferStake, - ConsensusSetSessionKey, + SessionSetKey, } impl Function { @@ -18,7 +18,7 @@ impl Function { x if x == Function::StakingStake as u8 => Some(Function::StakingStake), x if x == Function::StakingUnstake as u8 => Some(Function::StakingUnstake), x if x == Function::StakingTransferStake as u8 => Some(Function::StakingTransferStake), - x if x == Function::ConsensusSetSessionKey as u8 => Some(Function::ConsensusSetSessionKey), + x if x == Function::SessionSetKey as u8 => Some(Function::SessionSetKey), _ => None, } } @@ -40,9 +40,9 @@ impl Function { let value = params.read().unwrap(); staking::transfer_stake(transactor, &dest, value); } - Function::ConsensusSetSessionKey => { + Function::SessionSetKey => { let session = params.read().unwrap(); - consensus::set_session_key(transactor, &session); + session::set_key(transactor, &session); } } } From f179adbc4e49e7bd547691d29d622f37f363cadd Mon Sep 17 00:00:00 2001 From: Gav Date: Thu, 18 Jan 2018 18:45:29 +0100 Subject: [PATCH 056/112] comments. --- substrate/wasm-runtime/polkadot/src/runtime/session.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs index f72ef0b5c6..1112d45249 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -7,6 +7,7 @@ use runtime::{system, staking, consensus}; /// Get the current set of validators. These are the long-term identifiers for the validators /// and will be mapped to a session key with the most recent `set_next_session_key`. pub fn validators() -> Vec { + // TODO: derive from the actual validator set consensus::authorities() } @@ -14,6 +15,7 @@ pub fn validators() -> Vec { /// /// Called by staking::next_era() only. pub fn set_validators(new: &[AccountID]) { + // TODO: set the actual validators consensus::set_authorities(new); } From ba0d71a5517ef7490b5048c0dc3cbf55bf54309e Mon Sep 17 00:00:00 2001 From: Gav Date: Fri, 19 Jan 2018 08:49:38 +0100 Subject: [PATCH 057/112] Refactor and timestamp test --- substrate/wasm-runtime/polkadot/src/lib.rs | 1 + .../polkadot/src/runtime/session.rs | 28 ++++++---- .../polkadot/src/runtime/staking.rs | 30 +++++++---- .../polkadot/src/runtime/system.rs | 52 +++++-------------- .../polkadot/src/runtime/timestamp.rs | 30 ++++++++++- .../polkadot/src/support/function.rs | 16 ++++-- .../wasm-runtime/polkadot/src/support/mod.rs | 1 + .../polkadot/src/support/primitives.rs | 8 +-- .../polkadot/src/support/testing.rs | 16 ++++++ 9 files changed, 110 insertions(+), 72 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 500594e31a..b791fefdb7 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -8,6 +8,7 @@ extern crate runtime_support; extern crate rustc_hex; mod codec; +#[macro_use] mod support; mod runtime; pub use codec::{endiansensitive, streamreader, joiner, slicable, keyedvec}; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs index 1112d45249..0a736b3b47 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -4,6 +4,16 @@ use storage::Storage; use primitives::{AccountID, SessionKey, BlockNumber}; use runtime::{system, staking, consensus}; +// TRANSACTION API (available to all transactors) + +/// Sets the session key of `_transactor` to `_session`. This doesn't take effect until the next +/// session. +pub fn set_key(_transactor: &AccountID, _session: &AccountID) { + // TODO: record the new session key for `_transactor`, ready for the next session. +} + +// PUBLIC API (available to other runtime modules) + /// Get the current set of validators. These are the long-term identifiers for the validators /// and will be mapped to a session key with the most recent `set_next_session_key`. pub fn validators() -> Vec { @@ -24,17 +34,6 @@ pub fn length() -> BlockNumber { Storage::into(b"con\0bps") } -/// Sets the session key of `_transactor` to `_session`. This doesn't take effect until the next -/// session. -pub fn set_key(_transactor: &AccountID, _session: &AccountID) { - // TODO: record the new session key for `_transactor`, ready for the next session. -} - -/// Move onto next session: register the new authority set. -pub fn next_session() { - // TODO: Call set_authorities() with any new authorities. -} - /// Hook to be called prior to transaction processing. pub fn pre_transactions() { staking::pre_transactions(); @@ -51,3 +50,10 @@ pub fn post_transactions() { next_session(); } } + +// PRIVATE (not available) + +/// Move onto next session: register the new authority set. +fn next_session() { + // TODO: Call set_authorities() with any new authorities. +} diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index 366ad0668b..9b06602c84 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -3,6 +3,11 @@ use storage::Storage; use primitives::{BlockNumber, Balance, AccountID}; use runtime::{system, session}; +// Each validator's stake has one amount in each of three states: +// - inactive: free to be transferred +// - active: currently representing a validator +// - deactivating: recently representing a validator and not yet ready for transfer + /// The length of a staking era in blocks. pub fn era_length() -> BlockNumber { sessions_per_era() * session::length() @@ -13,21 +18,26 @@ pub fn sessions_per_era() -> BlockNumber { Storage::into(b"sta\0spe") } +/// The length of a staking era in sessions. +pub fn lockup_eras() -> BlockNumber { + Storage::into(b"sta\0lpe") +} + /// The era has changed - enact new staking set. /// /// NOTE: This always happens on a session change. -pub fn next_era() { +fn next_era() { // TODO: evaluate desired staking amounts and nominations and optimise to find the best // combination of validators, then use session::set_validators(). } /// The balance of a given account. -pub fn balance(who: &AccountID) -> Balance { +pub fn balance_inactive(who: &AccountID) -> Balance { Storage::into(&who.to_keyed_vec(b"sta\0bal\0")) } /// Transfer some unlocked staking balance to another staker. -pub fn transfer_stake(transactor: &AccountID, dest: &AccountID, value: Balance) { +pub fn transfer_inactive(transactor: &AccountID, dest: &AccountID, value: Balance) { let from_key = transactor.to_keyed_vec(b"sta\0bal\0"); let from_balance: Balance = Storage::into(&from_key); assert!(from_balance >= value); @@ -42,14 +52,14 @@ pub fn transfer_stake(transactor: &AccountID, dest: &AccountID, value: Balance) /// /// Effects will be felt at the beginning of the next era. pub fn stake(_transactor: &AccountID) { - unimplemented!() + // TODO: record the desire for `_transactor` to activate their stake. } /// Retract the desire to stake for the transactor. /// /// Effects will be felt at the beginning of the next era. pub fn unstake(_transactor: &AccountID) { - unimplemented!() + // TODO: record the desire for `_transactor` to deactivate their stake. } /// Hook to be called prior to transaction processing. @@ -88,8 +98,8 @@ mod tests { ], }; with_externalities(&mut t, || { - assert_eq!(staking::balance(&one), 42); - assert_eq!(staking::balance(&two), 0); + assert_eq!(staking::balance_inactive(&one), 42); + assert_eq!(staking::balance_inactive(&two), 0); }); } @@ -103,9 +113,9 @@ mod tests { ], }; with_externalities(&mut t, || { - staking::transfer_stake(&one, &two, 69); - assert_eq!(staking::balance(&one), 42); - assert_eq!(staking::balance(&two), 69); + staking::transfer_inactive(&one, &two, 69); + assert_eq!(staking::balance_inactive(&one), 42); + assert_eq!(staking::balance_inactive(&two), 69); }); } } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 690e1db527..d7abd1835a 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -60,12 +60,6 @@ pub fn execute_block(mut block: Block) { // so will wait until a little later. } -fn final_checks(_block: &Block) { - with_env(|e| { - assert_eq!(e.next_log_index, e.digest.logs.len()); - }); -} - /// Execute a given transaction. pub fn execute_transaction(utx: &UncheckedTransaction) { // Verify the signature is good. @@ -90,45 +84,23 @@ pub fn set_code(new: &[u8]) { new.store(b"\0code"); } +fn final_checks(_block: &Block) { + with_env(|e| { + assert_eq!(e.next_log_index, e.digest.logs.len()); + }); +} + #[cfg(test)] mod tests { use joiner::Joiner; use function::Function; use keyedvec::KeyedVec; use slicable::Slicable; - use std::collections::HashMap; - use runtime_support::{NoError, with_externalities, Externalities}; - use primitives::{AccountID, UncheckedTransaction, Transaction, Hashable}; + use runtime_support::with_externalities; + use primitives::{UncheckedTransaction, Transaction}; use statichex::StaticHexInto; use runtime::{system, staking}; - use testing::HexDisplay; - - #[derive(Debug, Default)] - struct TestExternalities { - storage: HashMap, Vec>, - } - impl Externalities for TestExternalities { - type Error = NoError; - - fn storage(&self, key: &[u8]) -> Result<&[u8], NoError> { - Ok(self.storage.get(&key.to_vec()).map_or(&[] as &[u8], Vec::as_slice)) - } - - fn set_storage(&mut self, key: Vec, value: Vec) { - self.storage.insert(key, value); - } - - fn chain_id(&self) -> u64 { 42 } - } - - macro_rules! map { - ($( $name:expr => $value:expr ),*) => ( - vec![ $( ( $name, $value ) ),* ].into_iter().collect() - ) - } - - fn one() -> AccountID { "2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee".convert() } - fn two() -> AccountID { "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a".convert() } + use testing::{TestExternalities, HexDisplay, one, two}; #[test] fn staking_balance_transfer_dispatch_works() { @@ -143,7 +115,7 @@ mod tests { transaction: Transaction { signed: one.clone(), nonce: 0, - function: Function::StakingTransferStake, + function: Function::StakingTransferInactive, input_data: vec![].join(&two).join(&69u64), }, signature: "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a".convert(), @@ -155,8 +127,8 @@ mod tests { with_externalities(&mut t, || { system::execute_transaction(&tx); - assert_eq!(staking::balance(&one), 42); - assert_eq!(staking::balance(&two), 69); + assert_eq!(staking::balance_inactive(&one), 42); + assert_eq!(staking::balance_inactive(&two), 69); }); } } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs index 6d694c88ae..09c1d5bcbe 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs @@ -1,10 +1,36 @@ use primitives::Timestamp; use storage::Storage; -pub fn timestamp() -> Timestamp { +pub fn get() -> Timestamp { Storage::into(b"tim\0val") } -pub fn set_timestamp(now: Timestamp) { +pub fn set(now: Timestamp) { now.store(b"tim\0val") } + +#[cfg(test)] +mod tests { + use joiner::Joiner; + use function::Function; + use keyedvec::KeyedVec; + use slicable::Slicable; + use runtime_support::with_externalities; + use primitives::{UncheckedTransaction, Transaction}; + use statichex::StaticHexInto; + use runtime::{system, timestamp}; + use testing::{TestExternalities, HexDisplay, one, two}; + + #[test] + fn timestamp_works() { + let mut t = TestExternalities { storage: map![ + b"tim\0val".to_vec() => vec![].join(&42u64) + ], }; + + with_externalities(&mut t, || { + assert_eq!(timestamp::get(), 42); + timestamp::set(69); + assert_eq!(timestamp::get(), 69); + }); + } +} diff --git a/substrate/wasm-runtime/polkadot/src/support/function.rs b/substrate/wasm-runtime/polkadot/src/support/function.rs index 995ec3c459..45dcea876b 100644 --- a/substrate/wasm-runtime/polkadot/src/support/function.rs +++ b/substrate/wasm-runtime/polkadot/src/support/function.rs @@ -1,6 +1,6 @@ -use runtime::{staking, session}; use primitives::AccountID; use streamreader::StreamReader; +use runtime::{staking, session, timestamp}; /// The functions that a transaction can call (and be dispatched to). #[cfg_attr(test, derive(PartialEq, Debug))] @@ -8,8 +8,9 @@ use streamreader::StreamReader; pub enum Function { StakingStake, StakingUnstake, - StakingTransferStake, + StakingTransferInactive, SessionSetKey, + TimestampSet, } impl Function { @@ -17,8 +18,9 @@ impl Function { match value { x if x == Function::StakingStake as u8 => Some(Function::StakingStake), x if x == Function::StakingUnstake as u8 => Some(Function::StakingUnstake), - x if x == Function::StakingTransferStake as u8 => Some(Function::StakingTransferStake), + x if x == Function::StakingTransferInactive as u8 => Some(Function::StakingTransferInactive), x if x == Function::SessionSetKey as u8 => Some(Function::SessionSetKey), + x if x == Function::TimestampSet as u8 => Some(Function::TimestampSet), _ => None, } } @@ -35,15 +37,19 @@ impl Function { Function::StakingUnstake => { staking::unstake(transactor); } - Function::StakingTransferStake => { + Function::StakingTransferInactive => { let dest = params.read().unwrap(); let value = params.read().unwrap(); - staking::transfer_stake(transactor, &dest, value); + staking::transfer_inactive(transactor, &dest, value); } Function::SessionSetKey => { let session = params.read().unwrap(); session::set_key(transactor, &session); } + Function::TimestampSet => { + let t = params.read().unwrap(); + timestamp::set(t); + } } } } diff --git a/substrate/wasm-runtime/polkadot/src/support/mod.rs b/substrate/wasm-runtime/polkadot/src/support/mod.rs index 732552effd..11cb23e997 100644 --- a/substrate/wasm-runtime/polkadot/src/support/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/support/mod.rs @@ -6,4 +6,5 @@ pub mod storage; #[cfg(test)] pub mod statichex; #[cfg(test)] +#[macro_use] pub mod testing; diff --git a/substrate/wasm-runtime/polkadot/src/support/primitives.rs b/substrate/wasm-runtime/polkadot/src/support/primitives.rs index 4cf9dd9d32..ecac3fbbd4 100644 --- a/substrate/wasm-runtime/polkadot/src/support/primitives.rs +++ b/substrate/wasm-runtime/polkadot/src/support/primitives.rs @@ -253,7 +253,7 @@ mod tests { let tx = Transaction { signed: one.clone(), nonce: 69, - function: Function::StakingTransferStake, + function: Function::StakingTransferInactive, input_data: Vec::new().join(&two).join(&69u64), }; let serialised = tx.to_vec(); @@ -274,7 +274,7 @@ mod tests { let tx = Transaction { signed: one.clone(), nonce: 69, - function: Function::StakingTransferStake, + function: Function::StakingTransferInactive, input_data: Vec::new().join(&two).join(&69u64), }; let data = [ @@ -344,7 +344,7 @@ mod tests { transaction: Transaction { signed: one.clone(), nonce: 69, - function: Function::StakingTransferStake, + function: Function::StakingTransferInactive, input_data: Vec::new().join(&two).join(&69u64), }, signature: [1u8; 64], @@ -408,7 +408,7 @@ mod tests { transaction: Transaction { signed: one.clone(), nonce: 69, - function: Function::StakingTransferStake, + function: Function::StakingTransferInactive, input_data: Vec::new().join(&two).join(&69u64), }, signature: [1u8; 64], diff --git a/substrate/wasm-runtime/polkadot/src/support/testing.rs b/substrate/wasm-runtime/polkadot/src/support/testing.rs index 5338add635..a617405e79 100644 --- a/substrate/wasm-runtime/polkadot/src/support/testing.rs +++ b/substrate/wasm-runtime/polkadot/src/support/testing.rs @@ -1,5 +1,7 @@ use runtime_support::{NoError, Externalities}; use std::collections::HashMap; +use primitives::AccountID; +use statichex::StaticHexInto; #[derive(Debug, Default)] pub struct TestExternalities { @@ -20,6 +22,20 @@ impl Externalities for TestExternalities { fn chain_id(&self) -> u64 { 42 } } +#[macro_export] +macro_rules! map { + ($( $name:expr => $value:expr ),*) => ( + vec![ $( ( $name, $value ) ),* ].into_iter().collect() + ) +} + +pub fn one() -> AccountID { + "2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee".convert() +} +pub fn two() -> AccountID { + "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a".convert() +} + pub struct HexDisplay<'a>(&'a [u8]); impl<'a> HexDisplay<'a> { From 3dcfd8ba6dc8e69eb452a7f4a08218f108204010 Mon Sep 17 00:00:00 2001 From: Gav Date: Fri, 19 Jan 2018 08:50:33 +0100 Subject: [PATCH 058/112] Remove fluff --- substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs index 09c1d5bcbe..e0f3d2c04e 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs @@ -12,14 +12,10 @@ pub fn set(now: Timestamp) { #[cfg(test)] mod tests { use joiner::Joiner; - use function::Function; use keyedvec::KeyedVec; - use slicable::Slicable; use runtime_support::with_externalities; - use primitives::{UncheckedTransaction, Transaction}; - use statichex::StaticHexInto; - use runtime::{system, timestamp}; - use testing::{TestExternalities, HexDisplay, one, two}; + use runtime::timestamp; + use testing::TestExternalities; #[test] fn timestamp_works() { From 368cbdbcbb0ef62fc72129a883cb38f76ed74adb Mon Sep 17 00:00:00 2001 From: Gav Date: Fri, 19 Jan 2018 08:51:38 +0100 Subject: [PATCH 059/112] Remove fluff. --- substrate/wasm-runtime/polkadot/src/runtime/staking.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index 9b06602c84..ecc2532872 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -74,7 +74,6 @@ pub fn post_transactions() { } } - #[cfg(test)] mod tests { use runtime_support::with_externalities; @@ -82,12 +81,6 @@ mod tests { use primitives::{AccountID}; use runtime::staking; - macro_rules! map { - ($( $name:expr => $value:expr ),*) => ( - vec![ $( ( $name, $value ) ),* ].into_iter().collect() - ) - } - #[test] fn staking_balance_works() { let one: AccountID = [1u8; 32]; From 400008028b207612e0d44c8f9dedebbe38a32069 Mon Sep 17 00:00:00 2001 From: Gav Date: Fri, 19 Jan 2018 09:37:00 +0100 Subject: [PATCH 060/112] Staking eras and tests. --- .../polkadot/src/runtime/session.rs | 2 +- .../polkadot/src/runtime/staking.rs | 127 +++++++++++++++--- 2 files changed, 113 insertions(+), 16 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs index 0a736b3b47..2ed6c7a0a2 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -31,7 +31,7 @@ pub fn set_validators(new: &[AccountID]) { /// The number of blocks in each session. pub fn length() -> BlockNumber { - Storage::into(b"con\0bps") + Storage::into(b"ses\0bps") } /// Hook to be called prior to transaction processing. diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index ecc2532872..ea2116b035 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -4,9 +4,14 @@ use primitives::{BlockNumber, Balance, AccountID}; use runtime::{system, session}; // Each validator's stake has one amount in each of three states: -// - inactive: free to be transferred -// - active: currently representing a validator -// - deactivating: recently representing a validator and not yet ready for transfer +// - inactive: free to be transferred. +// - active: currently representing a validator. +// - deactivating: recently representing a validator and not yet ready for transfer. + +/// The length of a staking era in sessions. +pub fn lockup_eras() -> BlockNumber { + Storage::into(b"sta\0lpe") +} /// The length of a staking era in blocks. pub fn era_length() -> BlockNumber { @@ -18,15 +23,40 @@ pub fn sessions_per_era() -> BlockNumber { Storage::into(b"sta\0spe") } -/// The length of a staking era in sessions. -pub fn lockup_eras() -> BlockNumber { - Storage::into(b"sta\0lpe") +/// The current era index. +pub fn current_era() -> BlockNumber { + Storage::into(b"sta\0era") +} + +/// The current era index. +pub fn set_current_era(new: BlockNumber) { + new.store(b"sta\0era"); +} + +/// The block number at which the era length last changed. +pub fn last_era_length_change() -> BlockNumber { + Storage::into(b"sta\0lec") +} + +/// Set a new era length. Won't kick in until the next era change (at current length). +pub fn set_sessions_per_era(new: BlockNumber) { + new.store(b"sta\0nse"); } /// The era has changed - enact new staking set. /// /// NOTE: This always happens on a session change. fn next_era() { + // Increment current era. + set_current_era(current_era() + 1); + + // Enact era length change. + let next_spe: u64 = Storage::into(b"sta\0nse"); + if next_spe > 0 && next_spe != sessions_per_era() { + next_spe.store(b"sta\0spe"); + system::block_number().store(b"sta\0lec"); + } + // TODO: evaluate desired staking amounts and nominations and optimise to find the best // combination of validators, then use session::set_validators(). } @@ -69,7 +99,7 @@ pub fn pre_transactions() { /// Hook to be called after to transaction processing. pub fn post_transactions() { // check block number and call next_era if necessary. - if system::block_number() % era_length() == 0 { + if (system::block_number() - last_era_length_change()) % era_length() == 0 { next_era(); } } @@ -77,17 +107,84 @@ pub fn post_transactions() { #[cfg(test)] mod tests { use runtime_support::with_externalities; - use testing::TestExternalities; - use primitives::{AccountID}; + use keyedvec::KeyedVec; + use joiner::Joiner; + use testing::{one, two, TestExternalities}; + use primitives::AccountID; use runtime::staking; + use environment::with_env; + + #[test] + fn staking_eras_work() { + let mut t = TestExternalities { storage: map![ + b"ses\0bps".to_vec() => vec![].join(&1u64), + b"sta\0spe".to_vec() => vec![].join(&2u64) + ], }; + with_externalities(&mut t, || { + assert_eq!(staking::era_length(), 2u64); + assert_eq!(staking::sessions_per_era(), 2u64); + assert_eq!(staking::last_era_length_change(), 0u64); + assert_eq!(staking::current_era(), 0u64); + + // Block 1: No change. + with_env(|e| e.block_number = 1); + staking::post_transactions(); + assert_eq!(staking::sessions_per_era(), 2u64); + assert_eq!(staking::last_era_length_change(), 0u64); + assert_eq!(staking::current_era(), 0u64); + + // Block 2: Simple era change. + with_env(|e| e.block_number = 2); + staking::post_transactions(); + assert_eq!(staking::sessions_per_era(), 2u64); + assert_eq!(staking::last_era_length_change(), 0u64); + assert_eq!(staking::current_era(), 1u64); + + // Block 3: Schedule an era length change; no visible changes. + with_env(|e| e.block_number = 3); + staking::set_sessions_per_era(3); + staking::post_transactions(); + assert_eq!(staking::sessions_per_era(), 2u64); + assert_eq!(staking::last_era_length_change(), 0u64); + assert_eq!(staking::current_era(), 1u64); + + // Block 4: Era change kicks in. + with_env(|e| e.block_number = 4); + staking::post_transactions(); + assert_eq!(staking::sessions_per_era(), 3u64); + assert_eq!(staking::last_era_length_change(), 4u64); + assert_eq!(staking::current_era(), 2u64); + + // Block 5: No change. + with_env(|e| e.block_number = 5); + staking::post_transactions(); + assert_eq!(staking::sessions_per_era(), 3u64); + assert_eq!(staking::last_era_length_change(), 4u64); + assert_eq!(staking::current_era(), 2u64); + + // Block 6: No change. + with_env(|e| e.block_number = 6); + staking::post_transactions(); + assert_eq!(staking::sessions_per_era(), 3u64); + assert_eq!(staking::last_era_length_change(), 4u64); + assert_eq!(staking::current_era(), 2u64); + + // Block 7: Era increment. + with_env(|e| e.block_number = 7); + staking::post_transactions(); + assert_eq!(staking::sessions_per_era(), 3u64); + assert_eq!(staking::last_era_length_change(), 4u64); + assert_eq!(staking::current_era(), 3u64); + }); + } #[test] fn staking_balance_works() { - let one: AccountID = [1u8; 32]; - let two: AccountID = [2u8; 32]; + let one = one(); + let two = two(); let mut t = TestExternalities { storage: map![ - { let mut r = b"sta\0bal\0".to_vec(); r.extend_from_slice(&one); r } => vec![42u8, 0, 0, 0, 0, 0, 0, 0] + one.to_keyed_vec(b"sta\0bal\0") => vec![].join(&42u64) ], }; with_externalities(&mut t, || { @@ -98,11 +195,11 @@ mod tests { #[test] fn staking_balance_transfer_works() { - let one: AccountID = [1u8; 32]; - let two: AccountID = [2u8; 32]; + let one = one(); + let two = two(); let mut t = TestExternalities { storage: map![ - { let mut r = b"sta\0bal\0".to_vec(); r.extend_from_slice(&one); r } => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + one.to_keyed_vec(b"sta\0bal\0") => vec![].join(&111u64) ], }; with_externalities(&mut t, || { From 81cd156d2a5f263e10d7b433372a2150bc7bbac8 Mon Sep 17 00:00:00 2001 From: Gav Date: Fri, 19 Jan 2018 10:34:55 +0100 Subject: [PATCH 061/112] Implement sessions. --- substrate/wasm-runtime/polkadot/src/lib.rs | 2 +- .../polkadot/src/runtime/consensus.rs | 39 +++++++------------ .../wasm-runtime/polkadot/src/runtime/mod.rs | 2 + .../polkadot/src/runtime/session.rs | 33 +++++++++++----- .../wasm-runtime/polkadot/src/support/mod.rs | 1 + .../polkadot/src/support/storage.rs | 6 +-- .../polkadot/src/support/storagevec.rs | 38 ++++++++++++++++++ 7 files changed, 83 insertions(+), 38 deletions(-) create mode 100644 substrate/wasm-runtime/polkadot/src/support/storagevec.rs diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index b791fefdb7..4a1302a756 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -12,7 +12,7 @@ mod codec; mod support; mod runtime; pub use codec::{endiansensitive, streamreader, joiner, slicable, keyedvec}; -pub use support::{primitives, function, environment, storage}; +pub use support::{primitives, function, environment, storage, storagevec}; #[cfg(test)] pub use support::{testing, statichex}; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs b/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs index f8991e8871..b773e7e1e6 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs @@ -1,35 +1,26 @@ use runtime_support::Vec; -use keyedvec::KeyedVec; -use storage::Storage; -use primitives::{AccountID, SessionKey, BlockNumber}; -use runtime::{system, staking}; +use storagevec::StorageVec; +use primitives::SessionKey; -pub fn set_authority(index: u32, authority: AccountID) { - authority.store(&index.to_keyed_vec(b"con\0aut\0")); -} - -fn authority(index: u32) -> AccountID { - Storage::into(&index.to_keyed_vec(b"con\0aut\0")) -} - -pub fn set_authority_count(count: u32) { - (count..authority_count()).for_each(|i| set_authority(i, SessionKey::default())); - count.store(b"con\0aut\0len"); -} - -fn authority_count() -> u32 { - Storage::into(b"con\0aut\0len") +struct AuthorityStorageVec {} +impl StorageVec for AuthorityStorageVec { + type Item = SessionKey; + const PREFIX: &'static[u8] = b"con\0aut\0"; } /// Get the current set of authorities. These are the session keys. -pub fn authorities() -> Vec { - (0..authority_count()).into_iter().map(authority).collect() +pub fn authorities() -> Vec { + AuthorityStorageVec::items() } /// Set the current set of authorities' session keys. /// /// Called by `next_session` only. -pub fn set_authorities(authorities: &[AccountID]) { - set_authority_count(authorities.len() as u32); - authorities.iter().enumerate().for_each(|(v, &i)| set_authority(v as u32, i)); +pub fn set_authorities(authorities: &[SessionKey]) { + AuthorityStorageVec::set_items(authorities); +} + +/// Set a single authority by index. +pub fn set_authority(index: u32, key: &SessionKey) { + AuthorityStorageVec::set_item(index, key); } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/mod.rs b/substrate/wasm-runtime/polkadot/src/runtime/mod.rs index 8e60ec431c..55a4801a5b 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/mod.rs @@ -8,3 +8,5 @@ pub mod staking; pub mod timestamp; #[allow(unused)] pub mod session; + +// TODO: governance, polkadao diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs index 2ed6c7a0a2..8e133ad563 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -1,31 +1,38 @@ use runtime_support::Vec; use keyedvec::KeyedVec; use storage::Storage; +use storagevec::StorageVec; use primitives::{AccountID, SessionKey, BlockNumber}; use runtime::{system, staking, consensus}; +struct ValidatorStorageVec {} +impl StorageVec for ValidatorStorageVec { + type Item = AccountID; + const PREFIX: &'static[u8] = b"ses\0key\0"; +} + // TRANSACTION API (available to all transactors) -/// Sets the session key of `_transactor` to `_session`. This doesn't take effect until the next +/// Sets the session key of `_validator` to `_key`. This doesn't take effect until the next /// session. -pub fn set_key(_transactor: &AccountID, _session: &AccountID) { - // TODO: record the new session key for `_transactor`, ready for the next session. +pub fn set_key(validator: &AccountID, key: &SessionKey) { + // set new value for next session + key.store(&validator.to_keyed_vec(b"ses\0nxt\0")); } // PUBLIC API (available to other runtime modules) -/// Get the current set of validators. These are the long-term identifiers for the validators -/// and will be mapped to a session key with the most recent `set_next_session_key`. -pub fn validators() -> Vec { - // TODO: derive from the actual validator set - consensus::authorities() +/// Get the current set of authorities. These are the session keys. +fn validators() -> Vec { + ValidatorStorageVec::items() } /// Set the current set of validators. /// -/// Called by staking::next_era() only. +/// Called by staking::next_era() only. `next_session` should be called after this in order to +/// update the session keys to the next validator set. pub fn set_validators(new: &[AccountID]) { - // TODO: set the actual validators + ValidatorStorageVec::set_items(new); consensus::set_authorities(new); } @@ -56,4 +63,10 @@ pub fn post_transactions() { /// Move onto next session: register the new authority set. fn next_session() { // TODO: Call set_authorities() with any new authorities. + validators().iter().enumerate().for_each(|(i, v)| { + let k = v.to_keyed_vec(b"ses\0nxt\0"); + if let Some(n) = Storage::try_into(&k) { + consensus::set_authority(i as u32, &n); + } + }) } diff --git a/substrate/wasm-runtime/polkadot/src/support/mod.rs b/substrate/wasm-runtime/polkadot/src/support/mod.rs index 11cb23e997..e4dae46c40 100644 --- a/substrate/wasm-runtime/polkadot/src/support/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/support/mod.rs @@ -2,6 +2,7 @@ pub mod primitives; pub mod function; pub mod environment; pub mod storage; +pub mod storagevec; #[cfg(test)] pub mod statichex; diff --git a/substrate/wasm-runtime/polkadot/src/support/storage.rs b/substrate/wasm-runtime/polkadot/src/support/storage.rs index becb4f7fb2..7c9696bc11 100644 --- a/substrate/wasm-runtime/polkadot/src/support/storage.rs +++ b/substrate/wasm-runtime/polkadot/src/support/storage.rs @@ -3,14 +3,14 @@ use endiansensitive::EndianSensitive; use runtime_support; pub trait Storage { - fn into(_key: &[u8]) -> Self where Self: Sized { unimplemented!() } + fn into(key: &[u8]) -> Self where Self: Sized + Default { Self::try_into(key).unwrap_or_else(Default::default) } + fn try_into(_key: &[u8]) -> Option where Self: Sized { unimplemented!() } fn store(&self, key: &[u8]); } impl Storage for T { - fn into(key: &[u8]) -> Self { + fn try_into(key: &[u8]) -> Option { Slicable::set_as_slice(|out| runtime_support::read_storage(key, out) == out.len()) - .unwrap_or_else(Default::default) } fn store(&self, key: &[u8]) { self.as_slice_then(|slice| runtime_support::set_storage(key, slice)); diff --git a/substrate/wasm-runtime/polkadot/src/support/storagevec.rs b/substrate/wasm-runtime/polkadot/src/support/storagevec.rs new file mode 100644 index 0000000000..ac0ded3a56 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/support/storagevec.rs @@ -0,0 +1,38 @@ +use runtime_support::Vec; +use keyedvec::KeyedVec; +use storage::Storage; + +/// A trait to conveniently store a vector of storable data. +// TODO: add iterator support +pub trait StorageVec { + type Item: Default + Sized + Storage; + const PREFIX: &'static [u8]; + + /// Get the current set of items. + fn items() -> Vec { + (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) { + item.store(&index.to_keyed_vec(Self::PREFIX)); + } + + fn item(index: u32) -> Self::Item { + Storage::into(&index.to_keyed_vec(Self::PREFIX)) + } + + fn set_count(count: u32) { + (count..Self::count()).for_each(|i| Self::set_item(i, &Self::Item::default())); + count.store(&b"len".to_keyed_vec(Self::PREFIX)); + } + + fn count() -> u32 { + Storage::into(&b"len".to_keyed_vec(Self::PREFIX)) + } +} From 63809d9e0c14d253f4a1da8782e52362ae65b7b1 Mon Sep 17 00:00:00 2001 From: Gav Date: Fri, 19 Jan 2018 10:49:23 +0100 Subject: [PATCH 062/112] Polish --- substrate/state_machine/src/lib.rs | 2 +- substrate/wasm-runtime/polkadot/src/lib.rs | 2 +- .../polkadot/src/runtime/consensus.rs | 2 +- .../polkadot/src/runtime/session.rs | 13 ++-- .../polkadot/src/runtime/staking.rs | 18 +++--- .../polkadot/src/runtime/system.rs | 6 +- .../polkadot/src/runtime/timestamp.rs | 4 +- .../wasm-runtime/polkadot/src/support/mod.rs | 3 +- .../polkadot/src/support/storable.rs | 62 +++++++++++++++++++ .../polkadot/src/support/storage.rs | 24 ------- .../polkadot/src/support/storagevec.rs | 38 ------------ 11 files changed, 87 insertions(+), 87 deletions(-) create mode 100644 substrate/wasm-runtime/polkadot/src/support/storable.rs delete mode 100644 substrate/wasm-runtime/polkadot/src/support/storage.rs delete mode 100644 substrate/wasm-runtime/polkadot/src/support/storagevec.rs diff --git a/substrate/state_machine/src/lib.rs b/substrate/state_machine/src/lib.rs index e94b2b6078..91622c9bc4 100644 --- a/substrate/state_machine/src/lib.rs +++ b/substrate/state_machine/src/lib.rs @@ -244,7 +244,7 @@ mod tests { fn set_storage(&mut self, key: Vec, value: Vec) { self.storage.insert(key, value); } - + fn chain_id(&self) -> u64 { 42 } } diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 4a1302a756..7e8cc2233e 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -12,7 +12,7 @@ mod codec; mod support; mod runtime; pub use codec::{endiansensitive, streamreader, joiner, slicable, keyedvec}; -pub use support::{primitives, function, environment, storage, storagevec}; +pub use support::{primitives, function, environment, storable}; #[cfg(test)] pub use support::{testing, statichex}; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs b/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs index b773e7e1e6..02bf288493 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs @@ -1,5 +1,5 @@ use runtime_support::Vec; -use storagevec::StorageVec; +use storable::StorageVec; use primitives::SessionKey; struct AuthorityStorageVec {} diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs index 8e133ad563..66309becaf 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -1,7 +1,6 @@ use runtime_support::Vec; use keyedvec::KeyedVec; -use storage::Storage; -use storagevec::StorageVec; +use storable::{kill, Storable, StorageVec}; use primitives::{AccountID, SessionKey, BlockNumber}; use runtime::{system, staking, consensus}; @@ -38,7 +37,7 @@ pub fn set_validators(new: &[AccountID]) { /// The number of blocks in each session. pub fn length() -> BlockNumber { - Storage::into(b"ses\0bps") + Storable::lookup_default(b"ses\0bps") } /// Hook to be called prior to transaction processing. @@ -62,11 +61,13 @@ pub fn post_transactions() { /// Move onto next session: register the new authority set. fn next_session() { - // TODO: Call set_authorities() with any new authorities. validators().iter().enumerate().for_each(|(i, v)| { let k = v.to_keyed_vec(b"ses\0nxt\0"); - if let Some(n) = Storage::try_into(&k) { + if let Some(n) = Storable::lookup(&k) { consensus::set_authority(i as u32, &n); + kill(&k); } - }) + }); } + +// TODO: tests diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index ea2116b035..29d6ac0272 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -1,5 +1,5 @@ use keyedvec::KeyedVec; -use storage::Storage; +use storable::Storable; use primitives::{BlockNumber, Balance, AccountID}; use runtime::{system, session}; @@ -10,7 +10,7 @@ use runtime::{system, session}; /// The length of a staking era in sessions. pub fn lockup_eras() -> BlockNumber { - Storage::into(b"sta\0lpe") + Storable::lookup_default(b"sta\0lpe") } /// The length of a staking era in blocks. @@ -20,12 +20,12 @@ pub fn era_length() -> BlockNumber { /// The length of a staking era in sessions. pub fn sessions_per_era() -> BlockNumber { - Storage::into(b"sta\0spe") + Storable::lookup_default(b"sta\0spe") } /// The current era index. pub fn current_era() -> BlockNumber { - Storage::into(b"sta\0era") + Storable::lookup_default(b"sta\0era") } /// The current era index. @@ -35,7 +35,7 @@ pub fn set_current_era(new: BlockNumber) { /// The block number at which the era length last changed. pub fn last_era_length_change() -> BlockNumber { - Storage::into(b"sta\0lec") + Storable::lookup_default(b"sta\0lec") } /// Set a new era length. Won't kick in until the next era change (at current length). @@ -51,7 +51,7 @@ fn next_era() { set_current_era(current_era() + 1); // Enact era length change. - let next_spe: u64 = Storage::into(b"sta\0nse"); + let next_spe: u64 = Storable::lookup_default(b"sta\0nse"); if next_spe > 0 && next_spe != sessions_per_era() { next_spe.store(b"sta\0spe"); system::block_number().store(b"sta\0lec"); @@ -63,16 +63,16 @@ fn next_era() { /// The balance of a given account. pub fn balance_inactive(who: &AccountID) -> Balance { - Storage::into(&who.to_keyed_vec(b"sta\0bal\0")) + Storable::lookup_default(&who.to_keyed_vec(b"sta\0bal\0")) } /// Transfer some unlocked staking balance to another staker. pub fn transfer_inactive(transactor: &AccountID, dest: &AccountID, value: Balance) { let from_key = transactor.to_keyed_vec(b"sta\0bal\0"); - let from_balance: Balance = Storage::into(&from_key); + let from_balance: Balance = Storable::lookup_default(&from_key); assert!(from_balance >= value); let to_key = dest.to_keyed_vec(b"sta\0bal\0"); - let to_balance: Balance = Storage::into(&to_key); + let to_balance: Balance = Storable::lookup_default(&to_key); assert!(to_balance + value > to_balance); // no overflow (from_balance - value).store(&from_key); (to_balance + value).store(&to_key); diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index d7abd1835a..f6be199625 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -1,6 +1,6 @@ use primitives::{Block, BlockNumber, Hash, UncheckedTransaction, TxOrder, Hashable}; use runtime_support::{Vec, swap}; -use storage::Storage; +use storable::Storable; use keyedvec::KeyedVec; use environment::with_env; use runtime::session; @@ -12,7 +12,7 @@ pub fn block_number() -> BlockNumber { /// Get the block hash of a given block (uses storage). pub fn block_hash(number: BlockNumber) -> Hash { - Storage::into(&number.to_keyed_vec(b"sys\0old\0")) + Storable::lookup_default(&number.to_keyed_vec(b"sys\0old\0")) } /// Deposits a log and ensures it matches the blocks log data. @@ -69,7 +69,7 @@ pub fn execute_transaction(utx: &UncheckedTransaction) { // check nonce let nonce_key = tx.signed.to_keyed_vec(b"sys\0non\0"); - let expected_nonce: TxOrder = Storage::into(&nonce_key); + let expected_nonce: TxOrder = Storable::lookup_default(&nonce_key); assert!(tx.nonce == expected_nonce, "All transactions should have the correct nonce"); // increment nonce in storage diff --git a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs index e0f3d2c04e..2232843b07 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs @@ -1,8 +1,8 @@ use primitives::Timestamp; -use storage::Storage; +use storable::Storable; pub fn get() -> Timestamp { - Storage::into(b"tim\0val") + Storable::lookup_default(b"tim\0val") } pub fn set(now: Timestamp) { diff --git a/substrate/wasm-runtime/polkadot/src/support/mod.rs b/substrate/wasm-runtime/polkadot/src/support/mod.rs index e4dae46c40..802476cc1b 100644 --- a/substrate/wasm-runtime/polkadot/src/support/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/support/mod.rs @@ -1,8 +1,7 @@ pub mod primitives; pub mod function; pub mod environment; -pub mod storage; -pub mod storagevec; +pub mod storable; #[cfg(test)] pub mod statichex; diff --git a/substrate/wasm-runtime/polkadot/src/support/storable.rs b/substrate/wasm-runtime/polkadot/src/support/storable.rs new file mode 100644 index 0000000000..7d45587338 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/support/storable.rs @@ -0,0 +1,62 @@ +use slicable::Slicable; +use endiansensitive::EndianSensitive; +use keyedvec::KeyedVec; +use runtime_support; + +pub trait Storable { + fn lookup_default(key: &[u8]) -> Self where Self: Sized + Default { Self::lookup(key).unwrap_or_else(Default::default) } + fn lookup(_key: &[u8]) -> Option where Self: Sized { unimplemented!() } + fn store(&self, key: &[u8]); +} + +pub fn kill(key: &[u8]) { runtime_support::set_storage(key, b""); } + +impl Storable for T { + fn lookup(key: &[u8]) -> Option { + Slicable::set_as_slice(|out| runtime_support::read_storage(key, out) == out.len()) + } + fn store(&self, key: &[u8]) { + self.as_slice_then(|slice| runtime_support::set_storage(key, slice)); + } +} + +impl Storable for [u8] { + fn store(&self, key: &[u8]) { + runtime_support::set_storage(key, self) + } +} + +/// A trait to conveniently store a vector of storable data. +// TODO: add iterator support +pub trait StorageVec { + type Item: Default + Sized + Storable; + const PREFIX: &'static [u8]; + + /// Get the current set of items. + fn items() -> Vec { + (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) { + item.store(&index.to_keyed_vec(Self::PREFIX)); + } + + fn item(index: u32) -> Self::Item { + Storable::lookup_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())); + count.store(&b"len".to_keyed_vec(Self::PREFIX)); + } + + fn count() -> u32 { + Storable::lookup_default(&b"len".to_keyed_vec(Self::PREFIX)) + } +} diff --git a/substrate/wasm-runtime/polkadot/src/support/storage.rs b/substrate/wasm-runtime/polkadot/src/support/storage.rs deleted file mode 100644 index 7c9696bc11..0000000000 --- a/substrate/wasm-runtime/polkadot/src/support/storage.rs +++ /dev/null @@ -1,24 +0,0 @@ -use slicable::Slicable; -use endiansensitive::EndianSensitive; -use runtime_support; - -pub trait Storage { - fn into(key: &[u8]) -> Self where Self: Sized + Default { Self::try_into(key).unwrap_or_else(Default::default) } - fn try_into(_key: &[u8]) -> Option where Self: Sized { unimplemented!() } - fn store(&self, key: &[u8]); -} - -impl Storage for T { - fn try_into(key: &[u8]) -> Option { - Slicable::set_as_slice(|out| runtime_support::read_storage(key, out) == out.len()) - } - fn store(&self, key: &[u8]) { - self.as_slice_then(|slice| runtime_support::set_storage(key, slice)); - } -} - -impl Storage for [u8] { - fn store(&self, key: &[u8]) { - runtime_support::set_storage(key, self) - } -} diff --git a/substrate/wasm-runtime/polkadot/src/support/storagevec.rs b/substrate/wasm-runtime/polkadot/src/support/storagevec.rs deleted file mode 100644 index ac0ded3a56..0000000000 --- a/substrate/wasm-runtime/polkadot/src/support/storagevec.rs +++ /dev/null @@ -1,38 +0,0 @@ -use runtime_support::Vec; -use keyedvec::KeyedVec; -use storage::Storage; - -/// A trait to conveniently store a vector of storable data. -// TODO: add iterator support -pub trait StorageVec { - type Item: Default + Sized + Storage; - const PREFIX: &'static [u8]; - - /// Get the current set of items. - fn items() -> Vec { - (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) { - item.store(&index.to_keyed_vec(Self::PREFIX)); - } - - fn item(index: u32) -> Self::Item { - Storage::into(&index.to_keyed_vec(Self::PREFIX)) - } - - fn set_count(count: u32) { - (count..Self::count()).for_each(|i| Self::set_item(i, &Self::Item::default())); - count.store(&b"len".to_keyed_vec(Self::PREFIX)); - } - - fn count() -> u32 { - Storage::into(&b"len".to_keyed_vec(Self::PREFIX)) - } -} From 748ee548701fb62c973bff534dd177f2d5e44a7c Mon Sep 17 00:00:00 2001 From: Gav Date: Fri, 19 Jan 2018 12:34:51 +0100 Subject: [PATCH 063/112] Test sessions. --- .../polkadot/src/runtime/session.rs | 71 +++++++++++++++---- .../polkadot/src/runtime/staking.rs | 26 +++---- .../polkadot/src/runtime/system.rs | 7 +- 3 files changed, 73 insertions(+), 31 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs index 66309becaf..ee88937ead 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -40,27 +40,20 @@ pub fn length() -> BlockNumber { Storable::lookup_default(b"ses\0bps") } -/// Hook to be called prior to transaction processing. -pub fn pre_transactions() { - staking::pre_transactions(); -} - -/// Hook to be called after to transaction processing. -pub fn post_transactions() { - staking::post_transactions(); - +/// Hook to be called after transaction processing. +pub fn check_rotate_session() { // do this last, after the staking system has had chance to switch out the authorities for the // new set. // check block number and call next_session if necessary. if system::block_number() % length() == 0 { - next_session(); + rotate_session(); } } -// PRIVATE (not available) +// PRIVATE (not available for use externally) /// Move onto next session: register the new authority set. -fn next_session() { +fn rotate_session() { validators().iter().enumerate().for_each(|(i, v)| { let k = v.to_keyed_vec(b"ses\0nxt\0"); if let Some(n) = Storable::lookup(&k) { @@ -70,4 +63,56 @@ fn next_session() { }); } -// TODO: tests +#[cfg(test)] +mod tests { + use runtime_support::with_externalities; + use keyedvec::KeyedVec; + use joiner::Joiner; + use testing::{one, two, TestExternalities}; + use primitives::AccountID; + use runtime::{consensus, session}; + use environment::with_env; + + #[test] + fn session_change_should_work() { + let mut t = TestExternalities { storage: map![ + b"ses\0bps".to_vec() => vec![].join(&2u64), + // the validators (10, 20, ...) + b"ses\0key\0len".to_vec() => vec![].join(&2u32), + 0u32.to_keyed_vec(b"ses\0key\0") => vec![10; 32], + 1u32.to_keyed_vec(b"ses\0key\0") => vec![20; 32], + // initial session keys (11, 21, ...) + b"con\0aut\0len".to_vec() => vec![].join(&2u32), + 0u32.to_keyed_vec(b"con\0aut\0") => vec![11; 32], + 1u32.to_keyed_vec(b"con\0aut\0") => vec![21; 32] + ], }; + with_externalities(&mut t, || { + assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); + assert_eq!(session::length(), 2u64); + assert_eq!(session::validators(), vec![[10u8; 32], [20u8; 32]]); + + // Block 1: No change + with_env(|e| e.block_number = 1); + session::check_rotate_session(); + assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); + + // Block 2: Session rollover, but no change. + with_env(|e| e.block_number = 2); + session::check_rotate_session(); + assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); + + // Block 3: Set new key for validator 2; no visible change. + with_env(|e| e.block_number = 3); + session::set_key(&[20; 32], &[22; 32]); + assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); + + session::check_rotate_session(); + assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); + + // Block 4: Session rollover, authority 2 changes. + with_env(|e| e.block_number = 4); + session::check_rotate_session(); + assert_eq!(consensus::authorities(), vec![[11u8; 32], [22u8; 32]]); + }); + } +} diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index 29d6ac0272..127b7041ad 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -46,7 +46,7 @@ pub fn set_sessions_per_era(new: BlockNumber) { /// The era has changed - enact new staking set. /// /// NOTE: This always happens on a session change. -fn next_era() { +fn new_era() { // Increment current era. set_current_era(current_era() + 1); @@ -92,15 +92,11 @@ pub fn unstake(_transactor: &AccountID) { // TODO: record the desire for `_transactor` to deactivate their stake. } -/// Hook to be called prior to transaction processing. -pub fn pre_transactions() { -} - /// Hook to be called after to transaction processing. -pub fn post_transactions() { - // check block number and call next_era if necessary. +pub fn check_new_era() { + // check block number and call new_era if necessary. if (system::block_number() - last_era_length_change()) % era_length() == 0 { - next_era(); + new_era(); } } @@ -128,14 +124,14 @@ mod tests { // Block 1: No change. with_env(|e| e.block_number = 1); - staking::post_transactions(); + staking::check_new_era(); assert_eq!(staking::sessions_per_era(), 2u64); assert_eq!(staking::last_era_length_change(), 0u64); assert_eq!(staking::current_era(), 0u64); // Block 2: Simple era change. with_env(|e| e.block_number = 2); - staking::post_transactions(); + staking::check_new_era(); assert_eq!(staking::sessions_per_era(), 2u64); assert_eq!(staking::last_era_length_change(), 0u64); assert_eq!(staking::current_era(), 1u64); @@ -143,35 +139,35 @@ mod tests { // Block 3: Schedule an era length change; no visible changes. with_env(|e| e.block_number = 3); staking::set_sessions_per_era(3); - staking::post_transactions(); + staking::check_new_era(); assert_eq!(staking::sessions_per_era(), 2u64); assert_eq!(staking::last_era_length_change(), 0u64); assert_eq!(staking::current_era(), 1u64); // Block 4: Era change kicks in. with_env(|e| e.block_number = 4); - staking::post_transactions(); + staking::check_new_era(); assert_eq!(staking::sessions_per_era(), 3u64); assert_eq!(staking::last_era_length_change(), 4u64); assert_eq!(staking::current_era(), 2u64); // Block 5: No change. with_env(|e| e.block_number = 5); - staking::post_transactions(); + staking::check_new_era(); assert_eq!(staking::sessions_per_era(), 3u64); assert_eq!(staking::last_era_length_change(), 4u64); assert_eq!(staking::current_era(), 2u64); // Block 6: No change. with_env(|e| e.block_number = 6); - staking::post_transactions(); + staking::check_new_era(); assert_eq!(staking::sessions_per_era(), 3u64); assert_eq!(staking::last_era_length_change(), 4u64); assert_eq!(staking::current_era(), 2u64); // Block 7: Era increment. with_env(|e| e.block_number = 7); - staking::post_transactions(); + staking::check_new_era(); assert_eq!(staking::sessions_per_era(), 3u64); assert_eq!(staking::last_era_length_change(), 4u64); assert_eq!(staking::current_era(), 3u64); diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index f6be199625..0b3b8a590b 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -3,7 +3,7 @@ use runtime_support::{Vec, swap}; use storable::Storable; use keyedvec::KeyedVec; use environment::with_env; -use runtime::session; +use runtime::{staking, session}; /// The current block number being processed. Set by `execute_block`. pub fn block_number() -> BlockNumber { @@ -48,9 +48,10 @@ pub fn execute_block(mut block: Block) { header.keccak256().store(&header_hash_key); // execute transactions - session::pre_transactions(); block.transactions.iter().for_each(execute_transaction); - session::post_transactions(); + + staking::check_new_era(); + session::check_rotate_session(); // any final checks final_checks(&block); From c29313c6180e9f13b9d0b1f672fe26a383831c9f Mon Sep 17 00:00:00 2001 From: Gav Date: Fri, 19 Jan 2018 14:17:56 +0100 Subject: [PATCH 064/112] Introduce better hashing. - Blake2 for secure hashing - XX for fast hashing --- substrate/Cargo.lock | 41 +++++++- substrate/executor/Cargo.toml | 1 - substrate/executor/src/lib.rs | 1 - substrate/executor/src/wasm_executor.rs | 66 ++++++++++-- substrate/native-runtime/support/Cargo.toml | 1 - substrate/native-runtime/support/src/lib.rs | 3 +- substrate/primitives/Cargo.toml | 4 +- substrate/primitives/src/ed25519.rs | 79 ++++++++------- substrate/primitives/src/hash.rs | 4 +- substrate/primitives/src/lib.rs | 94 +++++++++++++++++- substrate/state_machine/Cargo.toml | 1 - substrate/state_machine/src/lib.rs | 1 - .../polkadot/src/runtime/session.rs | 16 +-- .../polkadot/src/runtime/staking.rs | 10 +- .../polkadot/src/runtime/system.rs | 6 +- .../polkadot/src/runtime/timestamp.rs | 4 +- .../polkadot/src/support/primitives.rs | 16 ++- .../polkadot/src/support/storable.rs | 10 +- substrate/wasm-runtime/support/src/lib.rs | 30 +++++- .../release/runtime_polkadot.compact.wasm | Bin 5276 -> 18522 bytes .../release/runtime_polkadot.wasm | Bin 5364 -> 18609 bytes .../release/runtime_test.compact.wasm | Bin 962 -> 1460 bytes .../release/runtime_test.wasm | Bin 1079 -> 1576 bytes substrate/wasm-runtime/test/src/lib.rs | 17 +++- 24 files changed, 307 insertions(+), 98 deletions(-) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 7d5f50ddc4..72a5687799 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -20,6 +20,14 @@ dependencies = [ "odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "arrayvec" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "assert_matches" version = "1.1.0" @@ -90,6 +98,15 @@ name = "bitflags" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "blake2-rfc" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "byteorder" version = "1.1.0" @@ -138,6 +155,11 @@ dependencies = [ "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "constant_time_eq" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "crunchy" version = "0.1.6" @@ -710,13 +732,14 @@ dependencies = [ "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "polkadot-primitives" version = "0.1.0" dependencies = [ + "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "fixed-hash 0.1.0 (git+https://github.com/paritytech/primitives.git)", "polkadot-serializer 0.1.0", @@ -725,7 +748,7 @@ dependencies = [ "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "uint 0.1.0 (git+https://github.com/paritytech/primitives.git)", "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -767,7 +790,6 @@ version = "0.1.0" dependencies = [ "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "hashdb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "memorydb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "patricia-trie 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "polkadot-primitives 0.1.0", @@ -898,7 +920,6 @@ dependencies = [ "parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "polkadot-primitives 0.1.0", "polkadot-state-machine 0.1.0", - "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1151,6 +1172,14 @@ dependencies = [ "rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "twox-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "uint" version = "0.1.0" @@ -1235,6 +1264,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" "checksum arrayvec 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "e003cbf6e0e1c43a0fc8df2ea8ea24174514d35cbcf60c35ca6112e0139f65e2" +"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" "checksum assert_matches 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e772942dccdf11b368c31e044e4fca9189f80a773d2f0808379de65894cbf57" "checksum atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21e50800ec991574876040fff8ee46b136a53e985286fbe6a3bdfe6421b78860" "checksum backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "99f2ce94e22b8e664d95c57fff45b98a966c2252b60691d0b7aeeccd88d70983" @@ -1243,12 +1273,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5442186ef6560f30f1ee4b9c1e4c87a35a6879d3644550cc248ec2b955eb5fcd" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" +"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" "checksum byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff81738b726f5d099632ceaffe7fb65b90212e8dce59d518729e7e8634032d3d" "checksum bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d828f97b58cc5de3e40c421d0cf2132d6b2da4ee0e11b8632fa838f0f9333ad6" "checksum cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b13a57efd6b30ecd6598ebdb302cca617930b5470647570468a65d12ef9719" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" "checksum clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1b8c532887f1a292d17de05ae858a8fe50a301e196f9ef0ddb7ccd0d1d00f180" "checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd" +"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" "checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8" @@ -1351,6 +1383,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fbb47ae81353c63c487030659494b295f6cb6576242f907f203473b191b0389" "checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162" "checksum triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9291c7f0fae44858b5e087dd462afb382354120003778f1695b44aab98c7abd7" +"checksum twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "475352206e7a290c5fccc27624a163e8d0d115f7bb60ca18a64fc9ce056d7435" "checksum uint 0.1.0 (git+https://github.com/paritytech/primitives.git)" = "" "checksum unicase 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2e01da42520092d0cd2d6ac3ae69eb21a22ad43ff195676b86f8c37f487d6b80" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" diff --git a/substrate/executor/Cargo.toml b/substrate/executor/Cargo.toml index 2d124f60ac..0401bd4c77 100644 --- a/substrate/executor/Cargo.toml +++ b/substrate/executor/Cargo.toml @@ -12,7 +12,6 @@ serde = "1.0" serde_derive = "1.0" parity-wasm = "0.15.0" byteorder = "1.1" -tiny-keccak = "1.3" rustc-hex = "1.0.0" [dev-dependencies] diff --git a/substrate/executor/src/lib.rs b/substrate/executor/src/lib.rs index 3c54d25efb..f1da582538 100644 --- a/substrate/executor/src/lib.rs +++ b/substrate/executor/src/lib.rs @@ -33,7 +33,6 @@ extern crate polkadot_state_machine as state_machine; extern crate serde; extern crate parity_wasm; extern crate byteorder; -extern crate tiny_keccak; extern crate rustc_hex; #[macro_use] diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index 07056b1df7..c0c638fa3d 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -26,8 +26,7 @@ use state_machine::{Externalities, CodeExecutor}; use error::{Error, ErrorKind, Result}; use wasm_utils::{MemoryInstance, UserDefinedElements, AddModuleWithoutFullDependentInstance}; -use tiny_keccak; -use primitives::ed25519; +use primitives::{ed25519, blake2_256, twox_128, twox_256}; struct Heap { end: u32, @@ -141,10 +140,28 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, ext_chain_id() -> u64 => { this.ext.chain_id() }, - ext_keccak256(data: *const u8, len: u32, out: *mut u8) => { + ext_twox_128(data: *const u8, len: u32, out: *mut u8) => { let result = if let Ok(value) = this.memory.get(data, len as usize) { - tiny_keccak::keccak256(&value) + twox_128(&value) + } else { + [0; 16] + }; + let _ = this.memory.set(out, &result); + }, + ext_twox_256(data: *const u8, len: u32, out: *mut u8) => { + let result = + if let Ok(value) = this.memory.get(data, len as usize) { + twox_256(&value) + } else { + [0; 32] + }; + let _ = this.memory.set(out, &result); + }, + ext_blake2_256(data: *const u8, len: u32, out: *mut u8) => { + let result = + if let Ok(value) = this.memory.get(data, len as usize) { + blake2_256(&value) } else { [0; 32] }; @@ -223,6 +240,7 @@ mod tests { use super::*; use rustc_hex::FromHex; + use primitives::ed25519::hexdisplay::HexDisplay; #[derive(Debug, Default)] struct TestExternalities { @@ -261,16 +279,44 @@ mod tests { } #[test] - fn keccak256_should_work() { + fn blake2_256_should_work() { let mut ext = TestExternalities::default(); let test_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); assert_eq!( - WasmExecutor.call(&mut ext, &test_code[..], "test_keccak256", &CallData(b"".to_vec())).unwrap(), - FromHex::from_hex("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").unwrap() + WasmExecutor.call(&mut ext, &test_code[..], "test_blake2_256", &CallData(b"".to_vec())).unwrap(), + FromHex::from_hex("0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8").unwrap() ); assert_eq!( - WasmExecutor.call(&mut ext, &test_code[..], "test_keccak256", &CallData(b"Hello world!".to_vec())).unwrap(), - FromHex::from_hex("ecd0e108a98e192af1d2c25055f4e3bed784b5c877204e73219a5203251feaab").unwrap() + WasmExecutor.call(&mut ext, &test_code[..], "test_blake2_256", &CallData(b"Hello world!".to_vec())).unwrap(), + FromHex::from_hex("3fbc092db9350757e2ab4f7ee9792bfcd2f5220ada5a4bc684487f60c6034369").unwrap() + ); + } + + #[test] + fn twox_256_should_work() { + let mut ext = TestExternalities::default(); + let test_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); + assert_eq!( + WasmExecutor.call(&mut ext, &test_code[..], "test_twox_256", &CallData(b"".to_vec())).unwrap(), + FromHex::from_hex("99e9d85137db46ef4bbea33613baafd56f963c64b1f3685a4eb4abd67ff6203a").unwrap() + ); + assert_eq!( + WasmExecutor.call(&mut ext, &test_code[..], "test_twox_256", &CallData(b"Hello world!".to_vec())).unwrap(), + FromHex::from_hex("b27dfd7f223f177f2a13647b533599af0c07f68bda23d96d059da2b451a35a74").unwrap() + ); + } + + #[test] + fn twox_128_should_work() { + let mut ext = TestExternalities::default(); + let test_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); + assert_eq!( + WasmExecutor.call(&mut ext, &test_code[..], "test_twox_128", &CallData(b"".to_vec())).unwrap(), + FromHex::from_hex("99e9d85137db46ef4bbea33613baafd5").unwrap() + ); + assert_eq!( + WasmExecutor.call(&mut ext, &test_code[..], "test_twox_128", &CallData(b"Hello world!".to_vec())).unwrap(), + FromHex::from_hex("b27dfd7f223f177f2a13647b533599af").unwrap() ); } @@ -278,7 +324,7 @@ mod tests { fn ed25519_verify_should_work() { let mut ext = TestExternalities::default(); let test_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); - let key = ed25519::Pair::from_seed(&tiny_keccak::keccak256(b"test")); + let key = ed25519::Pair::from_seed(&blake2_256(b"test")); let sig = key.sign(b"all ok!"); let mut calldata = vec![]; calldata.extend_from_slice(key.public().as_ref()); diff --git a/substrate/native-runtime/support/Cargo.toml b/substrate/native-runtime/support/Cargo.toml index f576037bd2..1c24c014e6 100644 --- a/substrate/native-runtime/support/Cargo.toml +++ b/substrate/native-runtime/support/Cargo.toml @@ -11,5 +11,4 @@ lazy_static = "1.0.0" parking_lot = "0.5" polkadot-state-machine = { path = "../../state_machine" , version = "0.1" } environmental = { path = "../../environmental", version = "0.1.0" } -tiny-keccak = "1.3" polkadot-primitives = { path = "../../primitives", version = "0.1.0" } diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index aaa323f98d..caa7f3b272 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -1,7 +1,6 @@ #[macro_use] extern crate environmental; extern crate polkadot_state_machine; -extern crate tiny_keccak; extern crate polkadot_primitives as primitives; use std::fmt; @@ -76,7 +75,7 @@ pub fn chain_id() -> u64 { } /// Conduct a Keccak-256 hash of the given data. -pub use tiny_keccak::keccak256; +pub use primitives::{blake2_256, twox_128, twox_256}; /// Verify a ed25519 signature. pub fn ed25519_verify(sig: &[u8; 64], msg: &[u8], pubkey: &[u8; 32]) -> bool { diff --git a/substrate/primitives/Cargo.toml b/substrate/primitives/Cargo.toml index 045afba827..77eccdea88 100644 --- a/substrate/primitives/Cargo.toml +++ b/substrate/primitives/Cargo.toml @@ -9,10 +9,12 @@ fixed-hash = { git = "https://github.com/paritytech/primitives.git" } rustc-hex = "1.0" serde = "1.0" serde_derive = "1.0" -tiny-keccak = "1.3" uint = { git = "https://github.com/paritytech/primitives.git" } ring = "0.12" untrusted = "0.5" +twox-hash = "1.1.0" +byteorder = "1.1" +blake2-rfc = "0.2.18" [dev-dependencies] polkadot-serializer = { path = "../serializer", version = "0.1" } diff --git a/substrate/primitives/src/ed25519.rs b/substrate/primitives/src/ed25519.rs index 2630f858d2..e9ac7e473c 100644 --- a/substrate/primitives/src/ed25519.rs +++ b/substrate/primitives/src/ed25519.rs @@ -166,44 +166,53 @@ impl PartialEq for Signature { } } +pub mod hexdisplay { + + pub struct HexDisplay<'a>(&'a [u8]); + + impl<'a> HexDisplay<'a> { + pub fn from(d: &'a AsBytesRef) -> Self { HexDisplay(d.as_bytes_ref()) } + } + + impl<'a> ::std::fmt::Display for HexDisplay<'a> { + fn fmt(&self, fmtr: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { + for byte in self.0 { + try!( fmtr.write_fmt(format_args!("{:02x}", byte))); + } + Ok(()) + } + } + + pub trait AsBytesRef { + fn as_bytes_ref(&self) -> &[u8]; + } + + impl AsBytesRef for [u8] { + fn as_bytes_ref(&self) -> &[u8] { &self } + } + + impl AsBytesRef for Vec { + fn as_bytes_ref(&self) -> &[u8] { &self } + } + + macro_rules! impl_non_endians { + ( $( $t:ty ),* ) => { $( + impl AsBytesRef for $t { + fn as_bytes_ref(&self) -> &[u8] { &self[..] } + } + )* } + } + + impl_non_endians!([u8; 1], [u8; 2], [u8; 3], [u8; 4], [u8; 5], [u8; 6], [u8; 7], [u8; 8], + [u8; 10], [u8; 12], [u8; 14], [u8; 16], [u8; 20], [u8; 24], [u8; 28], [u8; 32], [u8; 40], + [u8; 48], [u8; 56], [u8; 64], [u8; 80], [u8; 96], [u8; 112], [u8; 128]); + +} + #[cfg(test)] mod test { use super::*; - -pub struct HexDisplay<'a>(&'a [u8]); - -impl<'a> HexDisplay<'a> { - pub fn from(d: &'a AsBytesRef) -> Self { HexDisplay(d.as_bytes_ref()) } -} - -impl<'a> ::std::fmt::Display for HexDisplay<'a> { - fn fmt(&self, fmtr: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { - for byte in self.0 { - try!( fmtr.write_fmt(format_args!("{:02x}", byte))); - } - Ok(()) - } -} - -pub trait AsBytesRef { - fn as_bytes_ref(&self) -> &[u8]; -} - -impl AsBytesRef for [u8] { - fn as_bytes_ref(&self) -> &[u8] { &self } -} - -macro_rules! impl_non_endians { - ( $( $t:ty ),* ) => { $( - impl AsBytesRef for $t { - fn as_bytes_ref(&self) -> &[u8] { &self[..] } - } - )* } -} - -impl_non_endians!([u8; 1], [u8; 2], [u8; 3], [u8; 4], [u8; 5], [u8; 6], [u8; 7], [u8; 8], - [u8; 10], [u8; 12], [u8; 14], [u8; 16], [u8; 20], [u8; 24], [u8; 28], [u8; 32], [u8; 40], - [u8; 48], [u8; 56], [u8; 64], [u8; 80], [u8; 96], [u8; 112], [u8; 128]); + use super::hexdisplay::HexDisplay; #[test] fn test_vector_should_work() { diff --git a/substrate/primitives/src/hash.rs b/substrate/primitives/src/hash.rs index cef573f6f2..0b56d5757f 100644 --- a/substrate/primitives/src/hash.rs +++ b/substrate/primitives/src/hash.rs @@ -41,8 +41,8 @@ impl_hash!(H160, 20); impl_serde!(H160, 20); impl_hash!(H256, 32); impl_serde!(H256, 32); -impl_hash!(H520, 65); -impl_serde!(H520, 65); +impl_hash!(H512, 64); +impl_serde!(H512, 64); #[cfg(test)] mod tests { diff --git a/substrate/primitives/src/lib.rs b/substrate/primitives/src/lib.rs index fc26658200..cb7606add2 100644 --- a/substrate/primitives/src/lib.rs +++ b/substrate/primitives/src/lib.rs @@ -20,9 +20,11 @@ extern crate rustc_hex; extern crate serde; -extern crate tiny_keccak; extern crate ring; extern crate untrusted; +extern crate twox_hash; +extern crate byteorder; +extern crate blake2_rfc; #[macro_use] extern crate crunchy; @@ -53,12 +55,98 @@ pub mod ed25519; /// Alias to 160-bit hash when used in the context of an account address. pub type Address = hash::H160; /// Alias to 520-bit hash when used in the context of a signature. -pub type Signature = hash::H520; +pub type Signature = hash::H512; pub use self::hash::{H160, H256}; pub use self::uint::{U256, U512}; /// A hash function. pub fn hash(data: &[u8]) -> hash::H256 { - tiny_keccak::keccak256(data).into() + blake2_256(data).into() +} + +/// Do a Blake2 512-bit hash and place result in `dest`. +pub fn blake2_512_into(data: &[u8], dest: &mut[u8; 64]) { + dest.copy_from_slice(blake2_rfc::blake2b::blake2b(64, &[], data).as_bytes()); +} + +/// Do a Blake2 512-bit hash and return result. +pub fn blake2_512(data: &[u8]) -> [u8; 64] { + let mut r: [u8; 64] = unsafe { std::mem::uninitialized() }; + blake2_512_into(data, &mut r); + r +} + +/// Do a Blake2 256-bit hash and place result in `dest`. +pub fn blake2_256_into(data: &[u8], dest: &mut[u8; 32]) { + dest.copy_from_slice(blake2_rfc::blake2b::blake2b(32, &[], data).as_bytes()); +} + +/// Do a Blake2 256-bit hash and return result. +pub fn blake2_256(data: &[u8]) -> [u8; 32] { + let mut r: [u8; 32] = unsafe { std::mem::uninitialized() }; + blake2_256_into(data, &mut r); + r +} + +/// Do a Blake2 128-bit hash and place result in `dest`. +pub fn blake2_128_into(data: &[u8], dest: &mut[u8; 16]) { + dest.copy_from_slice(blake2_rfc::blake2b::blake2b(16, &[], data).as_bytes()); +} + +/// Do a Blake2 128-bit hash and return result. +pub fn blake2_128(data: &[u8]) -> [u8; 16] { + let mut r: [u8; 16] = unsafe { std::mem::uninitialized() }; + blake2_128_into(data, &mut r); + r +} + +/// Do a XX 128-bit hash and place result in `dest`. +pub fn twox_128_into(data: &[u8], dest: &mut [u8; 16]) { + use ::std::hash::Hasher; + let mut h0 = twox_hash::XxHash::with_seed(0); + let mut h1 = twox_hash::XxHash::with_seed(1); + h0.write(data); + h1.write(data); + let r0 = h0.finish(); + let r1 = h1.finish(); + use byteorder::{ByteOrder, LittleEndian}; + LittleEndian::write_u64(&mut dest[0..8], r0); + LittleEndian::write_u64(&mut dest[8..16], r1); +} + +/// Do a XX 128-bit hash and return result. +pub fn twox_128(data: &[u8]) -> [u8; 16] { + let mut r: [u8; 16] = unsafe { std::mem::uninitialized() }; + twox_128_into(data, &mut r); + r +} + +/// Do a XX 256-bit hash and place result in `dest`. +pub fn twox_256_into(data: &[u8], dest: &mut [u8; 32]) { + use ::std::hash::Hasher; + use byteorder::{ByteOrder, LittleEndian}; + let mut h0 = twox_hash::XxHash::with_seed(0); + let mut h1 = twox_hash::XxHash::with_seed(1); + let mut h2 = twox_hash::XxHash::with_seed(2); + let mut h3 = twox_hash::XxHash::with_seed(3); + h0.write(data); + h1.write(data); + h2.write(data); + h3.write(data); + let r0 = h0.finish(); + let r1 = h1.finish(); + let r2 = h2.finish(); + let r3 = h3.finish(); + LittleEndian::write_u64(&mut dest[0..8], r0); + LittleEndian::write_u64(&mut dest[8..16], r1); + LittleEndian::write_u64(&mut dest[16..24], r2); + LittleEndian::write_u64(&mut dest[24..32], r3); +} + +/// Do a XX 256-bit hash and return result. +pub fn twox_256(data: &[u8]) -> [u8; 32] { + let mut r: [u8; 32] = unsafe { std::mem::uninitialized() }; + twox_256_into(data, &mut r); + r } diff --git a/substrate/state_machine/Cargo.toml b/substrate/state_machine/Cargo.toml index a0d25c821c..458bae8e1e 100644 --- a/substrate/state_machine/Cargo.toml +++ b/substrate/state_machine/Cargo.toml @@ -7,7 +7,6 @@ description = "Polkadot State Machine" [dependencies] polkadot-primitives = { path = "../primitives", version = "0.1.0" } hashdb = "0.1.1" -keccak-hash = "0.1.0" patricia-trie = "0.1.0" memorydb = "0.1.1" triehash = "0.1" diff --git a/substrate/state_machine/src/lib.rs b/substrate/state_machine/src/lib.rs index 91622c9bc4..cee96a36ad 100644 --- a/substrate/state_machine/src/lib.rs +++ b/substrate/state_machine/src/lib.rs @@ -22,7 +22,6 @@ extern crate polkadot_primitives as primitives; extern crate hashdb; extern crate memorydb; -extern crate keccak_hash; extern crate patricia_trie; extern crate triehash; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs index ee88937ead..412809d6b8 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -65,7 +65,7 @@ fn rotate_session() { #[cfg(test)] mod tests { - use runtime_support::with_externalities; + use runtime_support::{with_externalities, twox_128}; use keyedvec::KeyedVec; use joiner::Joiner; use testing::{one, two, TestExternalities}; @@ -76,15 +76,15 @@ mod tests { #[test] fn session_change_should_work() { let mut t = TestExternalities { storage: map![ - b"ses\0bps".to_vec() => vec![].join(&2u64), + twox_128(b"ses\0bps").to_vec() => vec![].join(&2u64), // the validators (10, 20, ...) - b"ses\0key\0len".to_vec() => vec![].join(&2u32), - 0u32.to_keyed_vec(b"ses\0key\0") => vec![10; 32], - 1u32.to_keyed_vec(b"ses\0key\0") => vec![20; 32], + twox_128(b"ses\0key\0len").to_vec() => vec![].join(&2u32), + twox_128(&0u32.to_keyed_vec(b"ses\0key\0")).to_vec() => vec![10; 32], + twox_128(&1u32.to_keyed_vec(b"ses\0key\0")).to_vec() => vec![20; 32], // initial session keys (11, 21, ...) - b"con\0aut\0len".to_vec() => vec![].join(&2u32), - 0u32.to_keyed_vec(b"con\0aut\0") => vec![11; 32], - 1u32.to_keyed_vec(b"con\0aut\0") => vec![21; 32] + twox_128(b"con\0aut\0len").to_vec() => vec![].join(&2u32), + twox_128(&0u32.to_keyed_vec(b"con\0aut\0")).to_vec() => vec![11; 32], + twox_128(&1u32.to_keyed_vec(b"con\0aut\0")).to_vec() => vec![21; 32] ], }; with_externalities(&mut t, || { assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index 127b7041ad..f3bae42060 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -102,7 +102,7 @@ pub fn check_new_era() { #[cfg(test)] mod tests { - use runtime_support::with_externalities; + use runtime_support::{with_externalities, twox_128}; use keyedvec::KeyedVec; use joiner::Joiner; use testing::{one, two, TestExternalities}; @@ -113,8 +113,8 @@ mod tests { #[test] fn staking_eras_work() { let mut t = TestExternalities { storage: map![ - b"ses\0bps".to_vec() => vec![].join(&1u64), - b"sta\0spe".to_vec() => vec![].join(&2u64) + twox_128(b"ses\0bps").to_vec() => vec![].join(&1u64), + twox_128(b"sta\0spe").to_vec() => vec![].join(&2u64) ], }; with_externalities(&mut t, || { assert_eq!(staking::era_length(), 2u64); @@ -180,7 +180,7 @@ mod tests { let two = two(); let mut t = TestExternalities { storage: map![ - one.to_keyed_vec(b"sta\0bal\0") => vec![].join(&42u64) + twox_128(&one.to_keyed_vec(b"sta\0bal\0")).to_vec() => vec![].join(&42u64) ], }; with_externalities(&mut t, || { @@ -195,7 +195,7 @@ mod tests { let two = two(); let mut t = TestExternalities { storage: map![ - one.to_keyed_vec(b"sta\0bal\0") => vec![].join(&111u64) + twox_128(&one.to_keyed_vec(b"sta\0bal\0")).to_vec() => vec![].join(&111u64) ], }; with_externalities(&mut t, || { diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 0b3b8a590b..0bf300d2b3 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -45,7 +45,7 @@ pub fn execute_block(mut block: Block) { // store the header hash in storage. let header_hash_key = header.number.to_keyed_vec(b"sys\0old\0"); - header.keccak256().store(&header_hash_key); + header.blake2_256().store(&header_hash_key); // execute transactions block.transactions.iter().for_each(execute_transaction); @@ -97,7 +97,7 @@ mod tests { use function::Function; use keyedvec::KeyedVec; use slicable::Slicable; - use runtime_support::with_externalities; + use runtime_support::{with_externalities, twox_128}; use primitives::{UncheckedTransaction, Transaction}; use statichex::StaticHexInto; use runtime::{system, staking}; @@ -109,7 +109,7 @@ mod tests { let two = two(); let mut t = TestExternalities { storage: map![ - one.to_keyed_vec(b"sta\0bal\0") => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + twox_128(&one.to_keyed_vec(b"sta\0bal\0")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] ], }; let tx = UncheckedTransaction { diff --git a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs index 2232843b07..10708a5a3c 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs @@ -13,14 +13,14 @@ pub fn set(now: Timestamp) { mod tests { use joiner::Joiner; use keyedvec::KeyedVec; - use runtime_support::with_externalities; + use runtime_support::{with_externalities, twox_128}; use runtime::timestamp; use testing::TestExternalities; #[test] fn timestamp_works() { let mut t = TestExternalities { storage: map![ - b"tim\0val".to_vec() => vec![].join(&42u64) + twox_128(b"tim\0val").to_vec() => vec![].join(&42u64) ], }; with_externalities(&mut t, || { diff --git a/substrate/wasm-runtime/polkadot/src/support/primitives.rs b/substrate/wasm-runtime/polkadot/src/support/primitives.rs index ecac3fbbd4..fb983bf84e 100644 --- a/substrate/wasm-runtime/polkadot/src/support/primitives.rs +++ b/substrate/wasm-runtime/polkadot/src/support/primitives.rs @@ -3,7 +3,7 @@ use streamreader::StreamReader; use joiner::Joiner; use slicable::{Slicable, NonTrivialSlicable}; use function::Function; -use runtime_support::{size_of, keccak256, ed25519_verify}; +use runtime_support::{size_of, blake2_256, twox_128, twox_256, ed25519_verify}; #[cfg(test)] use std::fmt; @@ -109,12 +109,20 @@ impl Slicable for Transaction { } pub trait Hashable: Sized { - fn keccak256(&self) -> [u8; 32]; + fn blake2_256(&self) -> [u8; 32]; + fn twox_128(&self) -> [u8; 16]; + fn twox_256(&self) -> [u8; 32]; } impl Hashable for T { - fn keccak256(&self) -> [u8; 32] { - keccak256(&self.to_vec()) + fn blake2_256(&self) -> [u8; 32] { + blake2_256(&self.to_vec()) + } + fn twox_128(&self) -> [u8; 16] { + twox_128(&self.to_vec()) + } + fn twox_256(&self) -> [u8; 32] { + twox_256(&self.to_vec()) } } diff --git a/substrate/wasm-runtime/polkadot/src/support/storable.rs b/substrate/wasm-runtime/polkadot/src/support/storable.rs index 7d45587338..177475b2d7 100644 --- a/substrate/wasm-runtime/polkadot/src/support/storable.rs +++ b/substrate/wasm-runtime/polkadot/src/support/storable.rs @@ -1,7 +1,7 @@ use slicable::Slicable; use endiansensitive::EndianSensitive; use keyedvec::KeyedVec; -use runtime_support; +use runtime_support::{self, twox_128, Vec}; pub trait Storable { fn lookup_default(key: &[u8]) -> Self where Self: Sized + Default { Self::lookup(key).unwrap_or_else(Default::default) } @@ -9,20 +9,20 @@ pub trait Storable { fn store(&self, key: &[u8]); } -pub fn kill(key: &[u8]) { runtime_support::set_storage(key, b""); } +pub fn kill(key: &[u8]) { runtime_support::set_storage(&twox_128(key)[..], b""); } impl Storable for T { fn lookup(key: &[u8]) -> Option { - Slicable::set_as_slice(|out| runtime_support::read_storage(key, out) == out.len()) + Slicable::set_as_slice(|out| runtime_support::read_storage(&twox_128(key)[..], out) == out.len()) } fn store(&self, key: &[u8]) { - self.as_slice_then(|slice| runtime_support::set_storage(key, slice)); + self.as_slice_then(|slice| runtime_support::set_storage(&twox_128(key)[..], slice)); } } impl Storable for [u8] { fn store(&self, key: &[u8]) { - runtime_support::set_storage(key, self) + runtime_support::set_storage(&twox_128(key)[..], self) } } diff --git a/substrate/wasm-runtime/support/src/lib.rs b/substrate/wasm-runtime/support/src/lib.rs index 57606a3f1b..bc987ff396 100644 --- a/substrate/wasm-runtime/support/src/lib.rs +++ b/substrate/wasm-runtime/support/src/lib.rs @@ -29,7 +29,9 @@ extern "C" { fn ext_get_allocated_storage(key_data: *const u8, key_len: u32, written_out: *mut u32) -> *mut u8; fn ext_get_storage_into(key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32) -> u32; fn ext_chain_id() -> u64; - fn ext_keccak256(data: *const u8, len: u32, out: *mut u8); + fn ext_blake2_256(data: *const u8, len: u32, out: *mut u8); + fn ext_twox_128(data: *const u8, len: u32, out: *mut u8); + fn ext_twox_256(data: *const u8, len: u32, out: *mut u8); fn ext_ed25519_verify(msg_data: *const u8, msg_len: u32, sig_data: *const u8, pubkey_data: *const u8) -> u32; } @@ -80,12 +82,32 @@ pub fn chain_id() -> u64 { } } -/// Conduct a keccak256 hash. -pub fn keccak256(data: &[u8]) -> [u8; 32] { +/// Conduct a 256-bit Blake2 hash. +pub fn blake2_256(data: &[u8]) -> [u8; 32] { unsafe { let mut result: [u8; 32] = uninitialized(); // guaranteed to write into result. - ext_keccak256(&data[0], data.len() as u32, &mut result[0]); + ext_blake2_256(&data[0], data.len() as u32, &mut result[0]); + result + } +} + +/// Conduct four XX hashes to give a 256-bit result. +pub fn twox_256(data: &[u8]) -> [u8; 32] { + unsafe { + let mut result: [u8; 32] = uninitialized(); + // guaranteed to write into result. + ext_twox_256(&data[0], data.len() as u32, &mut result[0]); + result + } +} + +/// Conduct two XX hashes to give a 256-bit result. +pub fn twox_128(data: &[u8]) -> [u8; 16] { + unsafe { + let mut result: [u8; 16] = uninitialized(); + // guaranteed to write into result. + ext_twox_128(&data[0], data.len() as u32, &mut result[0]); result } } diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm index 658efc37386ac47900dea844825f63fd7c92c24f..dbc3273e1b506a06521aae4b775386774d7353a8 100644 GIT binary patch literal 18522 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 literal 5276 zcmb_gy>A@H6`z^iy$|l~-QL}vMaL@ME{Na=M34*nc(4S6LqJhn7;e(@DC#0S#V!ieD3cy)$3z9xo1$_U_Dg?;R`-mFB56o_e_V;KAX(GPPj-aR2i!l*fV|YaG{$ zmG5=JK&hb7Y_>e3d|!W#H&3g6^Oudr!}-I*qc4n#=8xz5j~4UYTQGfJtqsff#nIlu z@!tO8-r<1?`$vzC7rVFSckUhRK05f#y@T7T(&DV-*MCV_ zKOY;F`FLu{lXsuYXOSY0OrEvKw|bE^sYT7t-b(}WZ$z3DR-_H`DYzLKYNXAM7m9w` za&saGVv{u^&2#cdvVvEA`d%ERJ~d*+_Do2MniHc03i-jx?^`BXnlG)gIJ$3N>ib!5Vtne^mnygG zInD?#wJ}+(MSp(8mB_%DZW>|Hq#g<3@rYQ`u2!`Oob0Sy?s8Ncj zw`pcu=2XMRGiRegUO6iw*l4bpWi8lf)n?hosopZr*vN@9(yq4<5sa)+v$D%tFcMO$ z6tR(KFmfVDoM$@JE~o7?h+rh5wR0jE=~7sV*vJWtY*U*$g>a3c;whx=s^Ye6=2d(6 zmFeJ3i*Qiwm)ada`veMM2`Tklh@T(=JV8r!ZEVna73gpP#?ux9!^31k4=Y%9s1^D6XRI#=f#GXnPMH6{0!)-moY2+P1my{&hQjyo|4Ah18N{}!wKLFZSL`baUt-c@y~uc;5&*Usyq6>88q zm?Qj4)AW{J#VDs>l$aSMwq@Gsv1w(dW)+!%;~HexagJ(42)}__*>8oAj64ynRs2*Y zqZ3I0N&;~r@qWn~F~yq(={bXmf(`0|aUz(gE60goqAnLPF_Zd?rSd_OHGMb{Y}EAO zM6gj)hS+dq5Hroz%n@@A)vOV78TKl^kagS4#eT&cLB$+MvLeGo4;ePY9axfXeW(l1 zQXip4ej#AQfYQF%wk;GDZad_z#dUj|VloqPEYkFD5h6^*0SGT1o4XmNr8(dM2*+l| zq7&_2ZfEU@`HEjKZa8ZkX{4~WNp1;-ux2CmrMU4(87^NWGit7gQ;ZwvCL`MPPINjz zj_#;*5DL`xIjGoUhE;DsEd%ZlLkq?@btQ}3t3!_G8aa9pL5`7;W3E8%VqZaT*3c0I zhTgas`p`iihOjoE{_nPM9<&UP9+t2o;4pfgf;(~w4N;(JY_9e>MvuF*?*e4_F% zh3E;hru7{q|3l^A%aNV3`_h=TtxAU&jkgUVjsUOEy<&H)RF*K%1UVJmhyq3~(NQ#_ zWMZykh$dz#)~JhZpc>Fhb*B4w<|8nEQwpR#$JqMx^QV1aJ^~zE@b~vxWerQx^TSwTjdtZLuz6u zE|n2AuPSv-FR%+os{?t~w*Jp0Tu4%9q%`pa7cEQ-D6H0xuIj}#{RD~0(Zx?JD%Ekn zv3j2dtLjhmHGRhVXf|9}3xFNgrv9q#8FV}JZhDEjX-pAvx(!kR(1F9qxyOlD>>a

      45kB57@SlpcDVEVlarH} z@Al!2+VVi}7T=ERZvL_x$PF9T$7%pFa6Z!z*c>F;32DgK4YL!H5^f_$gb`BV9kB^L zg&oFf9fdwb8?1PT%Xwy)L%_zg{uCXX)1h<#9e<*D-;JDsVl4*Mf;_QHYy(wfS`zV3 zxohy5#|+9GPo6LwX1tpH_{J9YOA!M~kez@H1nk*Zc;B(-I!jn_$fxp)%|OY_t&qcN zgfwI)DikJI7MX)YP2x7D5asJUfpIFkVM@5R%me1ZDzI=LZ$Co#B`_n7bw#CBU`8%5 zBNrH%zwFe=4OL)}DTMp84h(RpOs)+?>=OiTWS8tlzTFgHI;Z084X2LKe#qkDIO}o@ zzFXevUU4248|XL-*N&tb&bfBvTsvURfy?gZTVyv}-{+-Gb~Hd94p*U-M6b& zjwG+{vN>b}?!@xnAGN`6<*JT_e|Ldy(#Hn_k^tXTxR#84g}a9ZcFNa}vESl$5NRQB zB7Q;D$fRVCLEgeeytBdQigStk6%hk5ADZv<4t>p&-|9^N`77>&`0Y=kq@je8H1?%5 zSmcE*W{{k&I B=@I|{ diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm index 1d1c937b7001c2f142ec7f610157e0af3eb9b778..d04664b607955d53f806292a0250899ca082b507 100644 GIT binary patch literal 18609 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 F{{emLQm6m` literal 5364 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 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm index 69e547cd117a8e644a910fd360ae972b4a6efa6b..5c717847a5a2dfb1d4b0e0db128b5a2cb9c57aaf 100644 GIT binary patch delta 655 zcmZ{gzityj5XQfmU3_=39bZC6!(su#U1H$`Cql|1rJ|ytL+1z_(mKaHUmsF0( z#?JAfz4$r_7t@;&z+Wg5CO=*_r$w?iO%F^z=?^vlXRbQajQfMZ`Y<^*i^={O$R$FT z*k2d}zQ}H0d>EG2Y&o+ynV%->{YN$6w^cKvFmNZ7EG4}LZV19ka86NUW@hun8KYI0 z!y*}{MVd@({xm}{x+9pA<=o3(y=-M4kq7yL7Idu4HCxqIf-Bu|d=lSw|ta$}ZG zr}LNSNWV%P5tcp&VfCE0NmQ5gEMkS26~$crq#>cY&);u(t)UwF2eJ*8iatJh>yEtS zdlb5w^8YpOI!&PYo|x_bYiK-Rsn-s=!jYgz2_0u~U>}v~F!R#BJ)kQ$8CHi`msK4r z(L?NfrG&S5N5`@3PHDI8Sv|%kY~)CMC9XEI8wkDj*8*G*_n5fUEgjf#puZxE=?+^k ZS+HU)z)|YG{Si}T?POZY;zUFzJ!>62bpH)hfT#i!Hs}Ha@l3XRL zP4$v_Ds+3jlfJi7X*5{_RnVw{Nvag6$oIEc<#j4=s>b7B>h{ix_raw!rIZapLeL{% zaDpvEX~rs^r)!3GrWTnO23g=m3FJnN{|C^}KJ6S^cDgLL?$tw-c+2EDN1=*A)kU2>>P`keKN>nHYY{PB?QYHrwjIAH8*NL_KrM;$oa TVWR<1*LYcTjUys`Yux<;(KbtX diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm index cbf1c77bdcb8bee40d72f5b5c37e3f2723db12a3..64fb6a48bfd6f1cd23a2e17c4cc720efd7e8ae65 100644 GIT binary patch delta 673 zcmZ9J&2G~`5Xa}kZJfkuofe7^5?!nc=!rHWg>tGZ<-(0C5^~&TTg8o?Dsj_>1IsH! z=2WQ%Zd~BXkq6)j;EKexufXn_mXAH`%>3r#zhi%PKX?k_af$$dkE>l)NtU zaWIk+XqK$bE`l{SxNdMN({wnIU`g#a8Ot1a_Tz!lRi0t_>F_MtY&|W7{-9FZt5?i% znb{%7!DE0qMrc;vqc^VwhNCHgm&BVJR z@ZW-db9ADs_T*tdi%zoBe%6Dg5#2wY!cygGy=8;US~up?crY05!%fG2k(DY!?OUb( z36WF?Av`1}^p67G(zf`5_mPXA_@YVzd=ltWu|wMk#cTRHSH{ozPVtgfvHmYRJVzq^ z*RE!6lrseg6dd}AU(-e;p_|xH+jW4zc|xFLHwj3TzTkE64HtqfqMgw9od7!xJF0lZ xE4S@SLesgC=!XmZxck-|Dk8ph7w?g7Lfyosi3N3@0oa9DFZ7N(NX2)4^$Uk8py&Vq delta 405 zcmZ9HJxjw-6o$_^_oivm50h396f{<$f{PX_)X5B;#KFZ)+M3=>~i+ff3rvCrnBSO_V5`q%t1sIK(;L zHUa1zO(ud_LEKClqFt$0_iK%r7AGfv> zoKe^pzCV}=NQn7E#$o~#ewJ5FL)Y~*5pm=khX5Kwu=P7Mqf=awW_}{Ze^x`Ln1FxA zvi4{iw_S>>ZqS$p*WI8Exm0}F8_prG|5{j5NS(G)eyiUfcwqD7lY)U@zH;LQk)#VQ z>=1XYUMb?VixlnAnSl;i=%9ts1J#g4A8et0>nFYzoon_wY!V&2Xz>!O=fGhO)sFy@ PF&2;AYjwnEp) -> Vec { - keccak256(&input).to_vec() +fn test_blake2_256(input: Vec) -> Vec { + blake2_256(&input).to_vec() +} + +fn test_twox_256(input: Vec) -> Vec { + twox_256(&input).to_vec() +} + +fn test_twox_128(input: Vec) -> Vec { + twox_128(&input).to_vec() } fn test_ed25519_verify(input: Vec) -> Vec { @@ -35,5 +43,4 @@ fn test_data_in(input: Vec) -> Vec { b"all ok!".to_vec() } - -impl_stubs!(test_data_in, test_keccak256, test_ed25519_verify); +impl_stubs!(test_data_in, test_blake2_256, test_twox_256, test_twox_128, test_ed25519_verify); From 262dd7bc55e7e4f1fdef5a86551b91459e4bf271 Mon Sep 17 00:00:00 2001 From: Gav Date: Fri, 19 Jan 2018 16:34:28 +0100 Subject: [PATCH 065/112] Fix tests. --- .../polkadot/src/runtime/session.rs | 106 ++++++++++++++++-- .../polkadot/src/runtime/staking.rs | 4 +- .../polkadot/src/support/storable.rs | 2 + 3 files changed, 103 insertions(+), 9 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs index 412809d6b8..687dedfc5b 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -37,7 +37,27 @@ pub fn set_validators(new: &[AccountID]) { /// The number of blocks in each session. pub fn length() -> BlockNumber { - Storable::lookup_default(b"ses\0bps") + Storable::lookup_default(b"ses\0len") +} + +/// The current era index. +pub fn current_index() -> BlockNumber { + Storable::lookup_default(b"ses\0ind") +} + +/// Set the current era index. +pub fn set_current_index(new: BlockNumber) { + new.store(b"ses\0ind"); +} + +/// The block number at which the era length last changed. +pub fn last_length_change() -> BlockNumber { + Storable::lookup_default(b"ses\0llc") +} + +/// Set a new era length. Won't kick in until the next era change (at current length). +pub fn set_length(new: BlockNumber) { + new.store(b"ses\0nln"); } /// Hook to be called after transaction processing. @@ -45,7 +65,7 @@ pub fn check_rotate_session() { // do this last, after the staking system has had chance to switch out the authorities for the // new set. // check block number and call next_session if necessary. - if system::block_number() % length() == 0 { + if (system::block_number() - last_length_change()) % length() == 0 { rotate_session(); } } @@ -54,6 +74,17 @@ pub fn check_rotate_session() { /// Move onto next session: register the new authority set. fn rotate_session() { + // Increment current session index. + set_current_index(current_index() + 1); + + // Enact era length change. + if let Some(next_len) = u64::lookup(b"ses\0nln") { + next_len.store(b"ses\0len"); + system::block_number().store(b"ses\0llc"); + kill(b"ses\0nln"); + } + + // Update any changes in session keys. validators().iter().enumerate().for_each(|(i, v)| { let k = v.to_keyed_vec(b"ses\0nxt\0"); if let Some(n) = Storable::lookup(&k) { @@ -73,10 +104,9 @@ mod tests { use runtime::{consensus, session}; use environment::with_env; - #[test] - fn session_change_should_work() { - let mut t = TestExternalities { storage: map![ - twox_128(b"ses\0bps").to_vec() => vec![].join(&2u64), + fn simple_setup() -> TestExternalities { + TestExternalities { storage: map![ + twox_128(b"ses\0len").to_vec() => vec![].join(&2u64), // the validators (10, 20, ...) twox_128(b"ses\0key\0len").to_vec() => vec![].join(&2u32), twox_128(&0u32.to_keyed_vec(b"ses\0key\0")).to_vec() => vec![10; 32], @@ -85,12 +115,74 @@ mod tests { twox_128(b"con\0aut\0len").to_vec() => vec![].join(&2u32), twox_128(&0u32.to_keyed_vec(b"con\0aut\0")).to_vec() => vec![11; 32], twox_128(&1u32.to_keyed_vec(b"con\0aut\0")).to_vec() => vec![21; 32] - ], }; + ], } + } + + #[test] + fn simple_setup_should_work() { + let mut t = simple_setup(); with_externalities(&mut t, || { assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); assert_eq!(session::length(), 2u64); assert_eq!(session::validators(), vec![[10u8; 32], [20u8; 32]]); + }); + } + #[test] + fn session_length_change_should_work() { + let mut t = simple_setup(); + with_externalities(&mut t, || { + // Block 1: Change to length 3; no visible change. + with_env(|e| e.block_number = 1); + session::set_length(3); + session::check_rotate_session(); + assert_eq!(session::length(), 2); + assert_eq!(session::current_index(), 0); + + // Block 2: Length now changed to 3. Index incremented. + with_env(|e| e.block_number = 2); + session::set_length(3); + session::check_rotate_session(); + assert_eq!(session::length(), 3); + assert_eq!(session::current_index(), 1); + + // Block 3: Length now changed to 3. Index incremented. + with_env(|e| e.block_number = 3); + session::check_rotate_session(); + assert_eq!(session::length(), 3); + assert_eq!(session::current_index(), 1); + + // Block 4: Change to length 2; no visible change. + with_env(|e| e.block_number = 4); + session::set_length(2); + session::check_rotate_session(); + assert_eq!(session::length(), 3); + assert_eq!(session::current_index(), 1); + + // Block 5: Length now changed to 2. Index incremented. + with_env(|e| e.block_number = 5); + session::check_rotate_session(); + assert_eq!(session::length(), 2); + assert_eq!(session::current_index(), 2); + + // Block 6: No change. + with_env(|e| e.block_number = 6); + session::check_rotate_session(); + assert_eq!(session::length(), 2); + assert_eq!(session::current_index(), 2); + + // Block 7: Next index. + with_env(|e| e.block_number = 7); + session::check_rotate_session(); + assert_eq!(session::length(), 2); + assert_eq!(session::current_index(), 3); + }); + } + + #[test] + fn session_change_should_work() { + let mut t = simple_setup(); + with_externalities(&mut t, || { // Block 1: No change with_env(|e| e.block_number = 1); session::check_rotate_session(); diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index f3bae42060..64b64521bd 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -28,7 +28,7 @@ pub fn current_era() -> BlockNumber { Storable::lookup_default(b"sta\0era") } -/// The current era index. +/// Set the current era index. pub fn set_current_era(new: BlockNumber) { new.store(b"sta\0era"); } @@ -113,7 +113,7 @@ mod tests { #[test] fn staking_eras_work() { let mut t = TestExternalities { storage: map![ - twox_128(b"ses\0bps").to_vec() => vec![].join(&1u64), + twox_128(b"ses\0len").to_vec() => vec![].join(&1u64), twox_128(b"sta\0spe").to_vec() => vec![].join(&2u64) ], }; with_externalities(&mut t, || { diff --git a/substrate/wasm-runtime/polkadot/src/support/storable.rs b/substrate/wasm-runtime/polkadot/src/support/storable.rs index 177475b2d7..80c7af2136 100644 --- a/substrate/wasm-runtime/polkadot/src/support/storable.rs +++ b/substrate/wasm-runtime/polkadot/src/support/storable.rs @@ -9,6 +9,8 @@ pub trait Storable { fn store(&self, key: &[u8]); } +// TODO: consider using blake256 to avoid possible eclipse attack. + pub fn kill(key: &[u8]) { runtime_support::set_storage(&twox_128(key)[..], b""); } impl Storable for T { From 18defc0d95b9ab39592511f71f3b5d58c89e4980 Mon Sep 17 00:00:00 2001 From: Gav Date: Fri, 19 Jan 2018 17:39:06 +0100 Subject: [PATCH 066/112] Introduce staking. --- substrate/state_machine/src/lib.rs | 16 +-- .../polkadot/src/runtime/consensus.rs | 2 +- .../polkadot/src/runtime/session.rs | 38 +++--- .../polkadot/src/runtime/staking.rs | 109 ++++++++++++------ .../polkadot/src/runtime/system.rs | 16 +-- .../polkadot/src/runtime/timestamp.rs | 6 +- .../polkadot/src/support/function.rs | 8 +- .../polkadot/src/support/primitives.rs | 8 +- 8 files changed, 122 insertions(+), 81 deletions(-) diff --git a/substrate/state_machine/src/lib.rs b/substrate/state_machine/src/lib.rs index cee96a36ad..d1357592d4 100644 --- a/substrate/state_machine/src/lib.rs +++ b/substrate/state_machine/src/lib.rs @@ -134,10 +134,10 @@ pub trait Externalities { /// Get the current set of authorities from storage. fn authorities(&self) -> Result, Self::Error> { - (0..self.storage(b"con\0aut\0len")?.into_iter() + (0..self.storage(b"con:aut:len")?.into_iter() .rev() .fold(0, |acc, &i| (acc << 8) + (i as u32))) - .map(|i| self.storage(&to_keyed_vec(i, b"con\0aut\0".to_vec()))) + .map(|i| self.storage(&to_keyed_vec(i, b"con:aut:".to_vec()))) .collect() } } @@ -177,7 +177,7 @@ pub fn execute( overlay: &mut *overlay }; // make a copy. - let code = externalities.storage(b"\0code").unwrap_or(&[]).to_vec(); + let code = externalities.storage(b":code").unwrap_or(&[]).to_vec(); exec.call( &mut externalities, @@ -253,17 +253,17 @@ mod tests { assert_eq!(ext.authorities(), Ok(vec![])); - ext.set_storage(b"con\0aut\0len".to_vec(), vec![0u8; 4]); + ext.set_storage(b"con:aut:len".to_vec(), vec![0u8; 4]); assert_eq!(ext.authorities(), Ok(vec![])); - ext.set_storage(b"con\0aut\0len".to_vec(), vec![1u8, 0, 0, 0]); + ext.set_storage(b"con:aut:len".to_vec(), vec![1u8, 0, 0, 0]); assert_eq!(ext.authorities(), Ok(vec![&[][..]])); - ext.set_storage(b"con\0aut\0\0\0\0\0".to_vec(), b"first".to_vec()); + ext.set_storage(b"con:aut:::::".to_vec(), b"first".to_vec()); assert_eq!(ext.authorities(), Ok(vec![&b"first"[..]])); - ext.set_storage(b"con\0aut\0len".to_vec(), vec![2u8, 0, 0, 0]); - ext.set_storage(b"con\0aut\0\x01\0\0\0".to_vec(), b"second".to_vec()); + ext.set_storage(b"con:aut:len".to_vec(), vec![2u8, 0, 0, 0]); + ext.set_storage(b"con:aut:\x01:::".to_vec(), b"second".to_vec()); assert_eq!(ext.authorities(), Ok(vec![&b"first"[..], &b"second"[..]])); } } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs b/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs index 02bf288493..757c032f03 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs @@ -5,7 +5,7 @@ use primitives::SessionKey; struct AuthorityStorageVec {} impl StorageVec for AuthorityStorageVec { type Item = SessionKey; - const PREFIX: &'static[u8] = b"con\0aut\0"; + const PREFIX: &'static[u8] = b"con:aut:"; } /// Get the current set of authorities. These are the session keys. diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs index 687dedfc5b..cc572ea842 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -7,7 +7,7 @@ use runtime::{system, staking, consensus}; struct ValidatorStorageVec {} impl StorageVec for ValidatorStorageVec { type Item = AccountID; - const PREFIX: &'static[u8] = b"ses\0key\0"; + const PREFIX: &'static[u8] = b"ses:key:"; } // TRANSACTION API (available to all transactors) @@ -16,7 +16,7 @@ impl StorageVec for ValidatorStorageVec { /// session. pub fn set_key(validator: &AccountID, key: &SessionKey) { // set new value for next session - key.store(&validator.to_keyed_vec(b"ses\0nxt\0")); + key.store(&validator.to_keyed_vec(b"ses:nxt:")); } // PUBLIC API (available to other runtime modules) @@ -37,27 +37,27 @@ pub fn set_validators(new: &[AccountID]) { /// The number of blocks in each session. pub fn length() -> BlockNumber { - Storable::lookup_default(b"ses\0len") + Storable::lookup_default(b"ses:len") } /// The current era index. pub fn current_index() -> BlockNumber { - Storable::lookup_default(b"ses\0ind") + Storable::lookup_default(b"ses:ind") } /// Set the current era index. pub fn set_current_index(new: BlockNumber) { - new.store(b"ses\0ind"); + new.store(b"ses:ind"); } /// The block number at which the era length last changed. pub fn last_length_change() -> BlockNumber { - Storable::lookup_default(b"ses\0llc") + Storable::lookup_default(b"ses:llc") } /// Set a new era length. Won't kick in until the next era change (at current length). pub fn set_length(new: BlockNumber) { - new.store(b"ses\0nln"); + new.store(b"ses:nln"); } /// Hook to be called after transaction processing. @@ -78,15 +78,15 @@ fn rotate_session() { set_current_index(current_index() + 1); // Enact era length change. - if let Some(next_len) = u64::lookup(b"ses\0nln") { - next_len.store(b"ses\0len"); - system::block_number().store(b"ses\0llc"); - kill(b"ses\0nln"); + if let Some(next_len) = u64::lookup(b"ses:nln") { + next_len.store(b"ses:len"); + system::block_number().store(b"ses:llc"); + kill(b"ses:nln"); } // Update any changes in session keys. validators().iter().enumerate().for_each(|(i, v)| { - let k = v.to_keyed_vec(b"ses\0nxt\0"); + let k = v.to_keyed_vec(b"ses:nxt:"); if let Some(n) = Storable::lookup(&k) { consensus::set_authority(i as u32, &n); kill(&k); @@ -106,15 +106,15 @@ mod tests { fn simple_setup() -> TestExternalities { TestExternalities { storage: map![ - twox_128(b"ses\0len").to_vec() => vec![].join(&2u64), + twox_128(b"ses:len").to_vec() => vec![].join(&2u64), // the validators (10, 20, ...) - twox_128(b"ses\0key\0len").to_vec() => vec![].join(&2u32), - twox_128(&0u32.to_keyed_vec(b"ses\0key\0")).to_vec() => vec![10; 32], - twox_128(&1u32.to_keyed_vec(b"ses\0key\0")).to_vec() => vec![20; 32], + twox_128(b"ses:key:len").to_vec() => vec![].join(&2u32), + twox_128(&0u32.to_keyed_vec(b"ses:key:")).to_vec() => vec![10; 32], + twox_128(&1u32.to_keyed_vec(b"ses:key:")).to_vec() => vec![20; 32], // initial session keys (11, 21, ...) - twox_128(b"con\0aut\0len").to_vec() => vec![].join(&2u32), - twox_128(&0u32.to_keyed_vec(b"con\0aut\0")).to_vec() => vec![11; 32], - twox_128(&1u32.to_keyed_vec(b"con\0aut\0")).to_vec() => vec![21; 32] + twox_128(b"con:aut:len").to_vec() => vec![].join(&2u32), + twox_128(&0u32.to_keyed_vec(b"con:aut:")).to_vec() => vec![11; 32], + twox_128(&1u32.to_keyed_vec(b"con:aut:")).to_vec() => vec![21; 32] ], } } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index 64b64521bd..1406cd96ce 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -1,16 +1,30 @@ use keyedvec::KeyedVec; -use storable::Storable; +use storable::{Storable, StorageVec}; use primitives::{BlockNumber, Balance, AccountID}; use runtime::{system, session}; -// Each validator's stake has one amount in each of three states: -// - inactive: free to be transferred. -// - active: currently representing a validator. -// - deactivating: recently representing a validator and not yet ready for transfer. +type Liquidity = u64; + +struct IntentionStorageVec {} +impl StorageVec for IntentionStorageVec { + type Item = AccountID; + const PREFIX: &'static[u8] = b"ses:wil:"; +} + +// Each identity's stake may be in one of three bondage states, given by an integer: +// - n | n <= system::block_number(): inactive: free to be transferred. +// - ~0: active: currently representing a validator. +// - n | n > system::block_number(): deactivating: recently representing a validator and not yet +// ready for transfer. /// The length of a staking era in sessions. -pub fn lockup_eras() -> BlockNumber { - Storable::lookup_default(b"sta\0lpe") +pub fn eras_per_lockup() -> BlockNumber { + Storable::lookup_default(b"sta:epl") +} + +/// The length of a staking era in sessions. +pub fn validator_count() -> usize { + Storable::lookup_default(b"sta:vac") } /// The length of a staking era in blocks. @@ -20,27 +34,27 @@ pub fn era_length() -> BlockNumber { /// The length of a staking era in sessions. pub fn sessions_per_era() -> BlockNumber { - Storable::lookup_default(b"sta\0spe") + Storable::lookup_default(b"sta:spe") } /// The current era index. pub fn current_era() -> BlockNumber { - Storable::lookup_default(b"sta\0era") + Storable::lookup_default(b"sta:era") } /// Set the current era index. pub fn set_current_era(new: BlockNumber) { - new.store(b"sta\0era"); + new.store(b"sta:era"); } /// The block number at which the era length last changed. pub fn last_era_length_change() -> BlockNumber { - Storable::lookup_default(b"sta\0lec") + Storable::lookup_default(b"sta:lec") } /// Set a new era length. Won't kick in until the next era change (at current length). pub fn set_sessions_per_era(new: BlockNumber) { - new.store(b"sta\0nse"); + new.store(b"sta:nse"); } /// The era has changed - enact new staking set. @@ -51,28 +65,48 @@ fn new_era() { set_current_era(current_era() + 1); // Enact era length change. - let next_spe: u64 = Storable::lookup_default(b"sta\0nse"); + let next_spe: u64 = Storable::lookup_default(b"sta:nse"); if next_spe > 0 && next_spe != sessions_per_era() { - next_spe.store(b"sta\0spe"); - system::block_number().store(b"sta\0lec"); + next_spe.store(b"sta:spe"); + system::block_number().store(b"sta:lec"); } // TODO: evaluate desired staking amounts and nominations and optimise to find the best // combination of validators, then use session::set_validators(). + + // for now, this just orders would-be stakers by their balances and chooses the top-most + // validator_count() of them. + let mut intentions = IntentionStorageVec::items() + .into_iter() + .map(|v| (balance(&v), v)) + .collect::>(); + intentions.sort_unstable_by(|&(b1, _), &(b2, _)| b2.cmp(&b1)); + session::set_validators( + &intentions.into_iter() + .map(|(_, v)| v) + .take(validator_count()) + .collect::>() + ); } /// The balance of a given account. -pub fn balance_inactive(who: &AccountID) -> Balance { - Storable::lookup_default(&who.to_keyed_vec(b"sta\0bal\0")) +pub fn balance(who: &AccountID) -> Balance { + Storable::lookup_default(&who.to_keyed_vec(b"sta:bal:")) +} + +/// The liquidity-state of a given account. +pub fn bondage(who: &AccountID) -> Liquidity { + Storable::lookup_default(&who.to_keyed_vec(b"sta:bon:")) } /// Transfer some unlocked staking balance to another staker. -pub fn transfer_inactive(transactor: &AccountID, dest: &AccountID, value: Balance) { - let from_key = transactor.to_keyed_vec(b"sta\0bal\0"); - let from_balance: Balance = Storable::lookup_default(&from_key); +pub fn transfer(transactor: &AccountID, dest: &AccountID, value: Balance) { + let from_key = transactor.to_keyed_vec(b"sta:bal:"); + let from_balance = Balance::lookup_default(&from_key); assert!(from_balance >= value); - let to_key = dest.to_keyed_vec(b"sta\0bal\0"); + let to_key = dest.to_keyed_vec(b"sta:bal:"); let to_balance: Balance = Storable::lookup_default(&to_key); + assert!(bondage(transactor) <= bondage(dest)); assert!(to_balance + value > to_balance); // no overflow (from_balance - value).store(&from_key); (to_balance + value).store(&to_key); @@ -81,15 +115,22 @@ pub fn transfer_inactive(transactor: &AccountID, dest: &AccountID, value: Balanc /// Declare the desire to stake for the transactor. /// /// Effects will be felt at the beginning of the next era. -pub fn stake(_transactor: &AccountID) { - // TODO: record the desire for `_transactor` to activate their stake. +pub fn stake(transactor: &AccountID) { + let mut intentions = IntentionStorageVec::items(); + // can't be in the list twice. + assert!(intentions.iter().find(|t| *t == transactor).is_none()); + intentions.push(transactor.clone()); + IntentionStorageVec::set_items(&intentions); } /// Retract the desire to stake for the transactor. /// /// Effects will be felt at the beginning of the next era. -pub fn unstake(_transactor: &AccountID) { - // TODO: record the desire for `_transactor` to deactivate their stake. +pub fn unstake(transactor: &AccountID) { + let mut intentions = IntentionStorageVec::items(); + // TODO: use swap remove. + let intentions = intentions.into_iter().filter(|t| t != transactor).collect::>(); + IntentionStorageVec::set_items(&intentions); } /// Hook to be called after to transaction processing. @@ -113,8 +154,8 @@ mod tests { #[test] fn staking_eras_work() { let mut t = TestExternalities { storage: map![ - twox_128(b"ses\0len").to_vec() => vec![].join(&1u64), - twox_128(b"sta\0spe").to_vec() => vec![].join(&2u64) + twox_128(b"ses:len").to_vec() => vec![].join(&1u64), + twox_128(b"sta:spe").to_vec() => vec![].join(&2u64) ], }; with_externalities(&mut t, || { assert_eq!(staking::era_length(), 2u64); @@ -180,12 +221,12 @@ mod tests { let two = two(); let mut t = TestExternalities { storage: map![ - twox_128(&one.to_keyed_vec(b"sta\0bal\0")).to_vec() => vec![].join(&42u64) + twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![].join(&42u64) ], }; with_externalities(&mut t, || { - assert_eq!(staking::balance_inactive(&one), 42); - assert_eq!(staking::balance_inactive(&two), 0); + assert_eq!(staking::balance(&one), 42); + assert_eq!(staking::balance(&two), 0); }); } @@ -195,13 +236,13 @@ mod tests { let two = two(); let mut t = TestExternalities { storage: map![ - twox_128(&one.to_keyed_vec(b"sta\0bal\0")).to_vec() => vec![].join(&111u64) + twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![].join(&111u64) ], }; with_externalities(&mut t, || { - staking::transfer_inactive(&one, &two, 69); - assert_eq!(staking::balance_inactive(&one), 42); - assert_eq!(staking::balance_inactive(&two), 69); + staking::transfer(&one, &two, 69); + assert_eq!(staking::balance(&one), 42); + assert_eq!(staking::balance(&two), 69); }); } } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 0bf300d2b3..f96bc40c93 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -12,7 +12,7 @@ pub fn block_number() -> BlockNumber { /// Get the block hash of a given block (uses storage). pub fn block_hash(number: BlockNumber) -> Hash { - Storable::lookup_default(&number.to_keyed_vec(b"sys\0old\0")) + Storable::lookup_default(&number.to_keyed_vec(b"sys:old:")) } /// Deposits a log and ensures it matches the blocks log data. @@ -44,7 +44,7 @@ pub fn execute_block(mut block: Block) { // so will wait until a little later. // store the header hash in storage. - let header_hash_key = header.number.to_keyed_vec(b"sys\0old\0"); + let header_hash_key = header.number.to_keyed_vec(b"sys:old:"); header.blake2_256().store(&header_hash_key); // execute transactions @@ -69,7 +69,7 @@ pub fn execute_transaction(utx: &UncheckedTransaction) { let ref tx = utx.transaction; // check nonce - let nonce_key = tx.signed.to_keyed_vec(b"sys\0non\0"); + let nonce_key = tx.signed.to_keyed_vec(b"sys:non:"); let expected_nonce: TxOrder = Storable::lookup_default(&nonce_key); assert!(tx.nonce == expected_nonce, "All transactions should have the correct nonce"); @@ -82,7 +82,7 @@ pub fn execute_transaction(utx: &UncheckedTransaction) { /// Set the new code. pub fn set_code(new: &[u8]) { - new.store(b"\0code"); + new.store(b":code"); } fn final_checks(_block: &Block) { @@ -109,14 +109,14 @@ mod tests { let two = two(); let mut t = TestExternalities { storage: map![ - twox_128(&one.to_keyed_vec(b"sta\0bal\0")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] ], }; let tx = UncheckedTransaction { transaction: Transaction { signed: one.clone(), nonce: 0, - function: Function::StakingTransferInactive, + function: Function::StakingTransfer, input_data: vec![].join(&two).join(&69u64), }, signature: "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a".convert(), @@ -128,8 +128,8 @@ mod tests { with_externalities(&mut t, || { system::execute_transaction(&tx); - assert_eq!(staking::balance_inactive(&one), 42); - assert_eq!(staking::balance_inactive(&two), 69); + assert_eq!(staking::balance(&one), 42); + assert_eq!(staking::balance(&two), 69); }); } } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs index 10708a5a3c..c6a3ac2a96 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs @@ -2,11 +2,11 @@ use primitives::Timestamp; use storable::Storable; pub fn get() -> Timestamp { - Storable::lookup_default(b"tim\0val") + Storable::lookup_default(b"tim:val") } pub fn set(now: Timestamp) { - now.store(b"tim\0val") + now.store(b"tim:val") } #[cfg(test)] @@ -20,7 +20,7 @@ mod tests { #[test] fn timestamp_works() { let mut t = TestExternalities { storage: map![ - twox_128(b"tim\0val").to_vec() => vec![].join(&42u64) + twox_128(b"tim:val").to_vec() => vec![].join(&42u64) ], }; with_externalities(&mut t, || { diff --git a/substrate/wasm-runtime/polkadot/src/support/function.rs b/substrate/wasm-runtime/polkadot/src/support/function.rs index 45dcea876b..f0be93c4af 100644 --- a/substrate/wasm-runtime/polkadot/src/support/function.rs +++ b/substrate/wasm-runtime/polkadot/src/support/function.rs @@ -8,7 +8,7 @@ use runtime::{staking, session, timestamp}; pub enum Function { StakingStake, StakingUnstake, - StakingTransferInactive, + StakingTransfer, SessionSetKey, TimestampSet, } @@ -18,7 +18,7 @@ impl Function { match value { x if x == Function::StakingStake as u8 => Some(Function::StakingStake), x if x == Function::StakingUnstake as u8 => Some(Function::StakingUnstake), - x if x == Function::StakingTransferInactive as u8 => Some(Function::StakingTransferInactive), + x if x == Function::StakingTransfer as u8 => Some(Function::StakingTransfer), x if x == Function::SessionSetKey as u8 => Some(Function::SessionSetKey), x if x == Function::TimestampSet as u8 => Some(Function::TimestampSet), _ => None, @@ -37,10 +37,10 @@ impl Function { Function::StakingUnstake => { staking::unstake(transactor); } - Function::StakingTransferInactive => { + Function::StakingTransfer => { let dest = params.read().unwrap(); let value = params.read().unwrap(); - staking::transfer_inactive(transactor, &dest, value); + staking::transfer(transactor, &dest, value); } Function::SessionSetKey => { let session = params.read().unwrap(); diff --git a/substrate/wasm-runtime/polkadot/src/support/primitives.rs b/substrate/wasm-runtime/polkadot/src/support/primitives.rs index fb983bf84e..dbe75aad11 100644 --- a/substrate/wasm-runtime/polkadot/src/support/primitives.rs +++ b/substrate/wasm-runtime/polkadot/src/support/primitives.rs @@ -261,7 +261,7 @@ mod tests { let tx = Transaction { signed: one.clone(), nonce: 69, - function: Function::StakingTransferInactive, + function: Function::StakingTransfer, input_data: Vec::new().join(&two).join(&69u64), }; let serialised = tx.to_vec(); @@ -282,7 +282,7 @@ mod tests { let tx = Transaction { signed: one.clone(), nonce: 69, - function: Function::StakingTransferInactive, + function: Function::StakingTransfer, input_data: Vec::new().join(&two).join(&69u64), }; let data = [ @@ -352,7 +352,7 @@ mod tests { transaction: Transaction { signed: one.clone(), nonce: 69, - function: Function::StakingTransferInactive, + function: Function::StakingTransfer, input_data: Vec::new().join(&two).join(&69u64), }, signature: [1u8; 64], @@ -416,7 +416,7 @@ mod tests { transaction: Transaction { signed: one.clone(), nonce: 69, - function: Function::StakingTransferInactive, + function: Function::StakingTransfer, input_data: Vec::new().join(&two).join(&69u64), }, signature: [1u8; 64], From a87e99fdda2fc2f50556a7e212ad0139e58f8b4a Mon Sep 17 00:00:00 2001 From: Gav Date: Fri, 19 Jan 2018 20:29:42 +0100 Subject: [PATCH 067/112] Tests for simple staking system. --- .../polkadot/src/runtime/session.rs | 10 +- .../polkadot/src/runtime/staking.rs | 123 +++++++++++++++--- 2 files changed, 110 insertions(+), 23 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs index cc572ea842..b7ed1361ec 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -7,7 +7,7 @@ use runtime::{system, staking, consensus}; struct ValidatorStorageVec {} impl StorageVec for ValidatorStorageVec { type Item = AccountID; - const PREFIX: &'static[u8] = b"ses:key:"; + const PREFIX: &'static[u8] = b"ses:val:"; } // TRANSACTION API (available to all transactors) @@ -22,7 +22,7 @@ pub fn set_key(validator: &AccountID, key: &SessionKey) { // PUBLIC API (available to other runtime modules) /// Get the current set of authorities. These are the session keys. -fn validators() -> Vec { +pub fn validators() -> Vec { ValidatorStorageVec::items() } @@ -108,9 +108,9 @@ mod tests { TestExternalities { storage: map![ twox_128(b"ses:len").to_vec() => vec![].join(&2u64), // the validators (10, 20, ...) - twox_128(b"ses:key:len").to_vec() => vec![].join(&2u32), - twox_128(&0u32.to_keyed_vec(b"ses:key:")).to_vec() => vec![10; 32], - twox_128(&1u32.to_keyed_vec(b"ses:key:")).to_vec() => vec![20; 32], + twox_128(b"ses:val:len").to_vec() => vec![].join(&2u32), + twox_128(&0u32.to_keyed_vec(b"ses:val:")).to_vec() => vec![10; 32], + twox_128(&1u32.to_keyed_vec(b"ses:val:")).to_vec() => vec![20; 32], // initial session keys (11, 21, ...) twox_128(b"con:aut:len").to_vec() => vec![].join(&2u32), twox_128(&0u32.to_keyed_vec(b"con:aut:")).to_vec() => vec![11; 32], diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index 1406cd96ce..fe26a7c928 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -12,19 +12,19 @@ impl StorageVec for IntentionStorageVec { } // Each identity's stake may be in one of three bondage states, given by an integer: -// - n | n <= system::block_number(): inactive: free to be transferred. +// - n | n <= current_era(): inactive: free to be transferred. // - ~0: active: currently representing a validator. -// - n | n > system::block_number(): deactivating: recently representing a validator and not yet +// - n | n > current_era(): deactivating: recently representing a validator and not yet // ready for transfer. -/// The length of a staking era in sessions. -pub fn eras_per_lockup() -> BlockNumber { - Storable::lookup_default(b"sta:epl") +/// The length of the bonding duration in eras. +pub fn bonding_duration() -> BlockNumber { + Storable::lookup_default(b"sta:loc") } /// The length of a staking era in sessions. pub fn validator_count() -> usize { - Storable::lookup_default(b"sta:vac") + u32::lookup_default(b"sta:vac") as usize } /// The length of a staking era in blocks. @@ -42,27 +42,17 @@ pub fn current_era() -> BlockNumber { Storable::lookup_default(b"sta:era") } -/// Set the current era index. -pub fn set_current_era(new: BlockNumber) { - new.store(b"sta:era"); -} - /// The block number at which the era length last changed. pub fn last_era_length_change() -> BlockNumber { Storable::lookup_default(b"sta:lec") } -/// Set a new era length. Won't kick in until the next era change (at current length). -pub fn set_sessions_per_era(new: BlockNumber) { - new.store(b"sta:nse"); -} - /// The era has changed - enact new staking set. /// /// NOTE: This always happens on a session change. fn new_era() { // Increment current era. - set_current_era(current_era() + 1); + (current_era() + 1).store(b"sta:era"); // Enact era length change. let next_spe: u64 = Storable::lookup_default(b"sta:nse"); @@ -121,6 +111,7 @@ pub fn stake(transactor: &AccountID) { assert!(intentions.iter().find(|t| *t == transactor).is_none()); intentions.push(transactor.clone()); IntentionStorageVec::set_items(&intentions); + u64::max_value().store(&transactor.to_keyed_vec(b"sta:bon:")); } /// Retract the desire to stake for the transactor. @@ -131,6 +122,7 @@ pub fn unstake(transactor: &AccountID) { // TODO: use swap remove. let intentions = intentions.into_iter().filter(|t| t != transactor).collect::>(); IntentionStorageVec::set_items(&intentions); + (current_era() + bonding_duration()).store(&transactor.to_keyed_vec(b"sta:bon:")); } /// Hook to be called after to transaction processing. @@ -141,6 +133,11 @@ pub fn check_new_era() { } } +/// Set a new era length. Won't kick in until the next era change (at current length). +fn set_sessions_per_era(new: BlockNumber) { + new.store(b"sta:nse"); +} + #[cfg(test)] mod tests { use runtime_support::{with_externalities, twox_128}; @@ -148,9 +145,83 @@ mod tests { use joiner::Joiner; use testing::{one, two, TestExternalities}; use primitives::AccountID; - use runtime::staking; + use runtime::{staking, session}; use environment::with_env; + #[test] + fn staking_should_work() { + let one = one(); + let two = two(); + let three = [3u8; 32]; + let four = [4u8; 32]; + + let mut t = TestExternalities { storage: map![ + twox_128(b"ses:len").to_vec() => vec![].join(&1u64), + twox_128(b"ses:val:len").to_vec() => vec![].join(&2u32), + twox_128(&0u32.to_keyed_vec(b"ses:val:")).to_vec() => vec![10; 32], + twox_128(&1u32.to_keyed_vec(b"ses:val:")).to_vec() => vec![20; 32], + twox_128(b"sta:spe").to_vec() => vec![].join(&2u64), + twox_128(b"sta:vac").to_vec() => vec![].join(&2u32), + twox_128(b"sta:loc").to_vec() => vec![].join(&3u64), + twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![].join(&10u64), + twox_128(&two.to_keyed_vec(b"sta:bal:")).to_vec() => vec![].join(&20u64), + twox_128(&three.to_keyed_vec(b"sta:bal:")).to_vec() => vec![].join(&30u64), + twox_128(&four.to_keyed_vec(b"sta:bal:")).to_vec() => vec![].join(&40u64) + ], }; + + with_externalities(&mut t, || { + assert_eq!(staking::era_length(), 2u64); + assert_eq!(staking::validator_count(), 2usize); + assert_eq!(staking::bonding_duration(), 3u64); + assert_eq!(session::validators(), vec![[10u8; 32], [20u8; 32]]); + + // Block 1: Add three validators. No obvious change. + with_env(|e| e.block_number = 1); + staking::stake(&one); + staking::stake(&two); + staking::stake(&four); + staking::check_new_era(); + assert_eq!(session::validators(), vec![[10u8; 32], [20u8; 32]]); + + // Block 2: New validator set now. + with_env(|e| e.block_number = 2); + staking::check_new_era(); + assert_eq!(session::validators(), vec![four.clone(), two.clone()]); + + // Block 3: Unstake highest, introduce another staker. No change yet. + with_env(|e| e.block_number = 3); + staking::stake(&three); + staking::unstake(&four); + staking::check_new_era(); + + // Block 4: New era - validators change. + with_env(|e| e.block_number = 4); + staking::check_new_era(); + assert_eq!(session::validators(), vec![three.clone(), two.clone()]); + + // Block 5: Transfer stake from highest to lowest. No change yet. + with_env(|e| e.block_number = 5); + staking::transfer(&four, &one, 40); + staking::check_new_era(); + + // Block 6: Lowest now validator. + with_env(|e| e.block_number = 6); + staking::check_new_era(); + assert_eq!(session::validators(), vec![one.clone(), three.clone()]); + + // Block 7: Unstake three. No change yet. + with_env(|e| e.block_number = 7); + staking::unstake(&three); + staking::check_new_era(); + assert_eq!(session::validators(), vec![one.clone(), three.clone()]); + + // Block 8: Back to one and two. + with_env(|e| e.block_number = 8); + staking::check_new_era(); + assert_eq!(session::validators(), vec![one.clone(), two.clone()]); + }); + } + #[test] fn staking_eras_work() { let mut t = TestExternalities { storage: map![ @@ -245,4 +316,20 @@ mod tests { assert_eq!(staking::balance(&two), 69); }); } + + #[test] + #[should_panic] + fn staking_balance_transfer_when_bonded_doesnt_work() { + let one = one(); + let two = two(); + + let mut t = TestExternalities { storage: map![ + twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![].join(&111u64) + ], }; + + with_externalities(&mut t, || { + staking::stake(&one); + staking::transfer(&one, &two, 69); + }); + } } From ecb504e46797ca77568f5bcba5ef4353ef4ad821 Mon Sep 17 00:00:00 2001 From: Gav Date: Fri, 19 Jan 2018 20:31:18 +0100 Subject: [PATCH 068/112] Build fix for wasm. --- substrate/executor/src/wasm_executor.rs | 1 - .../polkadot/src/runtime/staking.rs | 1 + .../release/runtime_polkadot.compact.wasm | Bin 18522 -> 37802 bytes .../release/runtime_polkadot.wasm | Bin 18609 -> 37859 bytes 4 files changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index c0c638fa3d..7fc9a741f8 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -240,7 +240,6 @@ mod tests { use super::*; use rustc_hex::FromHex; - use primitives::ed25519::hexdisplay::HexDisplay; #[derive(Debug, Default)] struct TestExternalities { diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index fe26a7c928..6b41ddbd8f 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -1,3 +1,4 @@ +use runtime_support::Vec; use keyedvec::KeyedVec; use storable::{Storable, StorageVec}; use primitives::{BlockNumber, Balance, AccountID}; diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm index dbc3273e1b506a06521aae4b775386774d7353a8..5f357f211861828f797bbe3bf8388b2839067a07 100644 GIT binary patch literal 37802 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

      GsQHII{LdIbLMM zi4*jCQh0eXlP4zQ^0u8tu^pBF&evgYy=iGX;pL_!dyH;o!!qbk+`Y98#x1?T$M&4; zEbM2u(QdU%=+sp1SkCV4)8cn5<%yt^wqpqx?N~AmC<;iY`~stJ0c@#=ZB;gIy<=%c zqujOBnT}|t_=HhcpVBh|VX3&Z_oxDq;=aFY8=3ygrEKF$v)p*P);T-f)W%b?l|0Q! zn$6-S=h4uK2I!Zbk*{UBrXS=m&xbdytS_X|`HRvs;wy>PezQS`*IEW_qdeQ^tAMm# zo?!Gury@ad}>(!_uh)|~@N=1uXk>Gp&T<3g^1gZl6)fx#@ z#RT+usQPe_;Cm3S45J2o9?rK<$|S1I;Cme0gyQXTlOvw5w?(6m>eu4ix|y1whB>&y3^W_s$_@|{TfZHu0y=It4&sou(w*iV71xjN^Vqz-0&HtNH;s657F258x4+MvkZlf)%jF?%cQ37dc)+GCO3R?WUnn& z6;t3tyb%k1m_&wXuwQPjX=&N@OG~FTmA(ofl@|IcfYjj1pkHHY*=-?wkzng3lyN1@ z>bcAMf$+_jYtL%APbdoomak5w}PBl+7uJfWyzN)4BR{wG0n-|PGMN{7y zP4xK-zMkF88|0YQDLE9-I7#wiCF3|GpBtVIw(u1;

      d?nBkjN_JJ#2vzBkdw}_8t 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 literal 18522 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 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm index d04664b607955d53f806292a0250899ca082b507..700194bb0a902a08b3704ed1a25f78b67a0e113e 100644 GIT binary patch literal 37859 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 literal 18609 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 F{{emLQm6m` From 768cb3bca2d3d17a8b623985d619b00e4ead592d Mon Sep 17 00:00:00 2001 From: Gav Date: Fri, 19 Jan 2018 21:20:44 +0100 Subject: [PATCH 069/112] Fix tests. --- substrate/primitives/src/block.rs | 2 +- substrate/primitives/src/parachain.rs | 2 +- substrate/state_machine/src/lib.rs | 4 ++-- .../polkadot/src/support/environment.rs | 22 +++++++++++++++++++ 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/substrate/primitives/src/block.rs b/substrate/primitives/src/block.rs index 740b0c4cda..8cd077fd78 100644 --- a/substrate/primitives/src/block.rs +++ b/substrate/primitives/src/block.rs @@ -97,7 +97,7 @@ mod tests { "candidates": [ { "parachainIndex": 10, - "collatorSignature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "collatorSignature": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "unprocessedIngress": [], "block": "0x01030508" } diff --git a/substrate/primitives/src/parachain.rs b/substrate/primitives/src/parachain.rs index 1d64f3c824..ed44134ce2 100644 --- a/substrate/primitives/src/parachain.rs +++ b/substrate/primitives/src/parachain.rs @@ -118,7 +118,7 @@ mod tests { block: BlockData(vec![1, 2, 3]), }), r#"{ "parachainIndex": 5, - "collatorSignature": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a", + "collatorSignature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a", "unprocessedIngress": [ [ 1, diff --git a/substrate/state_machine/src/lib.rs b/substrate/state_machine/src/lib.rs index d1357592d4..cd25cdcb90 100644 --- a/substrate/state_machine/src/lib.rs +++ b/substrate/state_machine/src/lib.rs @@ -259,11 +259,11 @@ mod tests { ext.set_storage(b"con:aut:len".to_vec(), vec![1u8, 0, 0, 0]); assert_eq!(ext.authorities(), Ok(vec![&[][..]])); - ext.set_storage(b"con:aut:::::".to_vec(), b"first".to_vec()); + ext.set_storage(b"con:aut:\0\0\0\0".to_vec(), b"first".to_vec()); assert_eq!(ext.authorities(), Ok(vec![&b"first"[..]])); ext.set_storage(b"con:aut:len".to_vec(), vec![2u8, 0, 0, 0]); - ext.set_storage(b"con:aut:\x01:::".to_vec(), b"second".to_vec()); + ext.set_storage(b"con:aut:\x01\0\0\0".to_vec(), b"second".to_vec()); assert_eq!(ext.authorities(), Ok(vec![&b"first"[..], &b"second"[..]])); } } diff --git a/substrate/wasm-runtime/polkadot/src/support/environment.rs b/substrate/wasm-runtime/polkadot/src/support/environment.rs index 4d8ac354a8..da2e9b18ec 100644 --- a/substrate/wasm-runtime/polkadot/src/support/environment.rs +++ b/substrate/wasm-runtime/polkadot/src/support/environment.rs @@ -14,6 +14,7 @@ pub fn with_env T>(f: F) -> T { f(&mut *eb) } +#[cfg(not(test))] pub fn env() -> Rc> { // Initialize it to a null value static mut SINGLETON: *const Rc> = 0 as *const Rc>; @@ -31,3 +32,24 @@ pub fn env() -> Rc> { (*SINGLETON).clone() } } + +#[cfg(test)] +pub fn env() -> Rc> { + // Initialize it to a null value + thread_local!{ + static SINGLETON: RefCell<*const Rc>> = RefCell::new(0 as *const Rc>); + } + + SINGLETON.with(|s| unsafe { + if *s.borrow() == 0 as *const Rc> { + // Make it + let singleton: Rc> = Rc::new(RefCell::new(Default::default())); + + // Put it in the heap so it can outlive this call + *s.borrow_mut() = transmute(Box::new(singleton)); + } + + // Now we give out a copy of the data that is safe to use concurrently. + (**s.borrow()).clone() + }) +} From 693c2f88e17c5ba9af4c111e71bef74f106a4c4c Mon Sep 17 00:00:00 2001 From: Gav Date: Fri, 19 Jan 2018 21:28:19 +0100 Subject: [PATCH 070/112] Repotting and docs. --- substrate/primitives/src/ed25519.rs | 54 ++-------------- substrate/primitives/src/hashing.rs | 88 +++++++++++++++++++++++++ substrate/primitives/src/hexdisplay.rs | 38 +++++++++++ substrate/primitives/src/lib.rs | 89 +------------------------- 4 files changed, 136 insertions(+), 133 deletions(-) create mode 100644 substrate/primitives/src/hashing.rs create mode 100644 substrate/primitives/src/hexdisplay.rs diff --git a/substrate/primitives/src/ed25519.rs b/substrate/primitives/src/ed25519.rs index e9ac7e473c..cdbbc194c7 100644 --- a/substrate/primitives/src/ed25519.rs +++ b/substrate/primitives/src/ed25519.rs @@ -4,6 +4,7 @@ use untrusted; use ring::{rand, signature}; use rustc_hex::FromHex; +/// Verify a message without type checking the parameters' types for the right size. pub fn verify(sig: &[u8], message: &[u8], public: &[u8]) -> bool { let public_key = untrusted::Input::from(public); let msg = untrusted::Input::from(message); @@ -27,9 +28,12 @@ pub struct Pair(signature::Ed25519KeyPair); pub struct Signature ([u8; 64]); impl Signature { + /// A new signature from the given 64-byte `data`. pub fn from(data: [u8; 64]) -> Self { Signature(data) } + + /// A new signature from the given slice that should be 64 bytes long. pub fn from_slice(data: &[u8]) -> Self { let mut r = [0u8; 64]; r.copy_from_slice(data); @@ -50,9 +54,12 @@ impl AsRef<[u8]> for Signature { } impl Public { + /// A new instance from the given 32-byte `data`. pub fn from(data: [u8; 32]) -> Self { Public(data) } + + /// A new instance from the given slice that should be 32 bytes long. pub fn from_slice(data: &[u8]) -> Self { let mut r = [0u8; 32]; r.copy_from_slice(data); @@ -166,53 +173,9 @@ impl PartialEq for Signature { } } -pub mod hexdisplay { - - pub struct HexDisplay<'a>(&'a [u8]); - - impl<'a> HexDisplay<'a> { - pub fn from(d: &'a AsBytesRef) -> Self { HexDisplay(d.as_bytes_ref()) } - } - - impl<'a> ::std::fmt::Display for HexDisplay<'a> { - fn fmt(&self, fmtr: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { - for byte in self.0 { - try!( fmtr.write_fmt(format_args!("{:02x}", byte))); - } - Ok(()) - } - } - - pub trait AsBytesRef { - fn as_bytes_ref(&self) -> &[u8]; - } - - impl AsBytesRef for [u8] { - fn as_bytes_ref(&self) -> &[u8] { &self } - } - - impl AsBytesRef for Vec { - fn as_bytes_ref(&self) -> &[u8] { &self } - } - - macro_rules! impl_non_endians { - ( $( $t:ty ),* ) => { $( - impl AsBytesRef for $t { - fn as_bytes_ref(&self) -> &[u8] { &self[..] } - } - )* } - } - - impl_non_endians!([u8; 1], [u8; 2], [u8; 3], [u8; 4], [u8; 5], [u8; 6], [u8; 7], [u8; 8], - [u8; 10], [u8; 12], [u8; 14], [u8; 16], [u8; 20], [u8; 24], [u8; 28], [u8; 32], [u8; 40], - [u8; 48], [u8; 56], [u8; 64], [u8; 80], [u8; 96], [u8; 112], [u8; 128]); - -} - #[cfg(test)] mod test { use super::*; - use super::hexdisplay::HexDisplay; #[test] fn test_vector_should_work() { @@ -238,7 +201,6 @@ mod test { fn seeded_pair_should_work() { let pair = Pair::from_seed(b"12345678901234567890123456789012"); let public = pair.public(); - println!("{}", HexDisplay::from(&public.0)); assert_eq!(public, "2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee".into()); let message = b"Something important"; let signature = pair.sign(&message[..]); @@ -252,8 +214,6 @@ mod test { assert_eq!(public, "2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee".into()); let message = FromHex::from_hex("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000").unwrap(); let signature = pair.sign(&message[..]); - println!("pub: {}", HexDisplay::from(&public.0)); - println!("sig: {}", HexDisplay::from(&signature.0)); assert!(signature.verify(&message[..], &public)); } } diff --git a/substrate/primitives/src/hashing.rs b/substrate/primitives/src/hashing.rs new file mode 100644 index 0000000000..b21e06391e --- /dev/null +++ b/substrate/primitives/src/hashing.rs @@ -0,0 +1,88 @@ +use blake2_rfc; +use twox_hash; + +/// Do a Blake2 512-bit hash and place result in `dest`. +pub fn blake2_512_into(data: &[u8], dest: &mut[u8; 64]) { + dest.copy_from_slice(blake2_rfc::blake2b::blake2b(64, &[], data).as_bytes()); +} + +/// Do a Blake2 512-bit hash and return result. +pub fn blake2_512(data: &[u8]) -> [u8; 64] { + let mut r: [u8; 64] = unsafe { ::std::mem::uninitialized() }; + blake2_512_into(data, &mut r); + r +} + +/// Do a Blake2 256-bit hash and place result in `dest`. +pub fn blake2_256_into(data: &[u8], dest: &mut[u8; 32]) { + dest.copy_from_slice(blake2_rfc::blake2b::blake2b(32, &[], data).as_bytes()); +} + +/// Do a Blake2 256-bit hash and return result. +pub fn blake2_256(data: &[u8]) -> [u8; 32] { + let mut r: [u8; 32] = unsafe { ::std::mem::uninitialized() }; + blake2_256_into(data, &mut r); + r +} + +/// Do a Blake2 128-bit hash and place result in `dest`. +pub fn blake2_128_into(data: &[u8], dest: &mut[u8; 16]) { + dest.copy_from_slice(blake2_rfc::blake2b::blake2b(16, &[], data).as_bytes()); +} + +/// Do a Blake2 128-bit hash and return result. +pub fn blake2_128(data: &[u8]) -> [u8; 16] { + let mut r: [u8; 16] = unsafe { ::std::mem::uninitialized() }; + blake2_128_into(data, &mut r); + r +} + +/// Do a XX 128-bit hash and place result in `dest`. +pub fn twox_128_into(data: &[u8], dest: &mut [u8; 16]) { + use ::std::hash::Hasher; + let mut h0 = twox_hash::XxHash::with_seed(0); + let mut h1 = twox_hash::XxHash::with_seed(1); + h0.write(data); + h1.write(data); + let r0 = h0.finish(); + let r1 = h1.finish(); + use byteorder::{ByteOrder, LittleEndian}; + LittleEndian::write_u64(&mut dest[0..8], r0); + LittleEndian::write_u64(&mut dest[8..16], r1); +} + +/// Do a XX 128-bit hash and return result. +pub fn twox_128(data: &[u8]) -> [u8; 16] { + let mut r: [u8; 16] = unsafe { ::std::mem::uninitialized() }; + twox_128_into(data, &mut r); + r +} + +/// Do a XX 256-bit hash and place result in `dest`. +pub fn twox_256_into(data: &[u8], dest: &mut [u8; 32]) { + use ::std::hash::Hasher; + use byteorder::{ByteOrder, LittleEndian}; + let mut h0 = twox_hash::XxHash::with_seed(0); + let mut h1 = twox_hash::XxHash::with_seed(1); + let mut h2 = twox_hash::XxHash::with_seed(2); + let mut h3 = twox_hash::XxHash::with_seed(3); + h0.write(data); + h1.write(data); + h2.write(data); + h3.write(data); + let r0 = h0.finish(); + let r1 = h1.finish(); + let r2 = h2.finish(); + let r3 = h3.finish(); + LittleEndian::write_u64(&mut dest[0..8], r0); + LittleEndian::write_u64(&mut dest[8..16], r1); + LittleEndian::write_u64(&mut dest[16..24], r2); + LittleEndian::write_u64(&mut dest[24..32], r3); +} + +/// Do a XX 256-bit hash and return result. +pub fn twox_256(data: &[u8]) -> [u8; 32] { + let mut r: [u8; 32] = unsafe { ::std::mem::uninitialized() }; + twox_256_into(data, &mut r); + r +} diff --git a/substrate/primitives/src/hexdisplay.rs b/substrate/primitives/src/hexdisplay.rs new file mode 100644 index 0000000000..708d5e0528 --- /dev/null +++ b/substrate/primitives/src/hexdisplay.rs @@ -0,0 +1,38 @@ +pub struct HexDisplay<'a>(&'a [u8]); + +impl<'a> HexDisplay<'a> { + pub fn from(d: &'a AsBytesRef) -> Self { HexDisplay(d.as_bytes_ref()) } +} + +impl<'a> ::std::fmt::Display for HexDisplay<'a> { + fn fmt(&self, fmtr: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { + for byte in self.0 { + try!( fmtr.write_fmt(format_args!("{:02x}", byte))); + } + Ok(()) + } +} + +pub trait AsBytesRef { + fn as_bytes_ref(&self) -> &[u8]; +} + +impl AsBytesRef for [u8] { + fn as_bytes_ref(&self) -> &[u8] { &self } +} + +impl AsBytesRef for Vec { + fn as_bytes_ref(&self) -> &[u8] { &self } +} + +macro_rules! impl_non_endians { + ( $( $t:ty ),* ) => { $( + impl AsBytesRef for $t { + fn as_bytes_ref(&self) -> &[u8] { &self[..] } + } + )* } +} + +impl_non_endians!([u8; 1], [u8; 2], [u8; 3], [u8; 4], [u8; 5], [u8; 6], [u8; 7], [u8; 8], + [u8; 10], [u8; 12], [u8; 14], [u8; 16], [u8; 20], [u8; 24], [u8; 28], [u8; 32], [u8; 40], + [u8; 48], [u8; 56], [u8; 64], [u8; 80], [u8; 96], [u8; 112], [u8; 128]); diff --git a/substrate/primitives/src/lib.rs b/substrate/primitives/src/lib.rs index cb7606add2..c774ec7f42 100644 --- a/substrate/primitives/src/lib.rs +++ b/substrate/primitives/src/lib.rs @@ -51,6 +51,8 @@ pub mod parachain; pub mod uint; pub mod validator; pub mod ed25519; +pub mod hexdisplay; +pub mod hashing; /// Alias to 160-bit hash when used in the context of an account address. pub type Address = hash::H160; @@ -59,94 +61,9 @@ pub type Signature = hash::H512; pub use self::hash::{H160, H256}; pub use self::uint::{U256, U512}; +pub use hashing::{blake2_256, twox_128, twox_256}; /// A hash function. pub fn hash(data: &[u8]) -> hash::H256 { blake2_256(data).into() } - -/// Do a Blake2 512-bit hash and place result in `dest`. -pub fn blake2_512_into(data: &[u8], dest: &mut[u8; 64]) { - dest.copy_from_slice(blake2_rfc::blake2b::blake2b(64, &[], data).as_bytes()); -} - -/// Do a Blake2 512-bit hash and return result. -pub fn blake2_512(data: &[u8]) -> [u8; 64] { - let mut r: [u8; 64] = unsafe { std::mem::uninitialized() }; - blake2_512_into(data, &mut r); - r -} - -/// Do a Blake2 256-bit hash and place result in `dest`. -pub fn blake2_256_into(data: &[u8], dest: &mut[u8; 32]) { - dest.copy_from_slice(blake2_rfc::blake2b::blake2b(32, &[], data).as_bytes()); -} - -/// Do a Blake2 256-bit hash and return result. -pub fn blake2_256(data: &[u8]) -> [u8; 32] { - let mut r: [u8; 32] = unsafe { std::mem::uninitialized() }; - blake2_256_into(data, &mut r); - r -} - -/// Do a Blake2 128-bit hash and place result in `dest`. -pub fn blake2_128_into(data: &[u8], dest: &mut[u8; 16]) { - dest.copy_from_slice(blake2_rfc::blake2b::blake2b(16, &[], data).as_bytes()); -} - -/// Do a Blake2 128-bit hash and return result. -pub fn blake2_128(data: &[u8]) -> [u8; 16] { - let mut r: [u8; 16] = unsafe { std::mem::uninitialized() }; - blake2_128_into(data, &mut r); - r -} - -/// Do a XX 128-bit hash and place result in `dest`. -pub fn twox_128_into(data: &[u8], dest: &mut [u8; 16]) { - use ::std::hash::Hasher; - let mut h0 = twox_hash::XxHash::with_seed(0); - let mut h1 = twox_hash::XxHash::with_seed(1); - h0.write(data); - h1.write(data); - let r0 = h0.finish(); - let r1 = h1.finish(); - use byteorder::{ByteOrder, LittleEndian}; - LittleEndian::write_u64(&mut dest[0..8], r0); - LittleEndian::write_u64(&mut dest[8..16], r1); -} - -/// Do a XX 128-bit hash and return result. -pub fn twox_128(data: &[u8]) -> [u8; 16] { - let mut r: [u8; 16] = unsafe { std::mem::uninitialized() }; - twox_128_into(data, &mut r); - r -} - -/// Do a XX 256-bit hash and place result in `dest`. -pub fn twox_256_into(data: &[u8], dest: &mut [u8; 32]) { - use ::std::hash::Hasher; - use byteorder::{ByteOrder, LittleEndian}; - let mut h0 = twox_hash::XxHash::with_seed(0); - let mut h1 = twox_hash::XxHash::with_seed(1); - let mut h2 = twox_hash::XxHash::with_seed(2); - let mut h3 = twox_hash::XxHash::with_seed(3); - h0.write(data); - h1.write(data); - h2.write(data); - h3.write(data); - let r0 = h0.finish(); - let r1 = h1.finish(); - let r2 = h2.finish(); - let r3 = h3.finish(); - LittleEndian::write_u64(&mut dest[0..8], r0); - LittleEndian::write_u64(&mut dest[8..16], r1); - LittleEndian::write_u64(&mut dest[16..24], r2); - LittleEndian::write_u64(&mut dest[24..32], r3); -} - -/// Do a XX 256-bit hash and return result. -pub fn twox_256(data: &[u8]) -> [u8; 32] { - let mut r: [u8; 32] = unsafe { std::mem::uninitialized() }; - twox_256_into(data, &mut r); - r -} From 96da4e2e7adab012380cb759679a9856fc127051 Mon Sep 17 00:00:00 2001 From: Gav Date: Fri, 19 Jan 2018 21:32:11 +0100 Subject: [PATCH 071/112] Docs and licence. --- substrate/primitives/src/ed25519.rs | 16 ++++++++++++++++ substrate/primitives/src/hashing.rs | 18 ++++++++++++++++++ substrate/primitives/src/hexdisplay.rs | 22 ++++++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/substrate/primitives/src/ed25519.rs b/substrate/primitives/src/ed25519.rs index cdbbc194c7..b28e0bde6e 100644 --- a/substrate/primitives/src/ed25519.rs +++ b/substrate/primitives/src/ed25519.rs @@ -1,3 +1,19 @@ +// 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 . + //! Simple Ed25519 API. use untrusted; diff --git a/substrate/primitives/src/hashing.rs b/substrate/primitives/src/hashing.rs index b21e06391e..f82ec7ef8b 100644 --- a/substrate/primitives/src/hashing.rs +++ b/substrate/primitives/src/hashing.rs @@ -1,3 +1,21 @@ +// 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 . + +//! Hashing functions. + use blake2_rfc; use twox_hash; diff --git a/substrate/primitives/src/hexdisplay.rs b/substrate/primitives/src/hexdisplay.rs index 708d5e0528..d6299a2e41 100644 --- a/substrate/primitives/src/hexdisplay.rs +++ b/substrate/primitives/src/hexdisplay.rs @@ -1,6 +1,26 @@ +// 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 . + +//! Wrapper type for byte collections that outputs hex. + +/// Simple wrapper to display hex representation of bytes. pub struct HexDisplay<'a>(&'a [u8]); impl<'a> HexDisplay<'a> { + /// Create new instance that will display `d` as a hex string when displayed. pub fn from(d: &'a AsBytesRef) -> Self { HexDisplay(d.as_bytes_ref()) } } @@ -13,7 +33,9 @@ impl<'a> ::std::fmt::Display for HexDisplay<'a> { } } +/// Simple trait to transferm various types to `&[u8]` pub trait AsBytesRef { + /// Transferm `self` into `&[u8]`. fn as_bytes_ref(&self) -> &[u8]; } From 6112e38629033e23b7a0645a75c498f489d7d3d8 Mon Sep 17 00:00:00 2001 From: Gav Date: Fri, 19 Jan 2018 22:04:18 +0100 Subject: [PATCH 072/112] Documentation. --- substrate/native-runtime/support/src/lib.rs | 18 ++++ .../polkadot/src/codec/endiansensitive.rs | 19 ++++ .../wasm-runtime/polkadot/src/codec/joiner.rs | 19 ++++ .../polkadot/src/codec/keyedvec.rs | 19 ++++ .../wasm-runtime/polkadot/src/codec/mod.rs | 18 ++++ .../polkadot/src/codec/slicable.rs | 19 ++++ .../polkadot/src/codec/streamreader.rs | 22 +++++ substrate/wasm-runtime/polkadot/src/lib.rs | 21 +++++ .../polkadot/src/runtime/consensus.rs | 18 ++++ .../wasm-runtime/polkadot/src/runtime/mod.rs | 18 ++++ .../polkadot/src/runtime/session.rs | 19 ++++ .../polkadot/src/runtime/staking.rs | 94 ++++++++++++------- .../polkadot/src/runtime/system.rs | 19 ++++ .../polkadot/src/runtime/timestamp.rs | 24 ++++- .../polkadot/src/support/environment.rs | 27 +++++- .../polkadot/src/support/function.rs | 19 ++++ .../wasm-runtime/polkadot/src/support/mod.rs | 18 ++++ .../polkadot/src/support/primitives.rs | 46 ++++++++- .../polkadot/src/support/statichex.rs | 23 +++++ .../polkadot/src/support/storable.rs | 23 +++++ .../polkadot/src/support/testing.rs | 26 +++++ 21 files changed, 488 insertions(+), 41 deletions(-) diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index caa7f3b272..cd1aa00eef 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -1,3 +1,21 @@ +// 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 . + +//! Support functions. + #[macro_use] extern crate environmental; extern crate polkadot_state_machine; diff --git a/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs b/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs index f1e042d886..a157628422 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs +++ b/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs @@ -1,3 +1,22 @@ +// 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 . + +//! Endian manager. + +/// Trait to allow conversion to a know endian representation when sensitive. pub trait EndianSensitive: Sized { fn to_le(self) -> Self { self } fn to_be(self) -> Self { self } diff --git a/substrate/wasm-runtime/polkadot/src/codec/joiner.rs b/substrate/wasm-runtime/polkadot/src/codec/joiner.rs index 817df8e4cb..92a5aa87fc 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/joiner.rs +++ b/substrate/wasm-runtime/polkadot/src/codec/joiner.rs @@ -1,6 +1,25 @@ +// 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 . + +//! Vec serialiser. + use runtime_support::Vec; use slicable::Slicable; +/// Trait to allow itself to be serialised into a `Vec` pub trait Joiner { fn join(self, value: &T) -> Self; } diff --git a/substrate/wasm-runtime/polkadot/src/codec/keyedvec.rs b/substrate/wasm-runtime/polkadot/src/codec/keyedvec.rs index fad6b1956f..1f803b7c62 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/keyedvec.rs +++ b/substrate/wasm-runtime/polkadot/src/codec/keyedvec.rs @@ -1,6 +1,25 @@ +// 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 . + +//! Serialiser and prepender. + use runtime_support::Vec; use slicable::Slicable; +/// Trait to allow itselg to be serialised and prepended by a given slice. pub trait KeyedVec { fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec; } diff --git a/substrate/wasm-runtime/polkadot/src/codec/mod.rs b/substrate/wasm-runtime/polkadot/src/codec/mod.rs index 5350dc05c1..7d9bc90c4f 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/codec/mod.rs @@ -1,3 +1,21 @@ +// 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 . + +//! Codec utils. + pub mod endiansensitive; pub mod streamreader; pub mod joiner; diff --git a/substrate/wasm-runtime/polkadot/src/codec/slicable.rs b/substrate/wasm-runtime/polkadot/src/codec/slicable.rs index 939d1591ca..5ec042ec9b 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/slicable.rs +++ b/substrate/wasm-runtime/polkadot/src/codec/slicable.rs @@ -1,3 +1,21 @@ +// 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 . + +//! Serialisation. + use runtime_support::{Vec, size_of, transmute, uninitialized, slice}; use joiner::Joiner; use endiansensitive::EndianSensitive; @@ -22,6 +40,7 @@ pub trait Slicable: Sized { fn size_of(_value: &[u8]) -> Option; } +/// Trait to mark that a type is not trivially (essentially "in place") serialisable. pub trait NonTrivialSlicable: Slicable {} impl Slicable for T { diff --git a/substrate/wasm-runtime/polkadot/src/codec/streamreader.rs b/substrate/wasm-runtime/polkadot/src/codec/streamreader.rs index 33d6fd8bfd..371ceed4ee 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/streamreader.rs +++ b/substrate/wasm-runtime/polkadot/src/codec/streamreader.rs @@ -1,17 +1,39 @@ +// 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 . + +//! Deserialiser. + use slicable::Slicable; +/// Simple deserialiser. pub struct StreamReader<'a> { data: &'a[u8], offset: usize, } impl<'a> StreamReader<'a> { + /// Create a new deserialiser based on the `data`. pub fn new(data: &'a[u8]) -> Self { StreamReader { data: data, offset: 0, } } + + /// Deserialise a single item from the data stream. pub fn read(&mut self) -> Option { let size = T::size_of(&self.data[self.offset..])?; let new_offset = self.offset + size; diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 7e8cc2233e..7a96b6cee4 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -1,3 +1,21 @@ +// 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 . + +//! The Polkadot runtime. This can be compiled with #[no_std], ready for Wasm. + #![cfg_attr(feature = "without-std", no_std)] #![cfg_attr(feature = "strict", deny(warnings))] @@ -20,11 +38,14 @@ use runtime_support::Vec; use slicable::Slicable; use primitives::{Block, UncheckedTransaction}; +/// Execute a block, with `input` being the canonical serialisation of the block. Returns the +/// empty vector. pub fn execute_block(input: Vec) -> Vec { runtime::system::execute_block(Block::from_slice(&input).unwrap()); Vec::new() } +/// Execute a given, serialised, transaction. Returns the empty vector. pub fn execute_transaction(input: Vec) -> Vec { runtime::system::execute_transaction(&UncheckedTransaction::from_slice(&input).unwrap()); Vec::new() diff --git a/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs b/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs index 757c032f03..1e12135806 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs @@ -1,3 +1,21 @@ +// 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 . + +//! Conensus module for runtime; manages the authority set ready for the native code. + use runtime_support::Vec; use storable::StorageVec; use primitives::SessionKey; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/mod.rs b/substrate/wasm-runtime/polkadot/src/runtime/mod.rs index 55a4801a5b..f83922c42f 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/mod.rs @@ -1,3 +1,21 @@ +// 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 . + +//! The Polkadot runtime. + #[allow(unused)] pub mod system; #[allow(unused)] diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs index b7ed1361ec..907b3e16b1 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -1,3 +1,22 @@ +// 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 . + +//! Session manager: is told the validators and allows them to manage their session keys for the +//! consensus module. + use runtime_support::Vec; use keyedvec::KeyedVec; use storable::{kill, Storable, StorageVec}; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index 6b41ddbd8f..c9fc6e9293 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -1,10 +1,32 @@ +// 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 . + +//! Staking manager: Handles balances and periodically determines the best set of validators. + use runtime_support::Vec; use keyedvec::KeyedVec; use storable::{Storable, StorageVec}; -use primitives::{BlockNumber, Balance, AccountID}; +use primitives::{BlockNumber, AccountID}; use runtime::{system, session}; -type Liquidity = u64; +/// The balance of an account. +pub type Balance = u64; + +/// The amount of bonding period left in an account. Measured in eras. +pub type Bondage = u64; struct IntentionStorageVec {} impl StorageVec for IntentionStorageVec { @@ -48,45 +70,13 @@ pub fn last_era_length_change() -> BlockNumber { Storable::lookup_default(b"sta:lec") } -/// The era has changed - enact new staking set. -/// -/// NOTE: This always happens on a session change. -fn new_era() { - // Increment current era. - (current_era() + 1).store(b"sta:era"); - - // Enact era length change. - let next_spe: u64 = Storable::lookup_default(b"sta:nse"); - if next_spe > 0 && next_spe != sessions_per_era() { - next_spe.store(b"sta:spe"); - system::block_number().store(b"sta:lec"); - } - - // TODO: evaluate desired staking amounts and nominations and optimise to find the best - // combination of validators, then use session::set_validators(). - - // for now, this just orders would-be stakers by their balances and chooses the top-most - // validator_count() of them. - let mut intentions = IntentionStorageVec::items() - .into_iter() - .map(|v| (balance(&v), v)) - .collect::>(); - intentions.sort_unstable_by(|&(b1, _), &(b2, _)| b2.cmp(&b1)); - session::set_validators( - &intentions.into_iter() - .map(|(_, v)| v) - .take(validator_count()) - .collect::>() - ); -} - /// The balance of a given account. pub fn balance(who: &AccountID) -> Balance { Storable::lookup_default(&who.to_keyed_vec(b"sta:bal:")) } /// The liquidity-state of a given account. -pub fn bondage(who: &AccountID) -> Liquidity { +pub fn bondage(who: &AccountID) -> Bondage { Storable::lookup_default(&who.to_keyed_vec(b"sta:bon:")) } @@ -134,6 +124,40 @@ pub fn check_new_era() { } } +// PRIVATE + +/// The era has changed - enact new staking set. +/// +/// NOTE: This always happens on a session change. +fn new_era() { + // Increment current era. + (current_era() + 1).store(b"sta:era"); + + // Enact era length change. + let next_spe: u64 = Storable::lookup_default(b"sta:nse"); + if next_spe > 0 && next_spe != sessions_per_era() { + next_spe.store(b"sta:spe"); + system::block_number().store(b"sta:lec"); + } + + // TODO: evaluate desired staking amounts and nominations and optimise to find the best + // combination of validators, then use session::set_validators(). + + // for now, this just orders would-be stakers by their balances and chooses the top-most + // validator_count() of them. + let mut intentions = IntentionStorageVec::items() + .into_iter() + .map(|v| (balance(&v), v)) + .collect::>(); + intentions.sort_unstable_by(|&(b1, _), &(b2, _)| b2.cmp(&b1)); + session::set_validators( + &intentions.into_iter() + .map(|(_, v)| v) + .take(validator_count()) + .collect::>() + ); +} + /// Set a new era length. Won't kick in until the next era change (at current length). fn set_sessions_per_era(new: BlockNumber) { new.store(b"sta:nse"); diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index f96bc40c93..5ffa03ed81 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -1,3 +1,22 @@ +// 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 . + +//! System manager: Handles all of the top-level stuff; executing block/transaction, setting code +//! and depositing logs. + use primitives::{Block, BlockNumber, Hash, UncheckedTransaction, TxOrder, Hashable}; use runtime_support::{Vec, swap}; use storable::Storable; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs index c6a3ac2a96..7040473b1a 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs @@ -1,10 +1,32 @@ -use primitives::Timestamp; +// 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 . + +//! Timestamp manager: just handles the current timestamp. + use storable::Storable; +/// Representation of a time. +pub type Timestamp = u64; + +/// Get the current time. pub fn get() -> Timestamp { Storable::lookup_default(b"tim:val") } +/// Set the current time. pub fn set(now: Timestamp) { now.store(b"tim:val") } diff --git a/substrate/wasm-runtime/polkadot/src/support/environment.rs b/substrate/wasm-runtime/polkadot/src/support/environment.rs index da2e9b18ec..c01a1f4e92 100644 --- a/substrate/wasm-runtime/polkadot/src/support/environment.rs +++ b/substrate/wasm-runtime/polkadot/src/support/environment.rs @@ -1,13 +1,36 @@ +// 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 . + +//! Environment API: Allows certain information to be accessed throughout the runtime. + use runtime_support::{Rc, RefCell, transmute, Box}; use primitives::{BlockNumber, Digest}; #[derive(Default)] +/// The information that can be accessed globally. pub struct Environment { + /// The current block number. pub block_number: BlockNumber, + /// The current block digest. pub digest: Digest, + /// The number of log items in this block that have been accounted for so far. pub next_log_index: usize, } +/// Do something with the environment and return its value. Keep the function short. pub fn with_env T>(f: F) -> T { let e = env(); let mut eb = e.borrow_mut(); @@ -15,7 +38,7 @@ pub fn with_env T>(f: F) -> T { } #[cfg(not(test))] -pub fn env() -> Rc> { +fn env() -> Rc> { // Initialize it to a null value static mut SINGLETON: *const Rc> = 0 as *const Rc>; @@ -34,7 +57,7 @@ pub fn env() -> Rc> { } #[cfg(test)] -pub fn env() -> Rc> { +fn env() -> Rc> { // Initialize it to a null value thread_local!{ static SINGLETON: RefCell<*const Rc>> = RefCell::new(0 as *const Rc>); diff --git a/substrate/wasm-runtime/polkadot/src/support/function.rs b/substrate/wasm-runtime/polkadot/src/support/function.rs index f0be93c4af..f4ee9c79e6 100644 --- a/substrate/wasm-runtime/polkadot/src/support/function.rs +++ b/substrate/wasm-runtime/polkadot/src/support/function.rs @@ -1,3 +1,21 @@ +// 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 . + +//! Function data: This describes a function that can be called from an external transaction. + use primitives::AccountID; use streamreader::StreamReader; use runtime::{staking, session, timestamp}; @@ -14,6 +32,7 @@ pub enum Function { } impl Function { + /// Derive `Some` value from a `u8`, or `None` if it's invalid. pub fn from_u8(value: u8) -> Option { match value { x if x == Function::StakingStake as u8 => Some(Function::StakingStake), diff --git a/substrate/wasm-runtime/polkadot/src/support/mod.rs b/substrate/wasm-runtime/polkadot/src/support/mod.rs index 802476cc1b..56ad3a355c 100644 --- a/substrate/wasm-runtime/polkadot/src/support/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/support/mod.rs @@ -1,3 +1,21 @@ +// 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 . + +//! Support code for the runtime. + pub mod primitives; pub mod function; pub mod environment; diff --git a/substrate/wasm-runtime/polkadot/src/support/primitives.rs b/substrate/wasm-runtime/polkadot/src/support/primitives.rs index dbe75aad11..3ab385d488 100644 --- a/substrate/wasm-runtime/polkadot/src/support/primitives.rs +++ b/substrate/wasm-runtime/polkadot/src/support/primitives.rs @@ -1,3 +1,21 @@ +// 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 . + +//! Primitive types. + use runtime_support::Vec; use streamreader::StreamReader; use joiner::Joiner; @@ -13,26 +31,36 @@ pub type AccountID = [u8; 32]; /// The Ed25519 pub key of an session that belongs to an authority. This is used as what the /// external environment/consensus algorithm calls an "authority". pub type SessionKey = AccountID; -pub type Balance = u64; +/// Indentifier for a chain. pub type ChainID = u64; -pub type Hash = [u8; 32]; +/// Index of a block in the chain. pub type BlockNumber = u64; -pub type Timestamp = u64; +/// Index of a transaction. pub type TxOrder = u64; +/// A hash of some data. +pub type Hash = [u8; 32]; #[derive(Clone, Default)] #[cfg_attr(test, derive(PartialEq, Debug))] +/// The digest of a block, useful for light-clients. pub struct Digest { + /// All logs that have happened in the block. pub logs: Vec>, } #[derive(Clone)] #[cfg_attr(test, derive(PartialEq, Debug))] +/// The header for a block. pub struct Header { + /// The parent block's "hash" (actually the Blake2-256 hash of its serialised header). pub parent_hash: Hash, + /// The block's number (how many ancestors does it have?). pub number: BlockNumber, + /// The root of the trie that represents this block's final storage map. pub state_root: Hash, + /// The root of the trie that represents this block's transactions, indexed by a 32-bit integer. pub transaction_root: Hash, + /// The digest for this block. pub digest: Digest, } @@ -71,10 +99,15 @@ impl Slicable for Header { impl NonTrivialSlicable for Header {} #[cfg_attr(test, derive(PartialEq, Debug))] +/// A vetted and verified transaction from the external world. pub struct Transaction { + /// Who signed it (note this is not a signature). pub signed: AccountID, + /// The number of transactions have come before from the same signer. pub nonce: TxOrder, + /// The function that should be called. pub function: Function, + /// Serialised input data to the function. pub input_data: Vec, } @@ -128,12 +161,16 @@ impl Hashable for T { impl NonTrivialSlicable for Transaction {} +/// A transactions right from the external world. Unchecked. pub struct UncheckedTransaction { + /// The actual transaction information. pub transaction: Transaction, + /// The signature; should be an Ed25519 signature applied to the serialised `transaction` field. pub signature: [u8; 64], } impl UncheckedTransaction { + /// Verify the signature. pub fn ed25519_verify(&self) -> bool { let msg = self.transaction.to_vec(); ed25519_verify(&self.signature, &msg, &self.transaction.signed) @@ -183,8 +220,11 @@ impl Slicable for UncheckedTransaction { impl NonTrivialSlicable for UncheckedTransaction {} #[cfg_attr(test, derive(PartialEq, Debug))] +/// A Polkadot relay chain block. pub struct Block { + /// The header of the block. pub header: Header, + /// All transactions. pub transactions: Vec, } diff --git a/substrate/wasm-runtime/polkadot/src/support/statichex.rs b/substrate/wasm-runtime/polkadot/src/support/statichex.rs index 774cb82538..152ceadc0b 100644 --- a/substrate/wasm-runtime/polkadot/src/support/statichex.rs +++ b/substrate/wasm-runtime/polkadot/src/support/statichex.rs @@ -1,6 +1,26 @@ +// 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 . + +//! Interpret a static string of hex as a desired type. + use rustc_hex::FromHex; +/// Trait to allow conversion from a static hex string to an instance. pub trait StaticHexConversion: Sized { + /// Convert the static str into Self. Use just like `From::from`. fn from_static_hex(hex: &'static str) -> Self; } @@ -18,7 +38,10 @@ macro_rules! impl_sizes { impl_sizes!(1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128); +/// Trait to allow converting from itself (only implemented for a static str) into some useful +/// type (which must implement `StaticHexConversion`). pub trait StaticHexInto { + /// Convert self (i.e. a static str) into the appropriate type. Use just like `Into::into`. fn convert(self) -> T; } diff --git a/substrate/wasm-runtime/polkadot/src/support/storable.rs b/substrate/wasm-runtime/polkadot/src/support/storable.rs index 80c7af2136..3caf3ed19b 100644 --- a/substrate/wasm-runtime/polkadot/src/support/storable.rs +++ b/substrate/wasm-runtime/polkadot/src/support/storable.rs @@ -1,16 +1,39 @@ +// 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 . + +//! Stuff to do with the runtime's storage. + use slicable::Slicable; use endiansensitive::EndianSensitive; use keyedvec::KeyedVec; use runtime_support::{self, twox_128, Vec}; +/// Trait for a value which may be stored in the storage DB. pub trait Storable { + /// Lookup the value in storage and deserialise, giving a default value if not found. fn lookup_default(key: &[u8]) -> Self where Self: Sized + Default { Self::lookup(key).unwrap_or_else(Default::default) } + /// Lookup `Some` value in storage and deserialise; `None` if it's not there. fn lookup(_key: &[u8]) -> Option where Self: Sized { unimplemented!() } + /// Place the value in storage under `key`. fn store(&self, key: &[u8]); } // TODO: consider using blake256 to avoid possible eclipse attack. +/// Remove `key` from storage. pub fn kill(key: &[u8]) { runtime_support::set_storage(&twox_128(key)[..], b""); } impl Storable for T { diff --git a/substrate/wasm-runtime/polkadot/src/support/testing.rs b/substrate/wasm-runtime/polkadot/src/support/testing.rs index a617405e79..e2e7b40562 100644 --- a/substrate/wasm-runtime/polkadot/src/support/testing.rs +++ b/substrate/wasm-runtime/polkadot/src/support/testing.rs @@ -1,10 +1,30 @@ +// 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 . + +//! Testing helpers. + use runtime_support::{NoError, Externalities}; use std::collections::HashMap; use primitives::AccountID; use statichex::StaticHexInto; #[derive(Debug, Default)] +/// Simple externaties implementation. pub struct TestExternalities { + /// The storage map. pub storage: HashMap, Vec>, } @@ -29,16 +49,20 @@ macro_rules! map { ) } +/// One account (to which we know the secret key). pub fn one() -> AccountID { "2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee".convert() } +/// Another account (secret key known). pub fn two() -> AccountID { "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a".convert() } +/// Hex display, this time for no_std. See main codebase for documentation. pub struct HexDisplay<'a>(&'a [u8]); impl<'a> HexDisplay<'a> { + /// See main codebase for documentation. pub fn from(d: &'a AsBytesRef) -> Self { HexDisplay(d.as_bytes_ref()) } } @@ -51,7 +75,9 @@ impl<'a> ::std::fmt::Display for HexDisplay<'a> { } } +/// See main codebase for documentation. pub trait AsBytesRef { + /// See main codebase for documentation. fn as_bytes_ref(&self) -> &[u8]; } From c2fca83ffff07a4e22ee4a117698750687b25c47 Mon Sep 17 00:00:00 2001 From: Gav Date: Fri, 19 Jan 2018 22:09:01 +0100 Subject: [PATCH 073/112] Remove superfluous code. --- substrate/native-runtime/support/src/lib.rs | 26 ++++-------------- substrate/wasm-runtime/support/src/lib.rs | 17 ------------ .../release/runtime_polkadot.compact.wasm | Bin 37802 -> 37802 bytes .../release/runtime_polkadot.wasm | Bin 37859 -> 37859 bytes 4 files changed, 5 insertions(+), 38 deletions(-) diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index cd1aa00eef..348c0b17a9 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -//! Support functions. +//! The with-std support functions for the runtime. #[macro_use] extern crate environmental; @@ -36,6 +36,7 @@ pub use polkadot_state_machine::Externalities; // TODO: use the real error, not NoError. #[derive(Debug)] +/// As it says - an empty type we use for errors. pub struct NoError; impl fmt::Display for NoError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "") } @@ -43,12 +44,15 @@ impl fmt::Display for NoError { environmental!(ext : Externalities + 'static); +/// Get `key` from storage and return a `Vec`, empty if there's a problem. pub fn storage(key: &[u8]) -> Vec { ext::with(|ext| ext.storage(key).ok().map(|s| s.to_vec())) .unwrap_or(None) .unwrap_or_else(|| vec![]) } +/// Get `key` from storage, placing the value into `value_out` (as much as possible) and return +/// the number of bytes that the key in storage was. pub fn read_storage(key: &[u8], value_out: &mut [u8]) -> usize { ext::with(|ext| { if let Ok(value) = ext.storage(key) { @@ -61,24 +65,6 @@ pub fn read_storage(key: &[u8], value_out: &mut [u8]) -> usize { }).unwrap_or(0) } -pub fn storage_into(_key: &[u8]) -> Option { - let size = size_of::(); - - ext::with(|ext| { - if let Ok(value) = ext.storage(_key) { - if value.len() == size { - unsafe { - let mut result: T = std::mem::uninitialized(); - std::slice::from_raw_parts_mut(transmute::<*mut T, *mut u8>(&mut result), size) - .copy_from_slice(&value); - return Some(result); - } - } - } - None - }).unwrap_or(None) -} - pub fn set_storage(key: &[u8], value: &[u8]) { ext::with(|ext| ext.set_storage(key.to_vec(), value.to_vec()) @@ -149,8 +135,6 @@ mod tests { assert_eq!(storage(b"hello"), b"world".to_vec()); assert_eq!(storage(b"foo"), b"".to_vec()); set_storage(b"foo", &[1, 2, 3][..]); - assert_eq!(storage_into::<[u8; 3]>(b"foo"), Some([1, 2, 3])); - assert_eq!(storage_into::<[u8; 3]>(b"hello"), None); true })); diff --git a/substrate/wasm-runtime/support/src/lib.rs b/substrate/wasm-runtime/support/src/lib.rs index bc987ff396..b65b574351 100644 --- a/substrate/wasm-runtime/support/src/lib.rs +++ b/substrate/wasm-runtime/support/src/lib.rs @@ -43,23 +43,6 @@ pub fn storage(key: &[u8]) -> Vec { } } -pub fn storage_into(key: &[u8]) -> Option { - let mut result: T; - let size = size_of::(); - let written; - unsafe { - result = uninitialized(); - let result_as_byte_blob = transmute::<*mut T, *mut u8>(&mut result); - written = ext_get_storage_into(&key[0], key.len() as u32, result_as_byte_blob, size as u32) as usize; - } - // Only return a fully written value. - if written == size { - Some(result) - } else { - None - } -} - pub fn set_storage(key: &[u8], value: &[u8]) { unsafe { ext_set_storage( diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm index 5f357f211861828f797bbe3bf8388b2839067a07..ddd9dc70e64e3b02e101f88ad65bd0a5af897e86 100644 GIT binary patch delta 108 zcmZ3roN3i^rVamO7@utZFC(c1q$J&0S%8$hw-6`O8-~d`4oaItLoP5fzS*o6<_)5X z!b9X4zf2aWFxmXO%tl6qqqro|Dk(9?iox*>12=@1p9kc9Vc=#5$>kNNPL7`J4*;MS BCiVaT delta 108 zcmZ3roN3i^rVamO7~gFEFC(c1q$J&0S%8$hw-6`O7lz3?4oaItLoP5fe%Y)R<_)5X z!b9X4pG+30FxmXO%tl6qy|^UNDz7+|!SM|PHwTE5l$c}1;P?f`%g?i#96i||0Iy9a A761SM diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm index 700194bb0a902a08b3704ed1a25f78b67a0e113e..8d3d3fb1ee5ffba092f881fdbe5e5c3780f7d23b 100644 GIT binary patch delta 107 zcmaF7oaym$rVTo>j88V}%1UYhDR*~P79i#8EyT(AW^+QwXGX?1lM_NjH)n>K0hyZ@ zgons8ewl1nVX|4X++9Y6qqro|Dk(9?iox*>12=@1p9kc9Vc=#5$>kNNPM$K^9{^sN BCWin3 delta 107 zcmaF7oaym$rVTo>jBhsU%1UYhDR*~P79i#8EyT(AWphHvXGX>^lM_NjH)n>K0hyZ@ zgons8KACJ+VX|4X++9Y6y|^UNDz7+|!SM|PHwTE5l$c}1;P?f`%g?i#JY}*!0Bz4E ArvLx| From 1d872d7cce3bf51b82896e65088bf70ae4d30d2a Mon Sep 17 00:00:00 2001 From: Gav Date: Fri, 19 Jan 2018 22:39:47 +0100 Subject: [PATCH 074/112] Remove dummy key. --- substrate/pkcs8.key | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 substrate/pkcs8.key diff --git a/substrate/pkcs8.key b/substrate/pkcs8.key deleted file mode 100644 index 250fbac646..0000000000 --- a/substrate/pkcs8.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDMpfNjaigc9FKC -8owWoKvAua3O1es2CB7Gq6pFI4Ctv34Wt5XSk83XkSXLOsf2ib1zCpzLUQSVLtH1 -c05uTH6rXLmjbH3lFOUCqD41dIveqo72sekHnYjS23ME2v5JCkg9YFmn32FffHGt -2Uaho+MQZWbpT3SD5tKRdaUUx1f/i16oB4Fnk8zCdQ7NPFru+WUV0cvQnK3rOpOo -KbK59Jo04bHmf/EPeVmxonwt/nmAJRUemuQXPl1cH8sk+t6Bxxp9FLzX6rtmpGDk -mBwrYBNC5auT3L1V2xabI2TKobd/qa+9/Sz41PeHsYLX/cu9Iplvj+LU85gYwv5d -kjvMEI7pAgMBAAECggEBAID7z21HSUUGkMLL0JOqbNYpsWx906PYdl1NcSHmgIIC -AZyb1ShF1CUb7LAsuj+fDPLnK2/R/otwWRDUvggy2ltzM+XWyXqLMtP76kmSzV1o -Lnc6Jt+P4N7VRac3x7GNc36LrbZqylp+er/SA/x46PI6lyRR2eQQpYLcnVF9Wu9K -bbTQ9nH+hxJiRG85GXKjeFkIj7PXBYAiYYcgiPF1RfB3o2R0cXZI24Y5/Ufc3OKg -Jws/VsTIzoxoLd3u6rDKX/N40/VBrGqv76HFqVwgnbxeG+i6HZNIAvZn+6m3a6l5 -APIZp7FfLJ1vZaHP7S7GeNmcz+eJ9Y/FanItohJGfqECgYEA5d17o9Ol3H+6wkQk -a3LU03NfvcdU5TqTOGvzx6yGGASjlByZWb7rMsRMyQ/wP60j+2Hd/G4rXbkF6vee -5uen7geJ6bzhUev1nd1NDcVdZay8x0r3huePUV96k+wU1IrOZrZddlqPyUJMctDy -VbwbDPM0saGx0xIlx/JOC1kEEr0CgYEA4+p/TSEq9DWH5QaMlVxBp48HY4Yrv/gQ -UmNUbCyd7J21Re+7cY3ZGF5IoC2l4K4yPM6ovNipkX9WDZrw8T68sD8yTQzL/tDE -CuXxG+X0b81k5UiZBFIGXiBb8JpoHRKNNGjZTZyBNhOKc902oKoNyTKILX3qI/aL -M2v/SELm5Z0CgYEAx+XZnPn09pF5t3GM/ogpPw3Jh/+t+376AooWwWFuZ7q5Cpfo -YFygq1B8uimLM8T9UqKkat7gBaxe0hyvanyw1FZoAAXLKPP7cGLAnKYzd7VFoka2 -hfIf95MBxVv8LW3c2wPiuYc+HbbzRrIg3KAuIg/qlkNYoobYpk44wrOR0D0CgYB0 -RNeGaGo6ROi7nHixZWwU57FUQ0kkWI8zCHsz6Br0b4vfTqooBr3+YXLZTBA4K4Vz -YdXQ6RKwJ+6laCqMV334x3SIvAOBTc0E5kL3AXuOYZCcK0nsW0/mSsm8V3jPg/xH -BUn9/t4n0RYrf2lz0uzPfBjeZELC7+4ZYHnNyltyPQKBgQCvT40UwZ5yHAt3leWG -stGRTkbupenh2z23hXY0Cio8Zqa7KE5jBWdF4uu27ScK4rhFdS1sgQJFghj6SxRO -VT5PQuRP9ETJIVwNgNQbAxbfeg8DADKGAWX9W5r//WlW1xH0/tSAxX6Pp/IiT9or -cRljrhP8zW6qhj3BKjdivPDgPw== ------END PRIVATE KEY----- From cb730ff74ab6c88de3c56e9c684154cf6c2c6b01 Mon Sep 17 00:00:00 2001 From: Gav Date: Fri, 19 Jan 2018 22:40:25 +0100 Subject: [PATCH 075/112] Remove other superfluous file. --- substrate/ed25519.pk8 | Bin 85 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 substrate/ed25519.pk8 diff --git a/substrate/ed25519.pk8 b/substrate/ed25519.pk8 deleted file mode 100644 index 57a8e9f84df1dc3175d02132f88bf7d03563ed8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85 zcmV-b0IL5mQvv}2Fa-t!D`jv5A_O2jp9~yh%qqhDL7XlV#y11mAEmT)YK|2S8mY`X rKcB~;BLg7-wIOt@fg3EC6j=CGA>0MTxofFio@CXjjO!~zYbh_!erz9j From 6303c7900dc6746b6ea233d618179267ce0d9635 Mon Sep 17 00:00:00 2001 From: Gav Date: Sat, 20 Jan 2018 09:48:33 +0100 Subject: [PATCH 076/112] Optimise with swap_remove --- substrate/wasm-runtime/polkadot/src/runtime/staking.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index c9fc6e9293..fc7c12798e 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -99,7 +99,7 @@ pub fn transfer(transactor: &AccountID, dest: &AccountID, value: Balance) { pub fn stake(transactor: &AccountID) { let mut intentions = IntentionStorageVec::items(); // can't be in the list twice. - assert!(intentions.iter().find(|t| *t == transactor).is_none()); + assert!(intentions.iter().find(|t| *t == transactor).is_none(), "Cannot stake if already staked."); intentions.push(transactor.clone()); IntentionStorageVec::set_items(&intentions); u64::max_value().store(&transactor.to_keyed_vec(b"sta:bon:")); @@ -110,8 +110,11 @@ pub fn stake(transactor: &AccountID) { /// Effects will be felt at the beginning of the next era. pub fn unstake(transactor: &AccountID) { let mut intentions = IntentionStorageVec::items(); - // TODO: use swap remove. - let intentions = intentions.into_iter().filter(|t| t != transactor).collect::>(); + if let Some(position) = intentions.iter().position(|t| t == transactor) { + intentions.swap_remove(position); + } else { + panic!("Cannot unstake if not already staked."); + } IntentionStorageVec::set_items(&intentions); (current_era() + bonding_duration()).store(&transactor.to_keyed_vec(b"sta:bon:")); } From 2789bc2b8fb5b22b6cfc8ed96c99290eb2337fc5 Mon Sep 17 00:00:00 2001 From: Gav Date: Sun, 21 Jan 2018 22:35:25 +0100 Subject: [PATCH 077/112] Simple governance subsytem. --- substrate/executor/src/wasm_executor.rs | 5 +- substrate/native-runtime/support/src/lib.rs | 13 ++- .../polkadot/src/codec/endiansensitive.rs | 5 + .../polkadot/src/codec/slicable.rs | 24 ++-- substrate/wasm-runtime/polkadot/src/lib.rs | 2 +- .../polkadot/src/runtime/governance.rs | 97 ++++++++++++++++ .../wasm-runtime/polkadot/src/runtime/mod.rs | 4 +- .../polkadot/src/runtime/staking.rs | 108 ++++++++++-------- .../polkadot/src/support/function.rs | 16 ++- .../wasm-runtime/polkadot/src/support/mod.rs | 1 + .../polkadot/src/support/primitives.rs | 20 +++- .../polkadot/src/support/proposal.rs | 108 ++++++++++++++++++ .../polkadot/src/support/statichex.rs | 11 +- .../polkadot/src/support/storable.rs | 23 ++-- substrate/wasm-runtime/support/src/lib.rs | 6 +- 15 files changed, 360 insertions(+), 83 deletions(-) create mode 100644 substrate/wasm-runtime/polkadot/src/runtime/governance.rs create mode 100644 substrate/wasm-runtime/polkadot/src/support/proposal.rs diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index 7fc9a741f8..d0bc908136 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -128,11 +128,12 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, this.memory.write_primitive(written_out, written); offset as u32 }, - ext_get_storage_into(key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32) -> u32 => { + ext_get_storage_into(key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32, value_offset: u32) -> u32 => { if let Ok(key) = this.memory.get(key_data, key_len as usize) { if let Ok(value) = this.ext.storage(&key) { + let value = &value[value_offset as usize..]; let written = ::std::cmp::min(value_len as usize, value.len()); - let _ = this.memory.set(value_data, &value[0..written]); + let _ = this.memory.set(value_data, &value[..written]); written as u32 } else { 0 } } else { 0 } diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index 348c0b17a9..7adf9a904b 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -47,24 +47,29 @@ environmental!(ext : Externalities + 'static); /// Get `key` from storage and return a `Vec`, empty if there's a problem. pub fn storage(key: &[u8]) -> Vec { ext::with(|ext| ext.storage(key).ok().map(|s| s.to_vec())) - .unwrap_or(None) - .unwrap_or_else(|| vec![]) + .expect("read_storage cannot be called outside of an Externalities-provided environment.") + .unwrap_or_else(Vec::new) } /// Get `key` from storage, placing the value into `value_out` (as much as possible) and return /// the number of bytes that the key in storage was. -pub fn read_storage(key: &[u8], value_out: &mut [u8]) -> usize { +pub fn read_storage(key: &[u8], value_out: &mut [u8], value_offset: usize) -> usize { ext::with(|ext| { if let Ok(value) = ext.storage(key) { + let value = &value[value_offset..]; let written = ::std::cmp::min(value.len(), value_out.len()); value_out[0..written].copy_from_slice(&value[0..written]); value.len() } else { + // no-entry is treated as an empty vector of bytes. + // TODO: consider allowing empty-vector to exist separately to no-entry (i.e. return + // Option) 0 } - }).unwrap_or(0) + }).expect("read_storage cannot be called outside of an Externalities-provided environment.") } +/// Set the storage to some particular key. pub fn set_storage(key: &[u8], value: &[u8]) { ext::with(|ext| ext.set_storage(key.to_vec(), value.to_vec()) diff --git a/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs b/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs index a157628422..734067d234 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs +++ b/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs @@ -44,6 +44,11 @@ macro_rules! impl_non_endians { )* } } +// TODO: this is fine as long as bool is one byte. it'll break if llvm tries to use more. happily, +// this isn't an issue for the forseeable future. if it ever happens, then it should be implemented +// as endian sensitive. +impl EndianSensitive for bool {} + impl_endians!(u16, u32, u64, usize, i16, i32, i64, isize); impl_non_endians!(u8, i8, [u8; 1], [u8; 2], [u8; 3], [u8; 4], [u8; 5], [u8; 6], [u8; 7], [u8; 8], [u8; 10], [u8; 12], [u8; 14], [u8; 16], [u8; 20], [u8; 24], [u8; 28], [u8; 32], [u8; 40], diff --git a/substrate/wasm-runtime/polkadot/src/codec/slicable.rs b/substrate/wasm-runtime/polkadot/src/codec/slicable.rs index 5ec042ec9b..1c783e39df 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/slicable.rs +++ b/substrate/wasm-runtime/polkadot/src/codec/slicable.rs @@ -23,8 +23,10 @@ use endiansensitive::EndianSensitive; /// Trait that allows zero-copy read/write of value-references to/from slices in LE format. pub trait Slicable: Sized { fn from_slice(value: &[u8]) -> Option { - Self::set_as_slice(|out| if value.len() == out.len() { - out.copy_from_slice(&value); + Self::set_as_slice(&|out, offset| if value.len() >= out.len() + offset { + let value = &value[offset..]; + let len = out.len(); + out.copy_from_slice(&value[0..len]); true } else { false @@ -33,7 +35,7 @@ pub trait Slicable: Sized { fn to_vec(&self) -> Vec { self.as_slice_then(|s| s.to_vec()) } - fn set_as_slice bool>(set_slice: F) -> Option; + fn set_as_slice bool>(set_slice: &F) -> Option; fn as_slice_then R>(&self, f: F) -> R { f(&self.to_vec()) } @@ -44,13 +46,13 @@ pub trait Slicable: Sized { pub trait NonTrivialSlicable: Slicable {} impl Slicable for T { - fn set_as_slice bool>(fill_slice: F) -> Option { + fn set_as_slice bool>(fill_slice: &F) -> Option { let size = size_of::(); let mut result: T = unsafe { uninitialized() }; let result_slice = unsafe { slice::from_raw_parts_mut(transmute::<*mut T, *mut u8>(&mut result), size) }; - if fill_slice(result_slice) { + if fill_slice(result_slice, 0) { Some(result.from_le()) } else { None @@ -74,8 +76,16 @@ impl Slicable for Vec { fn from_slice(value: &[u8]) -> Option { Some(value[4..].to_vec()) } - fn set_as_slice bool>(_fill_slice: F) -> Option { - unimplemented!(); + fn set_as_slice bool>(fill_slice: &F) -> Option { + u32::set_as_slice(fill_slice).and_then(|len| { + let mut v = Vec::with_capacity(len as usize); + unsafe { v.set_len(len as usize); } + if fill_slice(&mut v, 4) { + Some(v) + } else { + None + } + }) } fn to_vec(&self) -> Vec { let mut r: Vec = Vec::new().join(&(self.len() as u32)); diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 7a96b6cee4..713d8eb091 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -30,7 +30,7 @@ mod codec; mod support; mod runtime; pub use codec::{endiansensitive, streamreader, joiner, slicable, keyedvec}; -pub use support::{primitives, function, environment, storable}; +pub use support::{primitives, function, proposal, environment, storable}; #[cfg(test)] pub use support::{testing, statichex}; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs new file mode 100644 index 0000000000..783522ffdf --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs @@ -0,0 +1,97 @@ +// 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 . + +//! Governance system: Handles administration and dispatch of sensitive operations including +//! setting new code, minting new tokens and changing parameters. + +use runtime_support::Vec; +use keyedvec::KeyedVec; +use storable::{Storable, StorageVec, kill}; +use primitives::{AccountID, Hash, BlockNumber}; +use proposal::Proposal; +use runtime::{staking, system, session}; + +// TRANSACTION API + +pub fn propose(transactor: &AccountID, proposal: &Proposal) { + if Proposal::lookup(b"gov:pro").is_some() { + panic!("there may only be one proposal per era."); + } + proposal.store(b"gov:pro"); + approve(transactor, staking::current_era()); +} + +pub fn approve(transactor: &AccountID, era_index: BlockNumber) { + if era_index != staking::current_era() { + panic!("approval vote applied on non-current era.") + } + if Proposal::lookup(b"gov:pro").is_none() { + panic!("there must be a proposal in order to approve."); + } + let key = transactor.to_keyed_vec(b"gov:app:"); + if bool::lookup(&key).is_some() { + panic!("transactor may not approve a proposal twice in one era."); + } + true.store(&key); + (approval_count() + 1).store(b"gov:app"); +} + +// INSPECTION API + +pub fn approval_count() -> u32 { + Storable::lookup_default(b"gov:app") +} + +pub fn approval_ppm_required() -> u32 { + Storable::lookup(b"gov:apr").unwrap_or(1000) +} + +pub fn approvals_required() -> u32 { + approval_ppm_required() * staking::validator_count() as u32 / 1000 +} + +// PUBLIC API + +/// Current era is ending; we should finish up any proposals. +pub fn end_of_an_era() { + // TODO: tally up votes for the current proposal, if any. enact if there are sufficient + // approvals. + if let Some(proposal) = Proposal::lookup(b"gov:pro") { + let enact = approval_count() >= approvals_required(); + + // clear proposal + reset_proposal(); + + if enact { + proposal.enact(); + } + } +} + +// PRIVATE API + +fn reset_proposal() { + session::validators().into_iter().for_each(|v| { + kill(&v.to_keyed_vec(b"gov:app:")); + }); + kill(b"gov:pro"); + kill(b"gov:app"); +} + +#[cfg(test)] +mod tests { + // TODO +} diff --git a/substrate/wasm-runtime/polkadot/src/runtime/mod.rs b/substrate/wasm-runtime/polkadot/src/runtime/mod.rs index f83922c42f..6af33d6a65 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/mod.rs @@ -26,5 +26,7 @@ pub mod staking; pub mod timestamp; #[allow(unused)] pub mod session; +#[allow(unused)] +pub mod governance; -// TODO: governance, polkadao +// TODO: polkadao diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index fc7c12798e..96843290a2 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -16,11 +16,11 @@ //! Staking manager: Handles balances and periodically determines the best set of validators. -use runtime_support::Vec; +use runtime_support::{Vec, RefCell}; use keyedvec::KeyedVec; use storable::{Storable, StorageVec}; use primitives::{BlockNumber, AccountID}; -use runtime::{system, session}; +use runtime::{system, session, governance}; /// The balance of an account. pub type Balance = u64; @@ -31,7 +31,7 @@ pub type Bondage = u64; struct IntentionStorageVec {} impl StorageVec for IntentionStorageVec { type Item = AccountID; - const PREFIX: &'static[u8] = b"ses:wil:"; + const PREFIX: &'static[u8] = b"sta:wil:"; } // Each identity's stake may be in one of three bondage states, given by an integer: @@ -40,6 +40,55 @@ impl StorageVec for IntentionStorageVec { // - n | n > current_era(): deactivating: recently representing a validator and not yet // ready for transfer. +// TRANSACTION API + +/// Transfer some unlocked staking balance to another staker. +pub fn transfer(transactor: &AccountID, dest: &AccountID, value: Balance) { + let from_key = transactor.to_keyed_vec(b"sta:bal:"); + let from_balance = Balance::lookup_default(&from_key); + assert!(from_balance >= value); + let to_key = dest.to_keyed_vec(b"sta:bal:"); + let to_balance: Balance = Storable::lookup_default(&to_key); + assert!(bondage(transactor) <= bondage(dest)); + assert!(to_balance + value > to_balance); // no overflow + (from_balance - value).store(&from_key); + (to_balance + value).store(&to_key); +} + +/// Declare the desire to stake for the transactor. +/// +/// Effects will be felt at the beginning of the next era. +pub fn stake(transactor: &AccountID) { + let mut intentions = IntentionStorageVec::items(); + // can't be in the list twice. + assert!(intentions.iter().find(|t| *t == transactor).is_none(), "Cannot stake if already staked."); + intentions.push(transactor.clone()); + IntentionStorageVec::set_items(&intentions); + u64::max_value().store(&transactor.to_keyed_vec(b"sta:bon:")); +} + +/// Retract the desire to stake for the transactor. +/// +/// Effects will be felt at the beginning of the next era. +pub fn unstake(transactor: &AccountID) { + let mut intentions = IntentionStorageVec::items(); + if let Some(position) = intentions.iter().position(|t| t == transactor) { + intentions.swap_remove(position); + } else { + panic!("Cannot unstake if not already staked."); + } + IntentionStorageVec::set_items(&intentions); + (current_era() + bonding_duration()).store(&transactor.to_keyed_vec(b"sta:bon:")); +} + +// PUBLIC API + +pub fn set_sessions_per_era(new: BlockNumber) { + new.store(b"sta:nse"); +} + +// INSPECTION API + /// The length of the bonding duration in eras. pub fn bonding_duration() -> BlockNumber { Storable::lookup_default(b"sta:loc") @@ -80,45 +129,6 @@ pub fn bondage(who: &AccountID) -> Bondage { Storable::lookup_default(&who.to_keyed_vec(b"sta:bon:")) } -/// Transfer some unlocked staking balance to another staker. -pub fn transfer(transactor: &AccountID, dest: &AccountID, value: Balance) { - let from_key = transactor.to_keyed_vec(b"sta:bal:"); - let from_balance = Balance::lookup_default(&from_key); - assert!(from_balance >= value); - let to_key = dest.to_keyed_vec(b"sta:bal:"); - let to_balance: Balance = Storable::lookup_default(&to_key); - assert!(bondage(transactor) <= bondage(dest)); - assert!(to_balance + value > to_balance); // no overflow - (from_balance - value).store(&from_key); - (to_balance + value).store(&to_key); -} - -/// Declare the desire to stake for the transactor. -/// -/// Effects will be felt at the beginning of the next era. -pub fn stake(transactor: &AccountID) { - let mut intentions = IntentionStorageVec::items(); - // can't be in the list twice. - assert!(intentions.iter().find(|t| *t == transactor).is_none(), "Cannot stake if already staked."); - intentions.push(transactor.clone()); - IntentionStorageVec::set_items(&intentions); - u64::max_value().store(&transactor.to_keyed_vec(b"sta:bon:")); -} - -/// Retract the desire to stake for the transactor. -/// -/// Effects will be felt at the beginning of the next era. -pub fn unstake(transactor: &AccountID) { - let mut intentions = IntentionStorageVec::items(); - if let Some(position) = intentions.iter().position(|t| t == transactor) { - intentions.swap_remove(position); - } else { - panic!("Cannot unstake if not already staked."); - } - IntentionStorageVec::set_items(&intentions); - (current_era() + bonding_duration()).store(&transactor.to_keyed_vec(b"sta:bon:")); -} - /// Hook to be called after to transaction processing. pub fn check_new_era() { // check block number and call new_era if necessary. @@ -131,8 +141,12 @@ pub fn check_new_era() { /// The era has changed - enact new staking set. /// -/// NOTE: This always happens on a session change. +/// NOTE: This always happens immediately before a session change to ensure that new validators +/// get a chance to set their session keys. fn new_era() { + // Inform governance module that it's the end of an era + governance::end_of_an_era(); + // Increment current era. (current_era() + 1).store(b"sta:era"); @@ -143,9 +157,8 @@ fn new_era() { system::block_number().store(b"sta:lec"); } - // TODO: evaluate desired staking amounts and nominations and optimise to find the best + // evaluate desired staking amounts and nominations and optimise to find the best // combination of validators, then use session::set_validators(). - // for now, this just orders would-be stakers by their balances and chooses the top-most // validator_count() of them. let mut intentions = IntentionStorageVec::items() @@ -161,11 +174,6 @@ fn new_era() { ); } -/// Set a new era length. Won't kick in until the next era change (at current length). -fn set_sessions_per_era(new: BlockNumber) { - new.store(b"sta:nse"); -} - #[cfg(test)] mod tests { use runtime_support::{with_externalities, twox_128}; diff --git a/substrate/wasm-runtime/polkadot/src/support/function.rs b/substrate/wasm-runtime/polkadot/src/support/function.rs index f4ee9c79e6..dd54ba1080 100644 --- a/substrate/wasm-runtime/polkadot/src/support/function.rs +++ b/substrate/wasm-runtime/polkadot/src/support/function.rs @@ -18,9 +18,9 @@ use primitives::AccountID; use streamreader::StreamReader; -use runtime::{staking, session, timestamp}; +use runtime::{staking, session, timestamp, governance}; -/// The functions that a transaction can call (and be dispatched to). +/// Public functions that can be dispatched to. #[cfg_attr(test, derive(PartialEq, Debug))] #[derive(Clone, Copy)] pub enum Function { @@ -29,6 +29,8 @@ pub enum Function { StakingTransfer, SessionSetKey, TimestampSet, + GovernancePropose, + GovernanceApprove, } impl Function { @@ -40,6 +42,8 @@ impl Function { x if x == Function::StakingTransfer as u8 => Some(Function::StakingTransfer), x if x == Function::SessionSetKey as u8 => Some(Function::SessionSetKey), x if x == Function::TimestampSet as u8 => Some(Function::TimestampSet), + x if x == Function::GovernancePropose as u8 => Some(Function::GovernancePropose), + x if x == Function::GovernanceApprove as u8 => Some(Function::GovernanceApprove), _ => None, } } @@ -69,6 +73,14 @@ impl Function { let t = params.read().unwrap(); timestamp::set(t); } + Function::GovernancePropose => { + let proposal = params.read().unwrap(); + governance::propose(transactor, &proposal); + } + Function::GovernanceApprove => { + let era_index = params.read().unwrap(); + governance::approve(transactor, era_index); + } } } } diff --git a/substrate/wasm-runtime/polkadot/src/support/mod.rs b/substrate/wasm-runtime/polkadot/src/support/mod.rs index 56ad3a355c..384909d019 100644 --- a/substrate/wasm-runtime/polkadot/src/support/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/support/mod.rs @@ -18,6 +18,7 @@ pub mod primitives; pub mod function; +pub mod proposal; pub mod environment; pub mod storable; diff --git a/substrate/wasm-runtime/polkadot/src/support/primitives.rs b/substrate/wasm-runtime/polkadot/src/support/primitives.rs index 3ab385d488..c59e7c5dcd 100644 --- a/substrate/wasm-runtime/polkadot/src/support/primitives.rs +++ b/substrate/wasm-runtime/polkadot/src/support/primitives.rs @@ -28,15 +28,25 @@ use std::fmt; /// The Ed25519 pubkey that identifies an account. pub type AccountID = [u8; 32]; + +/// Virtual account ID that represents the idea of a dispatch/statement being signed by everybody +/// (who matters). Essentially this means that a majority of validators have decided it is +/// "correct". +pub const EVERYBODY: AccountID = [255u8; 32]; + /// The Ed25519 pub key of an session that belongs to an authority. This is used as what the /// external environment/consensus algorithm calls an "authority". pub type SessionKey = AccountID; + /// Indentifier for a chain. pub type ChainID = u64; + /// Index of a block in the chain. pub type BlockNumber = u64; + /// Index of a transaction. pub type TxOrder = u64; + /// A hash of some data. pub type Hash = [u8; 32]; @@ -76,7 +86,7 @@ impl Slicable for Header { }) } - fn set_as_slice bool>(_fill_slice: F) -> Option { + fn set_as_slice bool>(_fill_slice: &F) -> Option { unimplemented!(); } @@ -122,7 +132,7 @@ impl Slicable for Transaction { }) } - fn set_as_slice bool>(_fill_slice: F) -> Option { + fn set_as_slice bool>(_fill_slice: &F) -> Option { unimplemented!(); } @@ -200,7 +210,7 @@ impl Slicable for UncheckedTransaction { }) } - fn set_as_slice bool>(_fill_slice: F) -> Option { + fn set_as_slice bool>(_fill_slice: &F) -> Option { unimplemented!(); } @@ -237,7 +247,7 @@ impl Slicable for Block { }) } - fn set_as_slice bool>(_fill_slice: F) -> Option { + fn set_as_slice bool>(_fill_slice: &F) -> Option { unimplemented!(); } @@ -271,7 +281,7 @@ impl Slicable for Vec { Some(r) } - fn set_as_slice bool>(_fill_slice: F) -> Option { + fn set_as_slice bool>(_fill_slice: &F) -> Option { unimplemented!(); } diff --git a/substrate/wasm-runtime/polkadot/src/support/proposal.rs b/substrate/wasm-runtime/polkadot/src/support/proposal.rs new file mode 100644 index 0000000000..bffd7aa76c --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/support/proposal.rs @@ -0,0 +1,108 @@ +// 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 . + +//! Proposal: This describes a combination of a function ID and data that can be used to call into +//! an internal function. + +use runtime_support::size_of; +use slicable::Slicable; +use joiner::Joiner; +use streamreader::StreamReader; +use runtime::staking; + +/// Internal functions that can be dispatched to. +#[cfg_attr(test, derive(PartialEq, Debug))] +#[derive(Clone, Copy)] +pub enum InternalFunction { + SystemSetCode, + StakingSetSessionsPerEra, +} + +impl InternalFunction { + /// Derive `Some` value from a `u8`, or `None` if it's invalid. + pub fn from_u8(value: u8) -> Option { + match value { + x if x == InternalFunction::SystemSetCode as u8 => Some(InternalFunction::SystemSetCode), + x if x == InternalFunction::StakingSetSessionsPerEra as u8 => Some(InternalFunction::StakingSetSessionsPerEra), + _ => None, + } + } +} + +/// An internal function. +#[cfg_attr(test, derive(PartialEq, Debug))] +pub struct Proposal { + /// The priviledged function to call. + pub function: InternalFunction, + /// The serialised data to call it with. + pub input_data: Vec, +} + +impl Slicable for Proposal { + fn set_as_slice bool>(fill_slice: &F) -> Option { + Some(Proposal { + function: InternalFunction::from_u8(Slicable::set_as_slice(fill_slice)?)?, + input_data: Slicable::set_as_slice(&|s, o| fill_slice(s, o + 1))?, + }) + } + + fn to_vec(&self) -> Vec { + Vec::new() + .join(&(self.function as u8)) + .join(&self.input_data) + } + + fn size_of(data: &[u8]) -> Option { + let first_part = size_of::(); + let second_part = >::size_of(&data[first_part..])?; + Some(first_part + second_part) + } +} + +impl Proposal { + pub fn enact(&self) { + let mut params = StreamReader::new(&self.input_data); + match self.function { + InternalFunction::SystemSetCode => { + let code = params.read().unwrap(); + staking::set_sessions_per_era(code); + } + InternalFunction::StakingSetSessionsPerEra => { + let value = params.read().unwrap(); + staking::set_sessions_per_era(value); + } + } + } +} + +#[cfg(test)] +mod test { + use super::*; + use statichex::StaticHexInto; + + #[test] + fn slicing_should_work() { + let p = Proposal { + function: InternalFunction::SystemSetCode, + input_data: b"Hello world".to_vec(), + }; + let v = p.to_vec(); + assert_eq!(v, "000b00000048656c6c6f20776f726c64".convert::>()); + + let o = Proposal::from_slice(&v).unwrap(); + assert_eq!(p, o); + } +} diff --git a/substrate/wasm-runtime/polkadot/src/support/statichex.rs b/substrate/wasm-runtime/polkadot/src/support/statichex.rs index 152ceadc0b..b750a8ca10 100644 --- a/substrate/wasm-runtime/polkadot/src/support/statichex.rs +++ b/substrate/wasm-runtime/polkadot/src/support/statichex.rs @@ -36,7 +36,16 @@ macro_rules! impl_sizes { )* } } -impl_sizes!(1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128); +impl StaticHexConversion for Vec { + fn from_static_hex(hex: &'static str) -> Self { + FromHex::from_hex(hex).unwrap() + } +} + +impl_sizes!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 451, 42, 43, 44, 45, 46, 47, 48, + 56, 64, 80, 96, 112, 128); /// Trait to allow converting from itself (only implemented for a static str) into some useful /// type (which must implement `StaticHexConversion`). diff --git a/substrate/wasm-runtime/polkadot/src/support/storable.rs b/substrate/wasm-runtime/polkadot/src/support/storable.rs index 3caf3ed19b..5cfa154937 100644 --- a/substrate/wasm-runtime/polkadot/src/support/storable.rs +++ b/substrate/wasm-runtime/polkadot/src/support/storable.rs @@ -17,28 +17,37 @@ //! Stuff to do with the runtime's storage. use slicable::Slicable; -use endiansensitive::EndianSensitive; use keyedvec::KeyedVec; use runtime_support::{self, twox_128, Vec}; /// Trait for a value which may be stored in the storage DB. pub trait Storable { /// Lookup the value in storage and deserialise, giving a default value if not found. - fn lookup_default(key: &[u8]) -> Self where Self: Sized + Default { Self::lookup(key).unwrap_or_else(Default::default) } + fn lookup_default(key: &[u8]) -> Self where Self: Sized + Default { + Self::lookup(key).unwrap_or_else(Default::default) + } + /// Lookup `Some` value in storage and deserialise; `None` if it's not there. - fn lookup(_key: &[u8]) -> Option where Self: Sized { unimplemented!() } + fn lookup(_key: &[u8]) -> Option where Self: Sized { + unimplemented!() + } + /// Place the value in storage under `key`. fn store(&self, key: &[u8]); } -// TODO: consider using blake256 to avoid possible eclipse attack. +// TODO: consider using blake256 to avoid possible preimage attack. /// Remove `key` from storage. -pub fn kill(key: &[u8]) { runtime_support::set_storage(&twox_128(key)[..], b""); } +pub fn kill(key: &[u8]) { + runtime_support::set_storage(&twox_128(key)[..], b""); +} -impl Storable for T { +impl Storable for T { fn lookup(key: &[u8]) -> Option { - Slicable::set_as_slice(|out| runtime_support::read_storage(&twox_128(key)[..], out) == out.len()) + Slicable::set_as_slice(&|out, offset| + runtime_support::read_storage(&twox_128(key)[..], out, offset) == out.len() + ) } fn store(&self, key: &[u8]) { self.as_slice_then(|slice| runtime_support::set_storage(&twox_128(key)[..], slice)); diff --git a/substrate/wasm-runtime/support/src/lib.rs b/substrate/wasm-runtime/support/src/lib.rs index b65b574351..5e689746c8 100644 --- a/substrate/wasm-runtime/support/src/lib.rs +++ b/substrate/wasm-runtime/support/src/lib.rs @@ -27,7 +27,7 @@ extern "C" { fn ext_print_num(value: u64); fn ext_set_storage(key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32); fn ext_get_allocated_storage(key_data: *const u8, key_len: u32, written_out: *mut u32) -> *mut u8; - fn ext_get_storage_into(key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32) -> u32; + fn ext_get_storage_into(key_data: *const u8, key_len: u32, value_data: *mut u8, value_len: u32, value_offset: u32) -> u32; fn ext_chain_id() -> u64; fn ext_blake2_256(data: *const u8, len: u32, out: *mut u8); fn ext_twox_128(data: *const u8, len: u32, out: *mut u8); @@ -52,9 +52,9 @@ pub fn set_storage(key: &[u8], value: &[u8]) { } } -pub fn read_storage(key: &[u8], value_out: &mut [u8]) -> usize { +pub fn read_storage(key: &[u8], value_offset: usize, value_out: &mut [u8]) -> usize { unsafe { - ext_get_storage_into(&key[0], key.len() as u32, &mut value_out[0], value_out.len() as u32) as usize + ext_get_storage_into(&key[0], key.len() as u32, &mut value_out[0], value_out.len() as u32, value_offset as u32) as usize } } From b615df2be6cb56ee9a9a0bddd9f51eae4b7147e9 Mon Sep 17 00:00:00 2001 From: Gav Date: Sun, 21 Jan 2018 22:35:51 +0100 Subject: [PATCH 078/112] fix comment --- substrate/wasm-runtime/polkadot/src/runtime/governance.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs index 783522ffdf..f6c41ff805 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs @@ -67,8 +67,7 @@ pub fn approvals_required() -> u32 { /// Current era is ending; we should finish up any proposals. pub fn end_of_an_era() { - // TODO: tally up votes for the current proposal, if any. enact if there are sufficient - // approvals. + // tally up votes for the current proposal, if any. enact if there are sufficient approvals. if let Some(proposal) = Proposal::lookup(b"gov:pro") { let enact = approval_count() >= approvals_required(); From 3788e47ce9e7ce49e41a41dbf0c06b4d89eac36b Mon Sep 17 00:00:00 2001 From: Gav Date: Sun, 21 Jan 2018 22:57:50 +0100 Subject: [PATCH 079/112] Fix some semantics. Add Storable::take. --- .../polkadot/src/runtime/governance.rs | 42 +++++++++---------- .../polkadot/src/support/proposal.rs | 12 ++++-- .../polkadot/src/support/storable.rs | 10 +++++ 3 files changed, 40 insertions(+), 24 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs index f6c41ff805..43a636f489 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs @@ -16,6 +16,13 @@ //! Governance system: Handles administration and dispatch of sensitive operations including //! setting new code, minting new tokens and changing parameters. +//! +//! For now this is limited to a simple qualified majority vote (whose parameter is retrieved from +//! storage) between validators. A single vote may be proposed per era, and at most one approval +//! vote may be cast by each validator. The tally is maintained +//! +//! +//! use runtime_support::Vec; use keyedvec::KeyedVec; @@ -34,27 +41,29 @@ pub fn propose(transactor: &AccountID, proposal: &Proposal) { approve(transactor, staking::current_era()); } -pub fn approve(transactor: &AccountID, era_index: BlockNumber) { +pub fn approve(validator: &AccountID, era_index: BlockNumber) { if era_index != staking::current_era() { panic!("approval vote applied on non-current era.") } if Proposal::lookup(b"gov:pro").is_none() { panic!("there must be a proposal in order to approve."); } - let key = transactor.to_keyed_vec(b"gov:app:"); + if session::validators().into_iter().position(|v| &v == validator).is_none() { + panic!("transactor must be a validator to approve."); + } + let key = validator.to_keyed_vec(b"gov:app:"); if bool::lookup(&key).is_some() { panic!("transactor may not approve a proposal twice in one era."); } true.store(&key); - (approval_count() + 1).store(b"gov:app"); +} + +pub fn set_approval_ppm_required(ppm: u32) { + ppm.store(b"gov:apr"); } // INSPECTION API -pub fn approval_count() -> u32 { - Storable::lookup_default(b"gov:app") -} - pub fn approval_ppm_required() -> u32 { Storable::lookup(b"gov:apr").unwrap_or(1000) } @@ -69,12 +78,11 @@ pub fn approvals_required() -> u32 { pub fn end_of_an_era() { // tally up votes for the current proposal, if any. enact if there are sufficient approvals. if let Some(proposal) = Proposal::lookup(b"gov:pro") { - let enact = approval_count() >= approvals_required(); - - // clear proposal - reset_proposal(); - - if enact { + kill(b"gov:pro"); + let approved: u32 = session::validators().into_iter() + .map(|v| bool::take(&v.to_keyed_vec(b"gov:app:")).map(|_| 1).unwrap_or(0)) + .sum(); + if approved >= approvals_required() { proposal.enact(); } } @@ -82,14 +90,6 @@ pub fn end_of_an_era() { // PRIVATE API -fn reset_proposal() { - session::validators().into_iter().for_each(|v| { - kill(&v.to_keyed_vec(b"gov:app:")); - }); - kill(b"gov:pro"); - kill(b"gov:app"); -} - #[cfg(test)] mod tests { // TODO diff --git a/substrate/wasm-runtime/polkadot/src/support/proposal.rs b/substrate/wasm-runtime/polkadot/src/support/proposal.rs index bffd7aa76c..963a01b749 100644 --- a/substrate/wasm-runtime/polkadot/src/support/proposal.rs +++ b/substrate/wasm-runtime/polkadot/src/support/proposal.rs @@ -21,7 +21,7 @@ use runtime_support::size_of; use slicable::Slicable; use joiner::Joiner; use streamreader::StreamReader; -use runtime::staking; +use runtime::{system, governance, staking}; /// Internal functions that can be dispatched to. #[cfg_attr(test, derive(PartialEq, Debug))] @@ -29,6 +29,7 @@ use runtime::staking; pub enum InternalFunction { SystemSetCode, StakingSetSessionsPerEra, + GovernanceSetApprovalPpmRequired, } impl InternalFunction { @@ -37,6 +38,7 @@ impl InternalFunction { match value { x if x == InternalFunction::SystemSetCode as u8 => Some(InternalFunction::SystemSetCode), x if x == InternalFunction::StakingSetSessionsPerEra as u8 => Some(InternalFunction::StakingSetSessionsPerEra), + x if x == InternalFunction::GovernanceSetApprovalPpmRequired as u8 => Some(InternalFunction::GovernanceSetApprovalPpmRequired), _ => None, } } @@ -77,13 +79,17 @@ impl Proposal { let mut params = StreamReader::new(&self.input_data); match self.function { InternalFunction::SystemSetCode => { - let code = params.read().unwrap(); - staking::set_sessions_per_era(code); + let code: Vec = params.read().unwrap(); + system::set_code(&code); } InternalFunction::StakingSetSessionsPerEra => { let value = params.read().unwrap(); staking::set_sessions_per_era(value); } + InternalFunction::GovernanceSetApprovalPpmRequired => { + let value = params.read().unwrap(); + governance::set_approval_ppm_required(value); + } } } } diff --git a/substrate/wasm-runtime/polkadot/src/support/storable.rs b/substrate/wasm-runtime/polkadot/src/support/storable.rs index 5cfa154937..61d9f080d9 100644 --- a/substrate/wasm-runtime/polkadot/src/support/storable.rs +++ b/substrate/wasm-runtime/polkadot/src/support/storable.rs @@ -32,6 +32,16 @@ pub trait Storable { unimplemented!() } + /// Retrives and returns the serialised value of a key from storage, removing it immediately. + fn take(key: &[u8]) -> Option where Self: Sized { + if let Some(value) = Self::lookup(key) { + kill(key); + Some(value) + } else { + None + } + } + /// Place the value in storage under `key`. fn store(&self, key: &[u8]); } From cf7bd8a6cd191f26fe66590aef0e295f4a8aadf0 Mon Sep 17 00:00:00 2001 From: Gav Date: Sun, 21 Jan 2018 23:00:36 +0100 Subject: [PATCH 080/112] Docs. --- substrate/wasm-runtime/polkadot/src/runtime/governance.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs index 43a636f489..d7d45fb0d0 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs @@ -19,10 +19,11 @@ //! //! For now this is limited to a simple qualified majority vote (whose parameter is retrieved from //! storage) between validators. A single vote may be proposed per era, and at most one approval -//! vote may be cast by each validator. The tally is maintained -//! -//! +//! vote may be cast by each validator. The tally is maintained through a simple tag in storage for +//! each validator that has approved. //! +//! At the end of the era, all validators approvals are tallied and if there are sufficient to pass +//! the proposal then it is enacted. All items in storage concerning the proposal are reset. use runtime_support::Vec; use keyedvec::KeyedVec; From baa0cfcc9af48777ee13d0b8686b4a864fd5f219 Mon Sep 17 00:00:00 2001 From: Gav Date: Mon, 22 Jan 2018 20:22:38 +0100 Subject: [PATCH 081/112] Tests and docs, plus some fixes. --- substrate/native-runtime/support/src/lib.rs | 16 + .../polkadot/src/codec/slicable.rs | 13 + .../polkadot/src/runtime/governance.rs | 284 +++++++++++++++++- .../polkadot/src/runtime/session.rs | 5 + .../polkadot/src/support/storable.rs | 88 +++++- 5 files changed, 395 insertions(+), 11 deletions(-) diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index 7adf9a904b..47755c3f75 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -151,4 +151,20 @@ mod tests { false })); } + + #[test] + fn read_storage_works() { + let mut t = TestExternalities { storage: map![ + b":test".to_vec() => b"\x0b\0\0\0Hello world".to_vec() + ], }; + + with_externalities(&mut t, || { + let mut v = [0u8; 4]; + assert!(read_storage(b":test", &mut v[..], 0) >= 4); + assert_eq!(v, [11u8, 0, 0, 0]); + let mut w = [0u8; 11]; + assert!(read_storage(b":test", &mut w[..], 4) >= 11); + assert_eq!(&w, b"Hello world"); + }); + } } diff --git a/substrate/wasm-runtime/polkadot/src/codec/slicable.rs b/substrate/wasm-runtime/polkadot/src/codec/slicable.rs index 1c783e39df..1ccf2ce32d 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/slicable.rs +++ b/substrate/wasm-runtime/polkadot/src/codec/slicable.rs @@ -96,3 +96,16 @@ impl Slicable for Vec { u32::from_slice(&data[0..4]).map(|i| (i + 4) as usize) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn vec_is_slicable() { + let v = b"Hello world".to_vec(); + v.as_slice_then(|ref slice| + assert_eq!(slice, &b"\x0b\0\0\0Hello world") + ); + } +} diff --git a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs index d7d45fb0d0..e4665d3838 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs @@ -34,14 +34,19 @@ use runtime::{staking, system, session}; // TRANSACTION API -pub fn propose(transactor: &AccountID, proposal: &Proposal) { +/// Propose a sensitive action to be taken. Any action that is enactable by `Proposal` is valid. +/// Proposal is by the `transactor` and will automatically count as an approval. Transactor must +/// be a current validator. It is illegal to propose when there is already a proposal in effect. +pub fn propose(validator: &AccountID, proposal: &Proposal) { if Proposal::lookup(b"gov:pro").is_some() { panic!("there may only be one proposal per era."); } proposal.store(b"gov:pro"); - approve(transactor, staking::current_era()); + approve(validator, staking::current_era()); } +/// Approve the current era's proposal. Transactor must be a validator. This may not be done more +/// than once for any validator in an era. pub fn approve(validator: &AccountID, era_index: BlockNumber) { if era_index != staking::current_era() { panic!("approval vote applied on non-current era.") @@ -59,18 +64,25 @@ pub fn approve(validator: &AccountID, era_index: BlockNumber) { true.store(&key); } +/// Set the proportion of validators that must approve for a proposal to be enacted at the end of +/// its era. The value, `ppm`, is measured as a fraction of 1000 rounded down to the nearest whole +/// validator. `1000` would require the approval of all validators; `667` would require two-thirds +/// (or there abouts) of validators. pub fn set_approval_ppm_required(ppm: u32) { ppm.store(b"gov:apr"); } // INSPECTION API +/// The proportion of validators required for a propsal to be approved measured as the number out +/// of 1000. pub fn approval_ppm_required() -> u32 { Storable::lookup(b"gov:apr").unwrap_or(1000) } +/// The number of concrete validator approvals required for a proposal to pass. pub fn approvals_required() -> u32 { - approval_ppm_required() * staking::validator_count() as u32 / 1000 + approval_ppm_required() * session::validator_count() as u32 / 1000 } // PUBLIC API @@ -80,18 +92,270 @@ pub fn end_of_an_era() { // tally up votes for the current proposal, if any. enact if there are sufficient approvals. if let Some(proposal) = Proposal::lookup(b"gov:pro") { kill(b"gov:pro"); - let approved: u32 = session::validators().into_iter() - .map(|v| bool::take(&v.to_keyed_vec(b"gov:app:")).map(|_| 1).unwrap_or(0)) - .sum(); - if approved >= approvals_required() { + let approvals_required = approvals_required(); + let approved = session::validators().into_iter() + .filter_map(|v| bool::take(&v.to_keyed_vec(b"gov:app:"))) + .take(approvals_required as usize) + .count() as u32; + if approved == approvals_required { proposal.enact(); } } } -// PRIVATE API - #[cfg(test)] mod tests { - // TODO + use super::*; + use runtime_support::{with_externalities, twox_128}; + use keyedvec::KeyedVec; + use joiner::Joiner; + use testing::{one, two, TestExternalities}; + use primitives::AccountID; + use proposal::InternalFunction; + use runtime::{staking, session}; + use environment::with_env; + + fn new_test_ext() -> TestExternalities { + let one = one(); + let two = two(); + let three = [3u8; 32]; + + TestExternalities { storage: map![ + twox_128(b"gov:apr").to_vec() => vec![].join(&667u32), + twox_128(b"ses:len").to_vec() => vec![].join(&1u64), + twox_128(b"ses:val:len").to_vec() => vec![].join(&3u32), + twox_128(&0u32.to_keyed_vec(b"ses:val:")).to_vec() => one.to_vec(), + twox_128(&1u32.to_keyed_vec(b"ses:val:")).to_vec() => two.to_vec(), + twox_128(&2u32.to_keyed_vec(b"ses:val:")).to_vec() => three.to_vec(), + twox_128(b"sta:wil:len").to_vec() => vec![].join(&3u32), + twox_128(&0u32.to_keyed_vec(b"sta:wil:")).to_vec() => one.to_vec(), + twox_128(&1u32.to_keyed_vec(b"sta:wil:")).to_vec() => two.to_vec(), + twox_128(&2u32.to_keyed_vec(b"sta:wil:")).to_vec() => three.to_vec(), + twox_128(b"sta:spe").to_vec() => vec![].join(&1u64), + twox_128(b"sta:vac").to_vec() => vec![].join(&3u64), + twox_128(b"sta:era").to_vec() => vec![].join(&1u64) + ], } + } + + #[test] + fn majority_voting_should_work() { + let one = one(); + let two = two(); + let three = [3u8; 32]; + let mut t = new_test_ext(); + + with_externalities(&mut t, || { + assert_eq!(staking::era_length(), 1u64); + assert_eq!(staking::current_era(), 1u64); + assert_eq!(session::validator_count(), 3usize); + assert_eq!(session::validators(), vec![one.clone(), two.clone(), three.clone()]); + assert!(!session::validators().into_iter().position(|v| &v == &one).is_none()); + + // Block 1: Make proposal. Approve it. Era length changes. + with_env(|e| e.block_number = 1); + propose(&one, &Proposal { + function: InternalFunction::StakingSetSessionsPerEra, + input_data: vec![].join(&2u64), + }); + approve(&two, 1); + staking::check_new_era(); + assert_eq!(staking::era_length(), 2); + }); + } + + #[test] + fn majority_voting_should_work_after_unsuccessful_previous() { + let one = one(); + let two = two(); + let three = [3u8; 32]; + let mut t = new_test_ext(); + + with_externalities(&mut t, || { + assert_eq!(staking::era_length(), 1u64); + assert_eq!(staking::current_era(), 1u64); + assert_eq!(session::validator_count(), 3usize); + assert_eq!(session::validators(), vec![one.clone(), two.clone(), three.clone()]); + assert!(!session::validators().into_iter().position(|v| &v == &one).is_none()); + + // Block 1: Make proposal. Fail it. + with_env(|e| e.block_number = 1); + propose(&one, &Proposal { + function: InternalFunction::StakingSetSessionsPerEra, + input_data: vec![].join(&2u64), + }); + staking::check_new_era(); + assert_eq!(staking::era_length(), 1); + + // Block 2: Make proposal. Approve it. It should change era length. + with_env(|e| e.block_number = 2); + propose(&one, &Proposal { + function: InternalFunction::StakingSetSessionsPerEra, + input_data: vec![].join(&2u64), + }); + approve(&two, 2); + staking::check_new_era(); + assert_eq!(staking::era_length(), 2); + }); + } + + #[test] + fn minority_voting_should_not_succeed() { + let one = one(); + let two = two(); + let three = [3u8; 32]; + let mut t = new_test_ext(); + + with_externalities(&mut t, || { + assert_eq!(staking::era_length(), 1u64); + assert_eq!(staking::current_era(), 1u64); + assert_eq!(session::validator_count(), 3usize); + assert_eq!(session::validators(), vec![one.clone(), two.clone(), three.clone()]); + assert!(!session::validators().into_iter().position(|v| &v == &one).is_none()); + + // Block 1: Make proposal. Will have only 1 vote. No change. + with_env(|e| e.block_number = 1); + propose(&one, &Proposal { + function: InternalFunction::StakingSetSessionsPerEra, + input_data: vec![].join(&2u64), + }); + staking::check_new_era(); + assert_eq!(staking::era_length(), 1); + }); + } + + #[test] + #[should_panic] + fn old_voting_should_be_illegal() { + let one = one(); + let two = two(); + let three = [3u8; 32]; + let mut t = new_test_ext(); + + with_externalities(&mut t, || { + assert_eq!(staking::era_length(), 1u64); + assert_eq!(staking::current_era(), 1u64); + assert_eq!(session::validator_count(), 3usize); + assert_eq!(session::validators(), vec![one.clone(), two.clone(), three.clone()]); + assert!(!session::validators().into_iter().position(|v| &v == &one).is_none()); + + // Block 1: Make proposal. Will have only 1 vote. No change. + with_env(|e| e.block_number = 1); + propose(&one, &Proposal { + function: InternalFunction::StakingSetSessionsPerEra, + input_data: vec![].join(&2u64), + }); + approve(&two, 0); + staking::check_new_era(); + assert_eq!(staking::era_length(), 1); + }); + } + + #[test] + #[should_panic] + fn double_voting_should_be_illegal() { + let one = one(); + let two = two(); + let three = [3u8; 32]; + let mut t = new_test_ext(); + + with_externalities(&mut t, || { + assert_eq!(staking::era_length(), 1u64); + assert_eq!(staking::current_era(), 1u64); + assert_eq!(session::validator_count(), 3usize); + assert_eq!(session::validators(), vec![one.clone(), two.clone(), three.clone()]); + assert!(!session::validators().into_iter().position(|v| &v == &one).is_none()); + + // Block 1: Make proposal. Will have only 1 vote. No change. + with_env(|e| e.block_number = 1); + propose(&one, &Proposal { + function: InternalFunction::StakingSetSessionsPerEra, + input_data: vec![].join(&2u64), + }); + approve(&two, 1); + approve(&two, 1); + staking::check_new_era(); + assert_eq!(staking::era_length(), 1); + }); + } + + #[test] + #[should_panic] + fn over_proposing_should_be_illegal() { + let one = one(); + let two = two(); + let three = [3u8; 32]; + let mut t = new_test_ext(); + + with_externalities(&mut t, || { + assert_eq!(staking::era_length(), 1u64); + assert_eq!(staking::current_era(), 1u64); + assert_eq!(session::validator_count(), 3usize); + assert_eq!(session::validators(), vec![one.clone(), two.clone(), three.clone()]); + assert!(!session::validators().into_iter().position(|v| &v == &one).is_none()); + + // Block 1: Make proposal. Will have only 1 vote. No change. + with_env(|e| e.block_number = 1); + propose(&one, &Proposal { + function: InternalFunction::StakingSetSessionsPerEra, + input_data: vec![].join(&2u64), + }); + propose(&two, &Proposal { + function: InternalFunction::StakingSetSessionsPerEra, + input_data: vec![].join(&2u64), + }); + staking::check_new_era(); + assert_eq!(staking::era_length(), 1); + }); + } + + #[test] + #[should_panic] + fn approving_without_proposal_should_be_illegal() { + let one = one(); + let two = two(); + let three = [3u8; 32]; + let mut t = new_test_ext(); + + with_externalities(&mut t, || { + assert_eq!(staking::era_length(), 1u64); + assert_eq!(staking::current_era(), 1u64); + assert_eq!(session::validator_count(), 3usize); + assert_eq!(session::validators(), vec![one.clone(), two.clone(), three.clone()]); + assert!(!session::validators().into_iter().position(|v| &v == &one).is_none()); + + // Block 1: Make proposal. Will have only 1 vote. No change. + with_env(|e| e.block_number = 1); + approve(&two, 1); + staking::check_new_era(); + assert_eq!(staking::era_length(), 1); + }); + } + + #[test] + #[should_panic] + fn non_validator_approving_should_be_illegal() { + let one = one(); + let two = two(); + let three = [3u8; 32]; + let four = [4u8; 32]; + let mut t = new_test_ext(); + + with_externalities(&mut t, || { + assert_eq!(staking::era_length(), 1u64); + assert_eq!(staking::current_era(), 1u64); + assert_eq!(session::validator_count(), 3usize); + assert_eq!(session::validators(), vec![one.clone(), two.clone(), three.clone()]); + assert!(!session::validators().into_iter().position(|v| &v == &one).is_none()); + + // Block 1: Make proposal. Will have only 1 vote. No change. + with_env(|e| e.block_number = 1); + propose(&one, &Proposal { + function: InternalFunction::StakingSetSessionsPerEra, + input_data: vec![].join(&2u64), + }); + approve(&four, 1); + staking::check_new_era(); + assert_eq!(staking::era_length(), 1); + }); + } } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs index 907b3e16b1..2034ff3168 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -59,6 +59,11 @@ pub fn length() -> BlockNumber { Storable::lookup_default(b"ses:len") } +/// The number of validators currently. +pub fn validator_count() -> usize { + ValidatorStorageVec::count() as usize +} + /// The current era index. pub fn current_index() -> BlockNumber { Storable::lookup_default(b"ses:ind") diff --git a/substrate/wasm-runtime/polkadot/src/support/storable.rs b/substrate/wasm-runtime/polkadot/src/support/storable.rs index 61d9f080d9..719415b8e8 100644 --- a/substrate/wasm-runtime/polkadot/src/support/storable.rs +++ b/substrate/wasm-runtime/polkadot/src/support/storable.rs @@ -56,7 +56,7 @@ pub fn kill(key: &[u8]) { impl Storable for T { fn lookup(key: &[u8]) -> Option { Slicable::set_as_slice(&|out, offset| - runtime_support::read_storage(&twox_128(key)[..], out, offset) == out.len() + runtime_support::read_storage(&twox_128(key)[..], out, offset) >= out.len() ) } fn store(&self, key: &[u8]) { @@ -104,3 +104,89 @@ pub trait StorageVec { Storable::lookup_default(&b"len".to_keyed_vec(Self::PREFIX)) } } + +#[cfg(test)] +mod tests { + use super::*; + use std::collections::HashMap; + use runtime_support::with_externalities; + use testing::{TestExternalities, HexDisplay}; + use runtime_support::{storage, twox_128}; + + #[test] + fn integers_can_be_stored() { + let mut t = TestExternalities { storage: HashMap::new(), }; + with_externalities(&mut t, || { + let x = 69u32; + x.store(b":test"); + let y = u32::lookup(b":test").unwrap(); + assert_eq!(x, y); + }); + with_externalities(&mut t, || { + let x = 69426942i64; + x.store(b":test"); + let y = i64::lookup(b":test").unwrap(); + assert_eq!(x, y); + }); + } + + #[test] + fn bools_can_be_stored() { + let mut t = TestExternalities { storage: HashMap::new(), }; + with_externalities(&mut t, || { + let x = true; + x.store(b":test"); + let y = bool::lookup(b":test").unwrap(); + assert_eq!(x, y); + }); + + with_externalities(&mut t, || { + let x = false; + x.store(b":test"); + let y = bool::lookup(b":test").unwrap(); + assert_eq!(x, y); + }); + } + + #[test] + fn vecs_can_be_retrieved() { + let mut t = TestExternalities { storage: HashMap::new(), }; + with_externalities(&mut t, || { + runtime_support::set_storage(&twox_128(b":test"), b"\x0b\0\0\0Hello world"); + let x = b"Hello world".to_vec(); + println!("Hex: {}", HexDisplay::from(&storage(&twox_128(b":test")))); + let y = >::lookup(b":test").unwrap(); + assert_eq!(x, y); + + }); + } + + #[test] + fn vecs_can_be_stored() { + let mut t = TestExternalities { storage: HashMap::new(), }; + let x = b"Hello world".to_vec(); + + with_externalities(&mut t, || { + x.store(b":test"); + }); + + println!("Ext is {:?}", t); + with_externalities(&mut t, || { + println!("Hex: {}", HexDisplay::from(&storage(&twox_128(b":test")))); + let y = >::lookup(b":test").unwrap(); + assert_eq!(x, y); + }); + } + + #[test] + fn proposals_can_be_stored() { + use proposal::{Proposal, InternalFunction}; + let mut t = TestExternalities { storage: HashMap::new(), }; + with_externalities(&mut t, || { + let x = Proposal { function: InternalFunction::StakingSetSessionsPerEra, input_data: b"Hello world".to_vec() }; + x.store(b":test"); + let y = Proposal::lookup(b":test").unwrap(); + assert_eq!(x, y); + }); + } +} From 07b9425ef698d874f7d757d10be0747a5ae6144d Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 23 Jan 2018 11:29:35 +0100 Subject: [PATCH 082/112] add todo. --- substrate/wasm-runtime/polkadot/src/runtime/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/substrate/wasm-runtime/polkadot/src/runtime/mod.rs b/substrate/wasm-runtime/polkadot/src/runtime/mod.rs index 6af33d6a65..9befa9bd42 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/mod.rs @@ -30,3 +30,4 @@ pub mod session; pub mod governance; // TODO: polkadao +// TODO: parachains From 8e8ea203d56a38e5c96c275c6c2ca9ccc74f19da Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 23 Jan 2018 12:12:48 +0100 Subject: [PATCH 083/112] Fix Wasm build issues. --- .../polkadot/src/support/proposal.rs | 2 +- substrate/wasm-runtime/support/src/lib.rs | 2 +- .../release/runtime_polkadot.compact.wasm | Bin 37802 -> 38655 bytes .../release/runtime_polkadot.wasm | Bin 37859 -> 38712 bytes 4 files changed, 2 insertions(+), 2 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/support/proposal.rs b/substrate/wasm-runtime/polkadot/src/support/proposal.rs index 963a01b749..e34eb41a64 100644 --- a/substrate/wasm-runtime/polkadot/src/support/proposal.rs +++ b/substrate/wasm-runtime/polkadot/src/support/proposal.rs @@ -17,7 +17,7 @@ //! Proposal: This describes a combination of a function ID and data that can be used to call into //! an internal function. -use runtime_support::size_of; +use runtime_support::{size_of, Vec}; use slicable::Slicable; use joiner::Joiner; use streamreader::StreamReader; diff --git a/substrate/wasm-runtime/support/src/lib.rs b/substrate/wasm-runtime/support/src/lib.rs index 5e689746c8..4d96617a8a 100644 --- a/substrate/wasm-runtime/support/src/lib.rs +++ b/substrate/wasm-runtime/support/src/lib.rs @@ -52,7 +52,7 @@ pub fn set_storage(key: &[u8], value: &[u8]) { } } -pub fn read_storage(key: &[u8], value_offset: usize, value_out: &mut [u8]) -> usize { +pub fn read_storage(key: &[u8], value_out: &mut [u8], value_offset: usize) -> usize { unsafe { ext_get_storage_into(&key[0], key.len() as u32, &mut value_out[0], value_out.len() as u32, value_offset as u32) as usize } diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm index ddd9dc70e64e3b02e101f88ad65bd0a5af897e86..a0d3d7de1eb2d7ad43605e6f5b65d4917c25e48e 100644 GIT binary patch delta 13941 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 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm index 8d3d3fb1ee5ffba092f881fdbe5e5c3780f7d23b..509eb2bdbd2b6398e0709b42d7127b0131490615 100644 GIT binary patch delta 14181 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 I&TY>B2Pj101poj5 delta 13985 zcmd5@Ymgk(b?)xznVt8}Y9F&ZyR&n$YW4mghr)-KY38MG48 z3IZ6>3lZiKhX`Lm;W(}=DZ9`Q2b=7lO@(r85f$%;u!Y&ANQyXA?4;}@KavVg#jbqk z+zv?g8r4efB! z4y{Md8hhl|rheN_HTU0^Z{B`*_w>}heFyefshH55-gC

      >J&uC6hAGoclDC(K! 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 From 2e69b7c16616ed0e64821a57d52d5cb0988348c6 Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Tue, 23 Jan 2018 15:25:00 +0100 Subject: [PATCH 084/112] Add the missing internal functions. --- .../polkadot/src/runtime/session.rs | 50 +++++++++--------- .../polkadot/src/runtime/staking.rs | 31 +++++++---- .../polkadot/src/runtime/system.rs | 1 + .../polkadot/src/support/proposal.rs | 20 ++++++- .../release/runtime_polkadot.compact.wasm | Bin 38655 -> 38655 bytes .../release/runtime_polkadot.wasm | Bin 38712 -> 38712 bytes 6 files changed, 66 insertions(+), 36 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs index 2034ff3168..20b7fe1628 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -37,14 +37,15 @@ pub fn set_key(validator: &AccountID, key: &SessionKey) { // set new value for next session key.store(&validator.to_keyed_vec(b"ses:nxt:")); } +// PRIVILEGED API (available to proposals) -// PUBLIC API (available to other runtime modules) - -/// Get the current set of authorities. These are the session keys. -pub fn validators() -> Vec<AccountID> { - ValidatorStorageVec::items() +/// Set a new era length. Won't kick in until the next era change (at current length). +pub fn set_length(new: BlockNumber) { + new.store(b"ses:nln"); } +// INTERNAL API (available to other runtime modules) + /// Set the current set of validators. /// /// Called by staking::next_era() only. `next_session` should be called after this in order to @@ -54,6 +55,23 @@ pub fn set_validators(new: &[AccountID]) { consensus::set_authorities(new); } +/// Hook to be called after transaction processing. +pub fn check_rotate_session() { + // do this last, after the staking system has had chance to switch out the authorities for the + // new set. + // check block number and call next_session if necessary. + if (system::block_number() - last_length_change()) % length() == 0 { + rotate_session(); + } +} + +// Inspection API + +/// Get the current set of authorities. These are the session keys. +pub fn validators() -> Vec<AccountID> { + ValidatorStorageVec::items() +} + /// The number of blocks in each session. pub fn length() -> BlockNumber { Storable::lookup_default(b"ses:len") @@ -69,37 +87,17 @@ pub fn current_index() -> BlockNumber { Storable::lookup_default(b"ses:ind") } -/// Set the current era index. -pub fn set_current_index(new: BlockNumber) { - new.store(b"ses:ind"); -} - /// The block number at which the era length last changed. pub fn last_length_change() -> BlockNumber { Storable::lookup_default(b"ses:llc") } -/// Set a new era length. Won't kick in until the next era change (at current length). -pub fn set_length(new: BlockNumber) { - new.store(b"ses:nln"); -} - -/// Hook to be called after transaction processing. -pub fn check_rotate_session() { - // do this last, after the staking system has had chance to switch out the authorities for the - // new set. - // check block number and call next_session if necessary. - if (system::block_number() - last_length_change()) % length() == 0 { - rotate_session(); - } -} - // PRIVATE (not available for use externally) /// Move onto next session: register the new authority set. fn rotate_session() { // Increment current session index. - set_current_index(current_index() + 1); + (current_index() + 1).store(b"ses:ind"); // Enact era length change. if let Some(next_len) = u64::lookup(b"ses:nln") { diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index 96843290a2..ca81a17764 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -81,12 +81,33 @@ pub fn unstake(transactor: &AccountID) { (current_era() + bonding_duration()).store(&transactor.to_keyed_vec(b"sta:bon:")); } -// PUBLIC API +// PRIVILEDGED API +/// Set the number of sessions in an era. pub fn set_sessions_per_era(new: BlockNumber) { new.store(b"sta:nse"); } +/// The length of the bonding duration in eras. +pub fn set_bonding_duration(new: BlockNumber) { + new.store(b"sta:loc"); +} + +/// The length of a staking era in sessions. +pub fn set_validator_count(new: usize) { + (new as u32).store(b"sta:vac"); +} + +// INTERNAL API + +/// Hook to be called after to transaction processing. +pub fn check_new_era() { + // check block number and call new_era if necessary. + if (system::block_number() - last_era_length_change()) % era_length() == 0 { + new_era(); + } +} + // INSPECTION API /// The length of the bonding duration in eras. @@ -129,14 +150,6 @@ pub fn bondage(who: &AccountID) -> Bondage { Storable::lookup_default(&who.to_keyed_vec(b"sta:bon:")) } -/// Hook to be called after to transaction processing. -pub fn check_new_era() { - // check block number and call new_era if necessary. - if (system::block_number() - last_era_length_change()) % era_length() == 0 { - new_era(); - } -} - // PRIVATE /// The era has changed - enact new staking set. diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 5ffa03ed81..e59876c426 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -42,6 +42,7 @@ pub fn deposit_log(log: &[u8]) { }); } +/// Actually execute all transitioning for `block`. pub fn execute_block(mut block: Block) { // populate environment from header. with_env(|e| { diff --git a/substrate/wasm-runtime/polkadot/src/support/proposal.rs b/substrate/wasm-runtime/polkadot/src/support/proposal.rs index e34eb41a64..8b45bc3859 100644 --- a/substrate/wasm-runtime/polkadot/src/support/proposal.rs +++ b/substrate/wasm-runtime/polkadot/src/support/proposal.rs @@ -21,7 +21,7 @@ use runtime_support::{size_of, Vec}; use slicable::Slicable; use joiner::Joiner; use streamreader::StreamReader; -use runtime::{system, governance, staking}; +use runtime::{system, governance, staking, session}; /// Internal functions that can be dispatched to. #[cfg_attr(test, derive(PartialEq, Debug))] @@ -29,7 +29,10 @@ use runtime::{system, governance, staking}; pub enum InternalFunction { SystemSetCode, StakingSetSessionsPerEra, + StakingSetBondingDuration, + StakingSetValidatorCount, GovernanceSetApprovalPpmRequired, + SessionSetLength, } impl InternalFunction { @@ -38,7 +41,10 @@ impl InternalFunction { match value { x if x == InternalFunction::SystemSetCode as u8 => Some(InternalFunction::SystemSetCode), x if x == InternalFunction::StakingSetSessionsPerEra as u8 => Some(InternalFunction::StakingSetSessionsPerEra), + x if x == InternalFunction::StakingSetBondingDuration as u8 => Some(InternalFunction::StakingSetBondingDuration), + x if x == InternalFunction::StakingSetValidatorCount as u8 => Some(InternalFunction::StakingSetValidatorCount), x if x == InternalFunction::GovernanceSetApprovalPpmRequired as u8 => Some(InternalFunction::GovernanceSetApprovalPpmRequired), + x if x == InternalFunction::SessionSetLength as u8 => Some(InternalFunction::SessionSetLength), _ => None, } } @@ -86,10 +92,22 @@ impl Proposal { let value = params.read().unwrap(); staking::set_sessions_per_era(value); } + InternalFunction::StakingSetBondingDuration => { + let value = params.read().unwrap(); + staking::set_bonding_duration(value); + } + InternalFunction::StakingSetValidatorCount => { + let value = params.read().unwrap(); + staking::set_validator_count(value); + } InternalFunction::GovernanceSetApprovalPpmRequired => { let value = params.read().unwrap(); governance::set_approval_ppm_required(value); } + InternalFunction::SessionSetLength => { + let value = params.read().unwrap(); + session::set_length(value); + } } } } diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm index a0d3d7de1eb2d7ad43605e6f5b65d4917c25e48e..ceac1b036e10c26c70f6da761b1bb0f56ecc60c7 100644 GIT binary patch delta 214 zcmeyrmg)amrVWdYBv^fU85I~D*{m3Nc$m0hEJp6h`bI93{~JwZWZOK|xK$EJN&8lF z1F7i|R!WRhCKvQ7POh%<nQULJ#lq&!%RTu+wb<mmD&EZ#s?!A-mjLBGCmZxBPxh<g z2CFV(oC6iJ1hYgY*Y){L&Yj{q*}jTxvv_|PD^OY96n~)BeN)^Sdp5I8UCXGImy^ff iIE9g$y*RblDkl}lnFHly=A|$=E`iD9Bu~COO$h*$M@NtV delta 216 zcmeyrmg)amrVWdYB$#}885I~DnXMRjc$m0hEJp6h`bI93{~JwZWZpd0xK$EJN&8lF z1F7i|R!WRLlM8wkCs$YbOt!DqVqtdY<(~YZT5NJ&74PN=)#-wabAa-mlMVWmC;L@# zgH@MJzF4I+c|x`K<lsIrAX{{DU7sK0lF4~fTqfIBv27Ob4`T%?%$wp5)VyzsJL8hg uY*W`VYUQNnF*r_P<Yq5UEw;+cOJQ)F1Lfr8Br`ZJfpYS4@+RM%rUU?UbV)S; diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm index 509eb2bdbd2b6398e0709b42d7127b0131490615..4a56fe2760cce554f731996b078824453bb2c1a5 100644 GIT binary patch delta 254 zcmdn7j%mj_rVSU3#94iL85I~D*{m3Nc$m0hEXK)+#;%ifji)lQZ9Z(=DhZ@KeXF^F z)X@klCB`X}s;9HDx$|;6zL_jgr8xOQz4c_fe)df@s)9^Q7$*x>DZqp#)o@L&t>R*u z0u$Akd|`^fWcz-$$$xvrndZQR!TKlFa87RQ69b7V)+93ZFiyT$>%7^%KZX^g|6;8x zw}QNYtU2=zHb<Z>Kt7XW&t{XUI~cX{a`G4)r!aD}7pE3m<)i{RbD*5eyc7nYYN$+3 J@?^2;N&wnFQfvSK delta 254 zcmdn7j%mj_rVSU3#F>0~85I~DnXMRjc$m0hEXK)+#;%ifji)j)Z$50?DhZ@KeXF^F z)X@klCB~jf)zjIS-Fdkk-%J*$Qk;CD-g>fKKl`Q{RY9gXjFSbc6ktM=YPcrXR&g=) zz(h4BUzj2=*}k7`^50%@rYSICu>MIkoRb^-#6Y5oHHl117$;w>b>3{>AHxdLf3en; zTR~nx)|`0<n<LN`AfL%`$!3$OI~cWcQu7!br!aD}7pE3mW#*+Y02M$uIXTG;j!U4N LyqvtrV$+oXxuH@| From 8ca5c09961a1e77cbd9e0b09b4868be13745a27c Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Tue, 23 Jan 2018 17:27:43 +0100 Subject: [PATCH 085/112] Initial (non-functional) code. - Kill Externalities Error type requirement. --- substrate/Cargo.lock | 2 ++ substrate/executor/Cargo.toml | 2 ++ substrate/executor/src/error.rs | 5 ++- substrate/executor/src/lib.rs | 5 +++ substrate/executor/src/native_executor.rs | 34 +++++++++++++++++++ substrate/executor/src/wasm_executor.rs | 5 ++- substrate/native-runtime/support/src/lib.rs | 10 +++--- substrate/state_machine/src/ext.rs | 8 ++--- substrate/state_machine/src/lib.rs | 25 +++++++++----- .../polkadot/src/support/testing.rs | 6 ++-- 10 files changed, 72 insertions(+), 30 deletions(-) create mode 100644 substrate/executor/src/native_executor.rs diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index a05893e615..1595bc0272 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -726,10 +726,12 @@ dependencies = [ "assert_matches 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "native-runtime 0.1.0", "parity-wasm 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)", "polkadot-primitives 0.1.0", "polkadot-serializer 0.1.0", "polkadot-state-machine 0.1.0", + "runtime-support 0.1.0", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/substrate/executor/Cargo.toml b/substrate/executor/Cargo.toml index 0401bd4c77..dbdef883cc 100644 --- a/substrate/executor/Cargo.toml +++ b/substrate/executor/Cargo.toml @@ -13,6 +13,8 @@ serde_derive = "1.0" parity-wasm = "0.15.0" byteorder = "1.1" rustc-hex = "1.0.0" +native-runtime = { path = "../native-runtime", version = "0.1" } +runtime-support = { path = "../native-runtime/support", version = "0.1" } [dev-dependencies] assert_matches = "1.1" diff --git a/substrate/executor/src/error.rs b/substrate/executor/src/error.rs index 4fd0ec0604..c1f9c2c711 100644 --- a/substrate/executor/src/error.rs +++ b/substrate/executor/src/error.rs @@ -17,7 +17,6 @@ //! Rust executor possible errors. use serializer; -use state_machine; error_chain! { foreign_links { @@ -38,9 +37,9 @@ error_chain! { } /// Externalities have failed. - Externalities(e: Box<state_machine::Error>) { + Externalities { description("externalities failure"), - display("Externalities error: {}", e), + display("Externalities error"), } /// Invalid index. diff --git a/substrate/executor/src/lib.rs b/substrate/executor/src/lib.rs index f1da582538..56c39e5b49 100644 --- a/substrate/executor/src/lib.rs +++ b/substrate/executor/src/lib.rs @@ -34,6 +34,8 @@ extern crate serde; extern crate parity_wasm; extern crate byteorder; extern crate rustc_hex; +extern crate native_runtime; +extern crate runtime_support; #[macro_use] extern crate error_chain; @@ -44,10 +46,13 @@ extern crate assert_matches; #[macro_use] mod wasm_utils; mod wasm_executor; +mod native_executor; pub mod error; /// Creates new RustExecutor for contracts. pub fn executor() -> wasm_executor::WasmExecutor { + // TODO: check what the code to execute is and use NativeExecutor if the wasm is compiled with + // matches. wasm_executor::WasmExecutor::default() } diff --git a/substrate/executor/src/native_executor.rs b/substrate/executor/src/native_executor.rs new file mode 100644 index 0000000000..5e588d559c --- /dev/null +++ b/substrate/executor/src/native_executor.rs @@ -0,0 +1,34 @@ +use primitives::contract::CallData; +use state_machine::{Externalities, CodeExecutor}; +use error::{Error, ErrorKind, Result}; +use native_runtime as runtime; +use runtime_support; + +struct NativeExecutor; + +impl CodeExecutor for NativeExecutor { + type Error = Error; + + fn call<E: Externalities>( + &self, + ext: &mut E, + code: &[u8], + method: &str, + data: &CallData, + ) -> Result<Vec<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. + let native_equivalent = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm"); + if code == &native_equivalent[..] { + runtime_support::with_externalities(ext, || match method { + // TODO: Panic handler that comes back with error. + "execute_block" => Ok(runtime::execute_block(data.0)), + "execute_transaction" => Ok(runtime::execute_transaction(data.0)), + _ => Err(ErrorKind::MethodNotFound(method.to_owned()).into()), + }) + } else { + // call into wasm. + unimplemented!() + } + } +} diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index d0bc908136..561e557ad9 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -241,15 +241,14 @@ mod tests { use super::*; use rustc_hex::FromHex; + use state_machine::ExternalitiesError; #[derive(Debug, Default)] struct TestExternalities { storage: HashMap<Vec<u8>, Vec<u8>>, } impl Externalities for TestExternalities { - type Error = Error; - - fn storage(&self, key: &[u8]) -> Result<&[u8]> { + fn storage(&self, key: &[u8]) -> ::std::result::Result<&[u8], ExternalitiesError> { Ok(self.storage.get(&key.to_vec()).map_or(&[] as &[u8], Vec::as_slice)) } diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index 47755c3f75..68914423b5 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -31,7 +31,7 @@ pub use std::boxed::Box; pub use std::slice; pub use std::mem::{size_of, transmute, swap, uninitialized}; -pub use polkadot_state_machine::Externalities; +pub use polkadot_state_machine::{Externalities, ExternalitiesError}; // TODO: use the real error, not NoError. @@ -42,7 +42,7 @@ impl fmt::Display for NoError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "") } } -environmental!(ext : Externalities<Error=NoError> + 'static); +environmental!(ext : Externalities + 'static); /// Get `key` from storage and return a `Vec`, empty if there's a problem. pub fn storage(key: &[u8]) -> Vec<u8> { @@ -93,7 +93,7 @@ pub fn ed25519_verify(sig: &[u8; 64], msg: &[u8], pubkey: &[u8; 32]) -> bool { /// Execute the given closure with global function available whose functionality routes into the /// externalities `ext`. Forwards the value that the closure returns. -pub fn with_externalities<R, F: FnOnce() -> R>(ext: &mut (Externalities<Error=NoError> + 'static), f: F) -> R { +pub fn with_externalities<R, F: FnOnce() -> R>(ext: &mut (Externalities + 'static), f: F) -> R { ext::using(ext, f) } @@ -112,9 +112,7 @@ mod tests { storage: HashMap<Vec<u8>, Vec<u8>>, } impl Externalities for TestExternalities { - type Error = NoError; - - fn storage(&self, key: &[u8]) -> Result<&[u8], NoError> { + fn storage(&self, key: &[u8]) -> Result<&[u8], ExternalitiesError> { Ok(self.storage.get(&key.to_vec()).map_or(&[] as &[u8], Vec::as_slice)) } diff --git a/substrate/state_machine/src/ext.rs b/substrate/state_machine/src/ext.rs index 1452558ccd..764c51de10 100644 --- a/substrate/state_machine/src/ext.rs +++ b/substrate/state_machine/src/ext.rs @@ -19,7 +19,7 @@ use std::{error, fmt}; use backend::Backend; -use {Externalities, OverlayedChanges}; +use {Externalities, ExternalitiesError, OverlayedChanges}; /// Errors that can occur when interacting with the externalities. #[derive(Debug, Copy, Clone)] @@ -61,12 +61,10 @@ pub struct Ext<'a, B: 'a> { impl<'a, B: 'a> Externalities for Ext<'a, B> where B: Backend { - type Error = B::Error; - - fn storage(&self, key: &[u8]) -> Result<&[u8], Self::Error> { + fn storage(&self, key: &[u8]) -> Result<&[u8], ExternalitiesError> { match self.overlay.storage(key) { Some(x) => Ok(x), - None => self.backend.storage(key) + None => self.backend.storage(key).map_err(|_| ExternalitiesError), } } diff --git a/substrate/state_machine/src/lib.rs b/substrate/state_machine/src/lib.rs index cd25cdcb90..cd7f9291bb 100644 --- a/substrate/state_machine/src/lib.rs +++ b/substrate/state_machine/src/lib.rs @@ -113,6 +113,18 @@ impl OverlayedChanges { pub trait Error: 'static + fmt::Debug + fmt::Display + Send {} impl<E> Error for E where E: 'static + fmt::Debug + fmt::Display + Send {} +/// Externalities Error. +/// +/// Externalities are not really allowed to have errors, since it's assumed that dependent code +/// would not be executed unless externalities were available. This is included for completeness, +/// and as a transition away from the pre-existing framework. +#[derive(Debug, Eq, PartialEq)] +pub struct ExternalitiesError; + +impl fmt::Display for ExternalitiesError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Externalities Error") } +} + fn to_keyed_vec(value: u32, mut prepend: Vec<u8>) -> Vec<u8> { prepend.extend((0..::std::mem::size_of::<u32>()).into_iter().map(|i| (value >> (i * 8)) as u8)); prepend @@ -120,11 +132,8 @@ fn to_keyed_vec(value: u32, mut prepend: Vec<u8>) -> Vec<u8> { /// Externalities: pinned to specific active address. pub trait Externalities { - /// Externalities error type. - type Error: Error; - /// Read storage of current contract being called. - fn storage(&self, key: &[u8]) -> Result<&[u8], Self::Error>; + fn storage(&self, key: &[u8]) -> Result<&[u8], ExternalitiesError>; /// Set storage of current contract being called (effective immediately). fn set_storage(&mut self, key: Vec<u8>, value: Vec<u8>); @@ -133,7 +142,7 @@ pub trait Externalities { fn chain_id(&self) -> u64; /// Get the current set of authorities from storage. - fn authorities(&self) -> Result<Vec<&[u8]>, Self::Error> { + fn authorities(&self) -> Result<Vec<&[u8]>, ExternalitiesError> { (0..self.storage(b"con:aut:len")?.into_iter() .rev() .fold(0, |acc, &i| (acc << 8) + (i as u32))) @@ -202,7 +211,7 @@ pub fn execute<B: backend::Backend, Exec: CodeExecutor>( #[cfg(test)] mod tests { use std::collections::HashMap; - use super::{OverlayedChanges, Externalities}; + use super::{OverlayedChanges, Externalities, ExternalitiesError}; #[test] fn overlayed_storage_works() { @@ -234,9 +243,7 @@ mod tests { storage: HashMap<Vec<u8>, Vec<u8>>, } impl Externalities for TestExternalities { - type Error = u8; - - fn storage(&self, key: &[u8]) -> Result<&[u8], Self::Error> { + fn storage(&self, key: &[u8]) -> Result<&[u8], ExternalitiesError> { Ok(self.storage.get(&key.to_vec()).map_or(&[] as &[u8], Vec::as_slice)) } diff --git a/substrate/wasm-runtime/polkadot/src/support/testing.rs b/substrate/wasm-runtime/polkadot/src/support/testing.rs index e2e7b40562..63aca0f8ae 100644 --- a/substrate/wasm-runtime/polkadot/src/support/testing.rs +++ b/substrate/wasm-runtime/polkadot/src/support/testing.rs @@ -16,7 +16,7 @@ //! Testing helpers. -use runtime_support::{NoError, Externalities}; +use runtime_support::{Externalities, ExternalitiesError}; use std::collections::HashMap; use primitives::AccountID; use statichex::StaticHexInto; @@ -29,9 +29,7 @@ pub struct TestExternalities { } impl Externalities for TestExternalities { - type Error = NoError; - - fn storage(&self, key: &[u8]) -> Result<&[u8], NoError> { + fn storage(&self, key: &[u8]) -> Result<&[u8], ExternalitiesError> { Ok(self.storage.get(&key.to_vec()).map_or(&[] as &[u8], Vec::as_slice)) } From 1617900c1d08816c3315178b40658a4e22700b10 Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Tue, 23 Jan 2018 20:38:01 +0100 Subject: [PATCH 086/112] Implement NativeExecutor, which attempts a native execution and falls back on Wasm otherwise. --- substrate/executor/src/native_executor.rs | 7 ++++--- substrate/native-runtime/support/src/lib.rs | 4 ++-- substrate/wasm-runtime/polkadot/src/lib.rs | 8 ++++---- substrate/wasm-runtime/support/src/lib.rs | 2 +- .../release/runtime_polkadot.compact.wasm | Bin 38655 -> 38647 bytes .../release/runtime_polkadot.wasm | Bin 38712 -> 38704 bytes .../release/runtime_test.compact.wasm | Bin 1460 -> 1460 bytes .../release/runtime_test.wasm | Bin 1576 -> 1576 bytes substrate/wasm-runtime/test/src/lib.rs | 10 +++++----- 9 files changed, 16 insertions(+), 15 deletions(-) diff --git a/substrate/executor/src/native_executor.rs b/substrate/executor/src/native_executor.rs index 5e588d559c..28146a46ea 100644 --- a/substrate/executor/src/native_executor.rs +++ b/substrate/executor/src/native_executor.rs @@ -1,6 +1,7 @@ use primitives::contract::CallData; use state_machine::{Externalities, CodeExecutor}; use error::{Error, ErrorKind, Result}; +use wasm_executor::WasmExecutor; use native_runtime as runtime; use runtime_support; @@ -22,13 +23,13 @@ impl CodeExecutor for NativeExecutor { if code == &native_equivalent[..] { runtime_support::with_externalities(ext, || match method { // TODO: Panic handler that comes back with error. - "execute_block" => Ok(runtime::execute_block(data.0)), - "execute_transaction" => Ok(runtime::execute_transaction(data.0)), + "execute_block" => Ok(runtime::execute_block(&data.0)), + "execute_transaction" => Ok(runtime::execute_transaction(&data.0)), _ => Err(ErrorKind::MethodNotFound(method.to_owned()).into()), }) } else { // call into wasm. - unimplemented!() + WasmExecutor.call(ext, code, method, data) } } } diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index 68914423b5..448cb6ce20 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -42,7 +42,7 @@ impl fmt::Display for NoError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "") } } -environmental!(ext : Externalities + 'static); +environmental!(ext : trait Externalities); /// Get `key` from storage and return a `Vec`, empty if there's a problem. pub fn storage(key: &[u8]) -> Vec<u8> { @@ -93,7 +93,7 @@ pub fn ed25519_verify(sig: &[u8; 64], msg: &[u8], pubkey: &[u8; 32]) -> bool { /// Execute the given closure with global function available whose functionality routes into the /// externalities `ext`. Forwards the value that the closure returns. -pub fn with_externalities<R, F: FnOnce() -> R>(ext: &mut (Externalities + 'static), f: F) -> R { +pub fn with_externalities<R, F: FnOnce() -> R>(ext: &mut Externalities, f: F) -> R { ext::using(ext, f) } diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 713d8eb091..66c5c866f6 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -40,14 +40,14 @@ use primitives::{Block, UncheckedTransaction}; /// Execute a block, with `input` being the canonical serialisation of the block. Returns the /// empty vector. -pub fn execute_block(input: Vec<u8>) -> Vec<u8> { - runtime::system::execute_block(Block::from_slice(&input).unwrap()); +pub fn execute_block(input: &[u8]) -> Vec<u8> { + runtime::system::execute_block(Block::from_slice(input).unwrap()); Vec::new() } /// Execute a given, serialised, transaction. Returns the empty vector. -pub fn execute_transaction(input: Vec<u8>) -> Vec<u8> { - runtime::system::execute_transaction(&UncheckedTransaction::from_slice(&input).unwrap()); +pub fn execute_transaction(input: &[u8]) -> Vec<u8> { + runtime::system::execute_transaction(&UncheckedTransaction::from_slice(input).unwrap()); Vec::new() } diff --git a/substrate/wasm-runtime/support/src/lib.rs b/substrate/wasm-runtime/support/src/lib.rs index 4d96617a8a..a01fe17c26 100644 --- a/substrate/wasm-runtime/support/src/lib.rs +++ b/substrate/wasm-runtime/support/src/lib.rs @@ -135,7 +135,7 @@ macro_rules! impl_stubs { $crate::Vec::from_raw_parts(input_data, input_len, input_len) }; - let output = super::$name(input); + let output = super::$name(&input[..]); &output[0] as *const u8 as u64 + ((output.len() as u64) << 32) } )* diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm index ceac1b036e10c26c70f6da761b1bb0f56ecc60c7..fbac14afd624eb259b6d07785685fc746afd3fcc 100644 GIT binary patch delta 14169 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 delta 14192 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 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm index 4a56fe2760cce554f731996b078824453bb2c1a5..2af80d0b4a62272b3fe1c07647b96c1e1b770cf2 100644 GIT binary patch delta 14138 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 delta 14147 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 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm index 5c717847a5a2dfb1d4b0e0db128b5a2cb9c57aaf..34ed540db27cdbbc5430b804d21e8ae884a9ca93 100644 GIT binary patch delta 63 zcmdnOy@h*&0TU~u0Fwg4W>X*o%Cu)@gEA-EGs{j+XQ_rrOn%Pd!paO%J=uV@1pr&Y B3g7?$ delta 63 zcmdnOy@h*&0TU~O0FwgaW>Y3sMkv#snGMREY|kt^Ih~~%A~E?niwl^=JlTM?1pr&6 B3g7?$ diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm index 64fb6a48bfd6f1cd23a2e17c4cc720efd7e8ae65..4ec976b958aaedc8980a075024f24b406c0f9f76 100644 GIT binary patch delta 62 ycmZ3%vw~+sGZQPL0Fwg4<_;hO!kj#pMRxLf=9h5Z3@FQr)rFNAq<C^O>rw!#R1F*e delta 62 ycmZ3%vw~+sGZQO=0Fwga<_;!SMhJ8ATo&2M>zQA|c{89aD^?dUi+OT0>rw!#I1L;C diff --git a/substrate/wasm-runtime/test/src/lib.rs b/substrate/wasm-runtime/test/src/lib.rs index 1cf1934976..6e257a091f 100644 --- a/substrate/wasm-runtime/test/src/lib.rs +++ b/substrate/wasm-runtime/test/src/lib.rs @@ -10,26 +10,26 @@ use alloc::vec::Vec; extern crate runtime_support; use runtime_support::{set_storage, storage, print, blake2_256, twox_128, twox_256, ed25519_verify}; -fn test_blake2_256(input: Vec<u8>) -> Vec<u8> { +fn test_blake2_256(input: &[u8]) -> Vec<u8> { blake2_256(&input).to_vec() } -fn test_twox_256(input: Vec<u8>) -> Vec<u8> { +fn test_twox_256(input: &[u8]) -> Vec<u8> { twox_256(&input).to_vec() } -fn test_twox_128(input: Vec<u8>) -> Vec<u8> { +fn test_twox_128(input: &[u8]) -> Vec<u8> { twox_128(&input).to_vec() } -fn test_ed25519_verify(input: Vec<u8>) -> Vec<u8> { +fn test_ed25519_verify(input: &[u8]) -> Vec<u8> { let sig = &input[0..64]; let pubkey = &input[64..96]; let msg = b"all ok!"; [ed25519_verify(sig, &msg[..], pubkey) as u8].to_vec() } -fn test_data_in(input: Vec<u8>) -> Vec<u8> { +fn test_data_in(input: &[u8]) -> Vec<u8> { print(b"set_storage" as &[u8]); set_storage(b"input", &input); From 1f5f56c089ff7052504ceec89c63ce3cf8a255b0 Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Tue, 23 Jan 2018 20:56:52 +0100 Subject: [PATCH 087/112] Ensure bool actually is endian-insensitive. --- .../polkadot/src/codec/endiansensitive.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs b/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs index 03dfbf8823..ec9be8e465 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs +++ b/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs @@ -45,9 +45,7 @@ macro_rules! impl_non_endians { )* } } -// TODO: this is fine as long as bool is one byte. it'll break if llvm tries to use more. happily, -// this isn't an issue for the forseeable future. if it ever happens, then it should be implemented -// as endian sensitive. +// NOTE: See test to ensure correctness. impl EndianSensitive for bool {} impl_endians!(u16, u32, u64, usize, i16, i32, i64, isize); @@ -70,4 +68,12 @@ mod tests { fn _takes_static<T: 'static>() { } fn _takes_endian_sensitive<T: EndianSensitive>() { _takes_static::<T>() } } + + #[test] + fn bool_is_not_endian_sensitive() { + let b = true; + assert_eq!(b.to_be(), b.to_le()); + let b = false; + assert_eq!(b.to_be(), b.to_le()); + } } From ead42293bc08c8a044f68d0c1fd17dc94f31880e Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Thu, 25 Jan 2018 19:28:28 +0100 Subject: [PATCH 088/112] Tests for native/wasm runtime --- substrate/Cargo.lock | 7 +++ substrate/executor/Cargo.toml | 1 + substrate/executor/src/lib.rs | 2 + substrate/executor/src/native_executor.rs | 50 ++++++++++++++++++ substrate/executor/src/wasm_executor.rs | 26 ++++----- substrate/wasm-runtime/polkadot/src/lib.rs | 17 ++++-- .../polkadot/src/runtime/system.rs | 3 ++ .../polkadot/src/support/function.rs | 2 +- .../wasm-runtime/polkadot/src/support/mod.rs | 4 +- .../polkadot/src/support/primitives.rs | 14 ++--- .../polkadot/src/support/proposal.rs | 4 +- substrate/wasm-runtime/pwasm-libc/src/lib.rs | 7 +++ .../release/runtime_polkadot.compact.wasm | Bin 42933 -> 42937 bytes .../release/runtime_polkadot.wasm | Bin 42990 -> 43015 bytes .../release/runtime_test.wasm | Bin 1905 -> 1943 bytes 15 files changed, 105 insertions(+), 32 deletions(-) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 1595bc0272..a7047446eb 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -498,6 +498,11 @@ dependencies = [ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "memcmp" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "memorydb" version = "0.1.1" @@ -726,6 +731,7 @@ dependencies = [ "assert_matches 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memcmp 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "native-runtime 0.1.0", "parity-wasm 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)", "polkadot-primitives 0.1.0", @@ -1333,6 +1339,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2" "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" +"checksum memcmp 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9a1b44fee357b6a05a9e22554ded6c1bbe57844b58190295257ac0ad4c5944e1" "checksum memorydb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "013b7e4c5e10c764936ebc6bd3662d8e3c92292d267bf6a42ef3f5cad9c793ee" "checksum mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e2e00e17be181010a91dbfefb01660b17311059dc8c7f48b9017677721e732bd" "checksum mio 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0e8411968194c7b139e9105bc4ae7db0bae232af087147e72f0616ebf5fdb9cb" diff --git a/substrate/executor/Cargo.toml b/substrate/executor/Cargo.toml index dbdef883cc..6164bb1c51 100644 --- a/substrate/executor/Cargo.toml +++ b/substrate/executor/Cargo.toml @@ -15,6 +15,7 @@ byteorder = "1.1" rustc-hex = "1.0.0" native-runtime = { path = "../native-runtime", version = "0.1" } runtime-support = { path = "../native-runtime/support", version = "0.1" } +memcmp = { version = "0.0.6" } [dev-dependencies] assert_matches = "1.1" diff --git a/substrate/executor/src/lib.rs b/substrate/executor/src/lib.rs index 56c39e5b49..17b1ec9025 100644 --- a/substrate/executor/src/lib.rs +++ b/substrate/executor/src/lib.rs @@ -34,8 +34,10 @@ extern crate serde; extern crate parity_wasm; extern crate byteorder; extern crate rustc_hex; +#[macro_use] extern crate native_runtime; extern crate runtime_support; +extern crate memcmp; #[macro_use] extern crate error_chain; diff --git a/substrate/executor/src/native_executor.rs b/substrate/executor/src/native_executor.rs index 28146a46ea..e195e8f8d7 100644 --- a/substrate/executor/src/native_executor.rs +++ b/substrate/executor/src/native_executor.rs @@ -33,3 +33,53 @@ impl CodeExecutor for NativeExecutor { } } } + +#[cfg(test)] +mod tests { + use super::*; + use primitives::twox_128; + use native_runtime::testing::{TestExternalities, one, two}; + use native_runtime::statichex::StaticHexInto; + use native_runtime::keyedvec::KeyedVec; + use native_runtime::runtime::staking::balance; + + fn tx() -> Vec<u8> { "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000".convert() } + + #[test] + fn execution_with_native_equivalent_code_runs_native_ok() { + let one = one(); + let two = two(); + + let mut t = TestExternalities { storage: map![ + twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + ], }; + + let native_equivalent_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm"); + NativeExecutor.call(&mut t, &native_equivalent_code[..], "execute_transaction", &CallData(tx())); + + runtime_support::with_externalities(&mut t, || { + assert_eq!(balance(&one), 42); + assert_eq!(balance(&two), 69); + }); + } + + #[test] + fn execution_with_foreign_code_runs_wasm_ok() { + let one = one(); + let two = two(); + + let mut t = TestExternalities { storage: map![ + twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + ], }; + + let mut foreign_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm"); + NativeExecutor.call(&mut t, &foreign_code[..], "execute_transaction", &CallData(tx())); + + runtime_support::with_externalities(&mut t, || { + assert_eq!(balance(&one), 42); + assert_eq!(balance(&two), 69); + }); + } + + // TODO: test panics. +} diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index 561e557ad9..f7d922d6fb 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -87,6 +87,15 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, ext_print_num(number: u64) => { println!("Runtime: {}", number); }, + ext_memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 => { + if let (Ok(sl1), Ok(sl2)) + = (this.memory.get(s1, n as usize), this.memory.get(s2, n as usize)) { + use memcmp::Memcmp; + (&sl1).memcmp(&sl2) as i32 + } else { + 0 + } + }, ext_memcpy(dest: *mut u8, src: *const u8, count: usize) -> *mut u8 => { let _ = this.memory.copy_nonoverlapping(src as usize, dest as usize, count as usize); println!("memcpy {} from {}, {} bytes", dest, src, count); @@ -242,22 +251,7 @@ mod tests { use super::*; use rustc_hex::FromHex; use state_machine::ExternalitiesError; - - #[derive(Debug, Default)] - struct TestExternalities { - storage: HashMap<Vec<u8>, Vec<u8>>, - } - impl Externalities for TestExternalities { - fn storage(&self, key: &[u8]) -> ::std::result::Result<&[u8], ExternalitiesError> { - Ok(self.storage.get(&key.to_vec()).map_or(&[] as &[u8], Vec::as_slice)) - } - - fn set_storage(&mut self, key: Vec<u8>, value: Vec<u8>) { - self.storage.insert(key, value); - } - - fn chain_id(&self) -> u64 { 42 } - } + use native_runtime::testing::{TestExternalities, one, two}; #[test] fn storage_should_work() { diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 3d52aa589f..1134d974a7 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -22,22 +22,28 @@ #[macro_use] extern crate runtime_support; -#[cfg(test)] +#[cfg(feature = "with-std")] extern crate rustc_hex; mod codec; #[macro_use] mod support; -mod runtime; +pub mod runtime; pub use codec::{endiansensitive, streamreader, joiner, slicable, keyedvec}; pub use support::{primitives, function, proposal, environment, storable}; -#[cfg(test)] +#[cfg(feature = "with-std")] pub use support::{testing, statichex}; use runtime_support::prelude::*; use slicable::Slicable; use primitives::{Block, UncheckedTransaction}; +/// A simple test. +pub fn simple_test(input: &[u8]) -> Vec<u8> { + println!("Executing block"); + Vec::new() +} + /// Execute a block, with `input` being the canonical serialisation of the block. Returns the /// empty vector. pub fn execute_block(input: &[u8]) -> Vec<u8> { @@ -47,7 +53,10 @@ pub fn execute_block(input: &[u8]) -> Vec<u8> { /// Execute a given, serialised, transaction. Returns the empty vector. pub fn execute_transaction(input: &[u8]) -> Vec<u8> { - runtime::system::execute_transaction(&UncheckedTransaction::from_slice(input).unwrap()); + println!("Deserialising... {:?}", input); + let utx = UncheckedTransaction::from_slice(input).unwrap(); + println!("Forwarding... {:?}", utx); + runtime::system::execute_transaction(&utx); Vec::new() } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 042d1af2d7..70348574b1 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -84,6 +84,7 @@ pub fn execute_block(mut block: Block) { /// Execute a given transaction. pub fn execute_transaction(utx: &UncheckedTransaction) { + println!("Executing..."); // Verify the signature is good. assert!(utx.ed25519_verify(), "All transactions should be properly signed"); @@ -97,6 +98,8 @@ pub fn execute_transaction(utx: &UncheckedTransaction) { // increment nonce in storage (expected_nonce + 1).store(&nonce_key); + println!("Dispatching..."); + // decode parameters and dispatch tx.function.dispatch(&tx.signed, &tx.input_data); } diff --git a/substrate/wasm-runtime/polkadot/src/support/function.rs b/substrate/wasm-runtime/polkadot/src/support/function.rs index dd54ba1080..875bb98326 100644 --- a/substrate/wasm-runtime/polkadot/src/support/function.rs +++ b/substrate/wasm-runtime/polkadot/src/support/function.rs @@ -21,8 +21,8 @@ use streamreader::StreamReader; use runtime::{staking, session, timestamp, governance}; /// Public functions that can be dispatched to. -#[cfg_attr(test, derive(PartialEq, Debug))] #[derive(Clone, Copy)] +#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] pub enum Function { StakingStake, StakingUnstake, diff --git a/substrate/wasm-runtime/polkadot/src/support/mod.rs b/substrate/wasm-runtime/polkadot/src/support/mod.rs index 384909d019..3730483b25 100644 --- a/substrate/wasm-runtime/polkadot/src/support/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/support/mod.rs @@ -22,8 +22,8 @@ pub mod proposal; pub mod environment; pub mod storable; -#[cfg(test)] +#[cfg(feature = "with-std")] pub mod statichex; -#[cfg(test)] #[macro_use] +#[cfg(feature = "with-std")] pub mod testing; diff --git a/substrate/wasm-runtime/polkadot/src/support/primitives.rs b/substrate/wasm-runtime/polkadot/src/support/primitives.rs index fe5bb2ebbd..48fa91dd79 100644 --- a/substrate/wasm-runtime/polkadot/src/support/primitives.rs +++ b/substrate/wasm-runtime/polkadot/src/support/primitives.rs @@ -23,7 +23,7 @@ use slicable::{Slicable, NonTrivialSlicable}; use function::Function; use runtime_support::{mem, blake2_256, twox_128, twox_256, ed25519_verify}; -#[cfg(test)] +#[cfg(feature = "with-std")] use std::fmt; /// The Ed25519 pubkey that identifies an account. @@ -51,7 +51,7 @@ pub type TxOrder = u64; pub type Hash = [u8; 32]; #[derive(Clone, Default)] -#[cfg_attr(test, derive(PartialEq, Debug))] +#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] /// The digest of a block, useful for light-clients. pub struct Digest { /// All logs that have happened in the block. @@ -59,7 +59,7 @@ pub struct Digest { } #[derive(Clone)] -#[cfg_attr(test, derive(PartialEq, Debug))] +#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] /// The header for a block. pub struct Header { /// The parent block's "hash" (actually the Blake2-256 hash of its serialised header). @@ -108,8 +108,8 @@ impl Slicable for Header { impl NonTrivialSlicable for Header {} -#[cfg_attr(test, derive(PartialEq, Debug))] /// A vetted and verified transaction from the external world. +#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] pub struct Transaction { /// Who signed it (note this is not a signature). pub signed: AccountID, @@ -187,14 +187,14 @@ impl UncheckedTransaction { } } -#[cfg(test)] +#[cfg(feature = "with-std")] impl PartialEq for UncheckedTransaction { fn eq(&self, other: &Self) -> bool { self.signature.iter().eq(other.signature.iter()) && self.transaction == other.transaction } } -#[cfg(test)] +#[cfg(feature = "with-std")] impl fmt::Debug for UncheckedTransaction { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "UncheckedTransaction({:?})", self.transaction) @@ -229,8 +229,8 @@ impl Slicable for UncheckedTransaction { impl NonTrivialSlicable for UncheckedTransaction {} -#[cfg_attr(test, derive(PartialEq, Debug))] /// A Polkadot relay chain block. +#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] pub struct Block { /// The header of the block. pub header: Header, diff --git a/substrate/wasm-runtime/polkadot/src/support/proposal.rs b/substrate/wasm-runtime/polkadot/src/support/proposal.rs index ec02e32dfb..663692a4f7 100644 --- a/substrate/wasm-runtime/polkadot/src/support/proposal.rs +++ b/substrate/wasm-runtime/polkadot/src/support/proposal.rs @@ -25,8 +25,8 @@ use streamreader::StreamReader; use runtime::{system, governance, staking, session}; /// Internal functions that can be dispatched to. -#[cfg_attr(test, derive(PartialEq, Debug))] #[derive(Clone, Copy)] +#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] pub enum InternalFunction { SystemSetCode, StakingSetSessionsPerEra, @@ -52,7 +52,7 @@ impl InternalFunction { } /// An internal function. -#[cfg_attr(test, derive(PartialEq, Debug))] +#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] pub struct Proposal { /// The priviledged function to call. pub function: InternalFunction, diff --git a/substrate/wasm-runtime/pwasm-libc/src/lib.rs b/substrate/wasm-runtime/pwasm-libc/src/lib.rs index eed597e73b..0c2fd43fc6 100644 --- a/substrate/wasm-runtime/pwasm-libc/src/lib.rs +++ b/substrate/wasm-runtime/pwasm-libc/src/lib.rs @@ -8,6 +8,7 @@ extern "C" { fn ext_memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8; fn ext_memmove(dest: *mut u8, src: *const u8, n: usize) -> *mut u8; fn ext_memset(dest: *mut u8, c: i32, n: usize) -> *mut u8; + fn ext_memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32; fn ext_malloc(size: usize) -> *mut u8; fn ext_free(ptr: *mut u8); } @@ -21,6 +22,12 @@ pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut ext_memcpy(dest, src, n) } +/// memcpy extern +#[no_mangle] +pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 { + ext_memcmp(s1, s2, n) +} + /// memmove extern #[no_mangle] pub unsafe extern "C" fn memmove(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 { diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm index 84f659746094ead43a63d2c53ed6422c1ec6a879..688c7bcdb8250ae6b2dafcf249e880cdf929fd92 100644 GIT binary patch delta 788 zcmYjPZAep57~Yw?de<ggGc6+J7(^K<rWxtdd8xKxn`lnUEi}XRv9(x5Q1+u};?$B{ zFDW{vLDxPEGdcvTYzje9L{>i{5+Z;4b3Y3IM7`(QmVch}Jm-DhuXFFyIqkDK?SPBC z3A-=o`~i&+e(hkCOl}~0_91Uki${!_1w58Ec`}I}TFX8oZr>4CaTnWC-ilEORhAQx zy{t476u(WSC`xu4|BFD?3h}r)6C*5cZsvx#*~2<zqYi0kUktIvQcFY#Th_s!+;n(g zxlIJ9wH6?rvTj7YVcm-O+<I)Yu%2pU>ZL@clFDZ_E5wha0IRK(2&~h#It|<Q?>F(b zZ|$!T`yF=d_03^HUQox!cGkskYshTaiGjTh0p#jHPY%4`Y154rc>k-h1$n)*56jLw zT_jCU4bb9r!u95MH6fSj4pwphkZTVSS@$7{7hM+fu5B1$;^C8goU?83wOGY`^c;7v zj-XCYMG7+=MH%uek%=U-)1Ld;=v;g86L&6N8c0XyLZljM#w4vI!n><|>P0U2f{*^O zlCC8C+4UtAwL@{YAJt4x6K)|zO;8jvpiU@-@Nh5-#zrIvhK{Fd*ul|rCgq<{Oi<su z?5`vu8|q!+D=tJDV0utuiE9ZFWz(<?YmW{WvZh=4#HgqF@<+idi(Z-sM@EX-<lsHN zY0@^OR%nN*krOJbhAYt=@I}t6>MLS$SpJO?N(CE;Ugqy7jk)<hvk=LFY$XeB-tncB uTXo`yFrh4GabBX7LEE@N&{IN<ASr7gIR4$3Zdj$E8obg<8O(pzM*afcU;uLf delta 810 zcmY*XOH5Ny5Pi4s+E-iRLlYA|>P3TqVbK5;X{%6)ZNoRUmC*XD)%qbpOEtt#Vhmuh zWz%LtliCoBqS2VZ;%bDT1Z62&W#Lj>xN+eEqsHIDxvx-RbMBluGiPS<-c(xkB&~{h z$z1%<rTC`?ec)WLx;xN)qB|&vY&#h*CK6lN{8@$1Gg>d=^S3mRM<no9FCZFgW)$4b zDvd``g&~uXXxIx=JwZY&RY+<q`v2tOo>k=W-aM`pSOZYju!P<P)}CB$vVRhB%GpFT z5VsY>BikLKg*JN$V$i+~5$rn=XY8lSw1rf#(k@D@R950yVHNqfLZI1EMYQaiV?z#+ zSiITH2fuEaLyWh!;G7SwHjGQ#_{N=WlXx)XJ9nYra0W3}mSMRErg`72s}6<VE)T|T zca&(^qT5SyB&vfWZa2g_j^m849WGv*@;0Jlv{UAe8M5fDM1|=OpXIys9-CL8L!<u! zuXuX0AJH7Z$t)Cjun`N2F2CaiU#`Z~D80S03I3$YA(qrZ`>3drHSne{stA6V?)NX3 zh&Nl{`oIeNHSk`^rx9<54~iPPWuE|sv0DASU`1k$kuF&RU!(#i68W$-EW_a7>8#cB zOdH-jK4#W`Tias7O;eGd{MO8FW|&RL?EBD?gegzbfx2PX&UH_+mQ5rc@;jA07=|n0 zRWh7yZ3cGhOqTH@*W)r;2&F>V>`RQ++yLz(I?VYZbwI-+OO9M2qC^X65ybi|%spDf wf2rWzxPm*Ne5^^S#=Y?z{?UCA9+yO_mz~bv`=J+g>jWxLLRGSw_1t%mfAa|gYXATM diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm index d758dcbb60ab7897654b228c382cf017239b01fe..861eb4c60800e920bc63aa8632272991c5c03d73 100644 GIT binary patch delta 975 zcmYjPT}YEr82--ZzJ2@l!?x0mg7TY%zx|MZ<?kBdCN>RinrWz0ClyXbQxwENt4+~T z4o3cEkdx6xUYr6;G$RTE!RjJ*Q`kk3soex6(M9k1bkkit@AI7JJ<oaHZ9kV;&pURo z3<ZYD+hy)1h8ucQaU#mZ@GQ&9d7fuj7LZpc1Xjta7`0l%!AHi*WT=T@xG==%`3@y^ zB73sj?Q+*ZL<|qa-Pq=0V(C$f>lza$cRTCr8*7+&SzWWs#Uu!bQLesaO(cL`grQh` zk1GOP<El_BvCB`hPzDr61jQ%h%b@(y+@Y#RI{^xt!s`IN;kV()7=ggS`wUjVDuWkr z)zAh;m2pgtl;q!mRTj!O(ab@Kj&^B~689&40IW=2knj{KNvQxAKTS_T0$EEpBM=Fh zi6AO6)jQ&T)-LfmTLTVRH<!?cb+e23EovD}$(aRgu;w8FzqA_gvel0`+-@@gj@qIC z=WX$T-)(g<+<uX<h*w2q5p@z@WOj*_punxUiHIZq+&y9N<lNZ|`s5$`E5NyYJG`SP zumV3<Ku7K_n1zjTMqw%#&4o?CrD4diqB(l+$N4lc4m&Oa?{f4(u25Wt!jz&4dmIk@ zyu>NpFp$IxS+u{Y^bDjvDb>-`Eg_U20f(esx<co9P`SiHio3dnc6_Prkts!mh&O7F z@|HzpK{|nqyZn2hGpFM{?KE}{!cT*><Jq`jQpf59yxH9+9T>3gmK}fXsoqw{y>|TQ zMo=BP`7zY>4A_RZ7&Z|-boWSK93J#|L-*!GeqbsCclD~Io^;scb?+u!OFLdjwEai` zsvpjUoTZUC(ldOJdivp$5T?i4ejWLH*Gtz5_RL6Eo%qw}Wr=0u#}g5FWUN(E0l?r? z8F;|A^=cYfn7B^Au<Xfl`VY~LN8p)<ogt>jMN@g8B7HC)4oq$BL;1>7(ss&-?>8Qu XRv9^!k`WmZiL8#_p$alRos0ehM@t+t delta 1013 zcmYjPYivtl7(U-wFQ@Hlr%Wpn%{R$(#fZzWOLZr#ExJivMmE>kX`<GdOXiwIl&zJ8 zHE)oun6M&?Ao&tmB3R513qcV-{J;;9NQ6klC4TUJUDx^Zyzlcq&-Y$V+wold@=WZi zBd_B1`{N%1d1`a3F06*Pg<Aw|P6365#4c+@jfS)cSRjH$-(r9u@z2nsE4;H+6&&2Z zN8KwF>B3u^ns#mzoSNWnRTZWih+up>EK>H7+|MBnxT0N!_*=V$I9Q#oQpAvuYy<-{ zRBJGhai=(o=bc9ev-5+9XYx;Csc<4e1sqlnVzV`h_|w{oLbENQBL-%)e-bf#r*18V z`O{Q0F+k6}7l`5c_tLnCHI{5b6^6=6h{S%Exe1cein&OdDssojb=QC7^I|hs0*VTo zE5BjyfU--2g`uhe#BYJ+M1qtjAKrO%;I?Vuqo<b`q1{`6c+EQ%@v(P0;ty}oVVq0_ zg@!0msGQCRh5yL=Q34U)Tw-LmedBX*-tdZYzJRuR2ywXDkMpcG9?Un^@Xfnw2JmoL z7FdA7kw6RP>7`i3syqDMuhpeyNvx!KRc3)|WYGk2?IfsOQ<64X;nJGDILo%Sj^r7r ziCPrgNs&TML4Z`14<6NS9Wk=XbuQkoZT%7=u?OpAK6QlH>Sv<DmTuV2_r0<CiHIE! zHSFPzuZ<Cnfl3tqG#2ZXL81^@V*Tp13FusXAjO@9hr93>gm}aX7ki4p9W%k-qdL4s z7derxKg_7Es2>K7HDuVF<FC_M1BBYcnEi>a#W%A$_@^mOI^jY`G~;wd?`HKtY(y_3 z5_=i@#V;BeT+XI+5(B5*KJ4?R+sWdm?P<MxAvUwXlunsRXQTY8QP0inbC%8c1v1>~ zkf1-YJ6l}=ZRhqO8{M)T5=j&C;$$g$wJdf1ApeH`-g^G$ibp2G%03G`y}TpK>eFuA v8v?QN+&-e{sa@$JA(=Pf<u85nGEJ{0f7rApqd)~ps3_~kQa!tW#Yg@DSAI3@ diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm index 1b822803e0047eac44c49621940c0f8da72b4867..1b9dc8a1cdf996fc29d9d523f4495fb06a4c4862 100644 GIT binary patch delta 324 zcmYk0Jx;?w5QS&gYdijn*Cb#XkVO@xi-n_5p+&TaBUmBXAj`jUoP>xXa04P2+yRLn zDQDn7v@~G5f!EA?-)NrZtNm;~oeK}x*k0U|I0Iq(@pxqDa;=t7iC{ud1|SLuEcpc) z<rT6whFS1=;on5#kh{L?4WVr`q*$eQO*a4Kfja`)Y4&{Tdfwp7U-CSdt--SLMcu=1 zgT!AXt00-eo)q(VlC7cBnChvnT#-0ka@eoYoL?4jAjRV-N+)2GS<X2eDhSk9RewVW zZx}G>VZvy5A`Gk9Wg1nO!$b!hL{-*fGF8fB>{tprWrBknI${b{cGvhFBYpQn`Uq)d YU-~S+CCwH!73yOLQ~A%fN=XiX0Xj!X?*IS* delta 271 zcmbQv|B-KkJ@b1;o{3J?6VH{%@Nlz(00%QOGYb<73u6HT11mElgCP4tMxM#>jN<h? z{3WTyCGkl)iP@<}@kXX*47|Kxk&^QK3NW7!iEn6R!N4yJmQPJFGBq`{j4w+q%1o<d z5D+XX1(}nYo|zY4npd8gm%<>(mYbTJTu{j%#13TS=9i^12!n)*Q%e{`*m4tda`FX} z8AMsqic(V<#5frlxE677Pv&Qm6y$JJaAZ|rP+%0`bkuNU7vPv|$)o@jHF0ECU;>L; qIC2VbY|dg@&&0?*xq<oS<j<^uj9iml*^V-@PGT2jWS^|Vo(%wK7eoI5 From bbac6f8da1f2cdc80243a5b84773cecf57b97992 Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Fri, 26 Jan 2018 15:24:12 +0100 Subject: [PATCH 089/112] Handle panics in native execution. --- substrate/executor/src/native_executor.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/substrate/executor/src/native_executor.rs b/substrate/executor/src/native_executor.rs index e195e8f8d7..14e08f8e80 100644 --- a/substrate/executor/src/native_executor.rs +++ b/substrate/executor/src/native_executor.rs @@ -1,3 +1,4 @@ +use std::panic::catch_unwind; use primitives::contract::CallData; use state_machine::{Externalities, CodeExecutor}; use error::{Error, ErrorKind, Result}; @@ -22,9 +23,8 @@ impl CodeExecutor for NativeExecutor { let native_equivalent = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm"); if code == &native_equivalent[..] { runtime_support::with_externalities(ext, || match method { - // TODO: Panic handler that comes back with error. - "execute_block" => Ok(runtime::execute_block(&data.0)), - "execute_transaction" => Ok(runtime::execute_transaction(&data.0)), + "execute_block" => catch_unwind(|| runtime::execute_block(&data.0)).map_err(|_| ErrorKind::Runtime.into()), + "execute_transaction" => catch_unwind(|| runtime::execute_transaction(&data.0)).map_err(|_| ErrorKind::Runtime.into()), _ => Err(ErrorKind::MethodNotFound(method.to_owned()).into()), }) } else { From 0b138b0fd5d6b027ad17d04b17e2b8878586e2a0 Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Fri, 26 Jan 2018 19:26:10 +0100 Subject: [PATCH 090/112] Introduce tests which demonstrate bad wasm compiler. --- substrate/build.sh | 6 +++ substrate/executor/src/lib.rs | 7 +-- substrate/executor/src/native_executor.rs | 41 ++++++++++++++---- substrate/executor/src/wasm_executor.rs | 28 ++++++++++-- substrate/wasm-runtime/polkadot/src/lib.rs | 13 ++---- .../polkadot/src/runtime/system.rs | 3 -- substrate/wasm-runtime/support/src/lib.rs | 8 +++- .../release/runtime_polkadot.compact.wasm | Bin 42937 -> 43095 bytes .../release/runtime_polkadot.wasm | Bin 43015 -> 43173 bytes .../release/runtime_test.compact.wasm | Bin 1789 -> 1875 bytes .../release/runtime_test.wasm | Bin 1943 -> 2029 bytes substrate/wasm-runtime/test/src/lib.rs | 20 ++++++++- 12 files changed, 96 insertions(+), 30 deletions(-) create mode 100755 substrate/build.sh diff --git a/substrate/build.sh b/substrate/build.sh new file mode 100755 index 0000000000..40a1043226 --- /dev/null +++ b/substrate/build.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +cd wasm-runtime +./build.sh +cd .. + diff --git a/substrate/executor/src/lib.rs b/substrate/executor/src/lib.rs index 17b1ec9025..9bea6958de 100644 --- a/substrate/executor/src/lib.rs +++ b/substrate/executor/src/lib.rs @@ -34,7 +34,6 @@ extern crate serde; extern crate parity_wasm; extern crate byteorder; extern crate rustc_hex; -#[macro_use] extern crate native_runtime; extern crate runtime_support; extern crate memcmp; @@ -53,8 +52,6 @@ mod native_executor; pub mod error; /// Creates new RustExecutor for contracts. -pub fn executor() -> wasm_executor::WasmExecutor { - // TODO: check what the code to execute is and use NativeExecutor if the wasm is compiled with - // matches. - wasm_executor::WasmExecutor::default() +pub fn executor() -> native_executor::NativeExecutor { + native_executor::NativeExecutor } diff --git a/substrate/executor/src/native_executor.rs b/substrate/executor/src/native_executor.rs index 14e08f8e80..79e6af2ea9 100644 --- a/substrate/executor/src/native_executor.rs +++ b/substrate/executor/src/native_executor.rs @@ -6,7 +6,7 @@ use wasm_executor::WasmExecutor; use native_runtime as runtime; use runtime_support; -struct NativeExecutor; +pub struct NativeExecutor; impl CodeExecutor for NativeExecutor { type Error = Error; @@ -46,7 +46,31 @@ mod tests { fn tx() -> Vec<u8> { "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000".convert() } #[test] - fn execution_with_native_equivalent_code_runs_native_ok() { + fn panic_execution_with_foreign_code_gives_error() { + let one = one(); + let mut t = TestExternalities { storage: map![ + twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0] + ], }; + + let foreign_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm"); + let r = NativeExecutor.call(&mut t, &foreign_code[..], "execute_transaction", &CallData(tx())); + assert!(r.is_err()); + } + + #[test] + fn panic_execution_with_native_equivalent_code_gives_error() { + let one = one(); + let mut t = TestExternalities { storage: map![ + twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0] + ], }; + + let native_equivalent_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm"); + let r = NativeExecutor.call(&mut t, &native_equivalent_code[..], "execute_transaction", &CallData(tx())); + assert!(r.is_err()); + } + + #[test] + fn successful_execution_with_native_equivalent_code_gives_ok() { let one = one(); let two = two(); @@ -55,7 +79,8 @@ mod tests { ], }; let native_equivalent_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm"); - NativeExecutor.call(&mut t, &native_equivalent_code[..], "execute_transaction", &CallData(tx())); + let r = NativeExecutor.call(&mut t, &native_equivalent_code[..], "execute_transaction", &CallData(tx())); + assert!(r.is_ok()); runtime_support::with_externalities(&mut t, || { assert_eq!(balance(&one), 42); @@ -64,7 +89,7 @@ mod tests { } #[test] - fn execution_with_foreign_code_runs_wasm_ok() { + fn successful_execution_with_foreign_code_gives_ok() { let one = one(); let two = two(); @@ -72,14 +97,14 @@ mod tests { twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] ], }; - let mut foreign_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm"); - NativeExecutor.call(&mut t, &foreign_code[..], "execute_transaction", &CallData(tx())); + let foreign_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm"); + let r = NativeExecutor.call(&mut t, &foreign_code[..], "execute_transaction", &CallData(tx())); + println!("{:?}", r); + assert!(r.is_ok()); runtime_support::with_externalities(&mut t, || { assert_eq!(balance(&one), 42); assert_eq!(balance(&two), 69); }); } - - // TODO: test panics. } diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index f7d922d6fb..05cb5580eb 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -234,7 +234,9 @@ impl CodeExecutor for WasmExecutor { .add_argument(I32(offset as i32)) .add_argument(I32(size as i32))) .and_then(|p| module.execute_export(method, p)) - .map_err(|_| -> Error { ErrorKind::Runtime.into() })?; + .map_err(|_| -> Error { + ErrorKind::Runtime.into() + })?; if let Some(I64(r)) = returned { memory.get(r as u32, (r >> 32) as u32 as usize) @@ -250,8 +252,28 @@ mod tests { use super::*; use rustc_hex::FromHex; - use state_machine::ExternalitiesError; - use native_runtime::testing::{TestExternalities, one, two}; + use native_runtime::testing::TestExternalities; + + #[test] + fn returning_should_work() { + let mut ext = TestExternalities::default(); + let test_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); + + let output = WasmExecutor.call(&mut ext, &test_code[..], "test_empty_return", &CallData(vec![])).unwrap(); + assert_eq!(output, vec![0u8; 0]); + } + + #[test] + fn panicking_should_work() { + let mut ext = TestExternalities::default(); + let test_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); + + let output = WasmExecutor.call(&mut ext, &test_code[..], "test_panic", &CallData(vec![])); + assert!(output.is_err()); + + let output = WasmExecutor.call(&mut ext, &test_code[..], "test_conditional_panic", &CallData(vec![2])); + assert!(output.is_err()); + } #[test] fn storage_should_work() { diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 1134d974a7..c03fcc83c5 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -38,12 +38,6 @@ use runtime_support::prelude::*; use slicable::Slicable; use primitives::{Block, UncheckedTransaction}; -/// A simple test. -pub fn simple_test(input: &[u8]) -> Vec<u8> { - println!("Executing block"); - Vec::new() -} - /// Execute a block, with `input` being the canonical serialisation of the block. Returns the /// empty vector. pub fn execute_block(input: &[u8]) -> Vec<u8> { @@ -53,11 +47,12 @@ pub fn execute_block(input: &[u8]) -> Vec<u8> { /// Execute a given, serialised, transaction. Returns the empty vector. pub fn execute_transaction(input: &[u8]) -> Vec<u8> { - println!("Deserialising... {:?}", input); + if input.len() == 0 { + panic!("no transaction data given!"); + } let utx = UncheckedTransaction::from_slice(input).unwrap(); - println!("Forwarding... {:?}", utx); runtime::system::execute_transaction(&utx); - Vec::new() + input.to_vec()//Vec::new() } impl_stubs!(execute_block, execute_transaction); diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 70348574b1..042d1af2d7 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -84,7 +84,6 @@ pub fn execute_block(mut block: Block) { /// Execute a given transaction. pub fn execute_transaction(utx: &UncheckedTransaction) { - println!("Executing..."); // Verify the signature is good. assert!(utx.ed25519_verify(), "All transactions should be properly signed"); @@ -98,8 +97,6 @@ pub fn execute_transaction(utx: &UncheckedTransaction) { // increment nonce in storage (expected_nonce + 1).store(&nonce_key); - println!("Dispatching..."); - // decode parameters and dispatch tx.function.dispatch(&tx.signed, &tx.input_data); } diff --git a/substrate/wasm-runtime/support/src/lib.rs b/substrate/wasm-runtime/support/src/lib.rs index 0c13c17ff7..d0b4c8a799 100644 --- a/substrate/wasm-runtime/support/src/lib.rs +++ b/substrate/wasm-runtime/support/src/lib.rs @@ -144,7 +144,13 @@ macro_rules! impl_stubs { }; let output = super::$name(&input[..]); - &output[0] as *const u8 as u64 + ((output.len() as u64) << 32) + // things break if we try to take the address of an unallocated vec, so we + // shortcircuit the empty output case. + if output.len() > 0 { + &output[0] as *const u8 as u64 + ((output.len() as u64) << 32) + } else { + 0 + } } )* } diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm index 688c7bcdb8250ae6b2dafcf249e880cdf929fd92..dfff5d575e5accbe8b199b51b524d51e270cbd8c 100644 GIT binary patch delta 266 zcmX|*u}Z{15QcaD-JqCTF6D{MBvoF(?F19Z0|@sJM@k>SG{MR)k07xS1Hx6lf`!^y z*jNTGg;!jEGshuYd^<nGKi}IYzQ6GLOxV7!U+CvCx&<2Q9{R-<uJy6aahjp>hV3N` zV<`E)O`Yb>(+qKGj#K3+*4QM7yN~|-WJj<K-F2IO*-+v#t1Vy(m>{$Pqp&amf65Ux z8>ZxpkxP=2a)PuAN2FG4P|Rw%a3~TnxpdSdjY#F#4s9Coznpw4f1zr!%_3KbMDc6u O0LRfhHtU<G73~3g6fs-? delta 107 zcmcb9fobP?rVXnYnJ%B)yoT}iV%B&jrh2ByJxe9D6qrq!IGhyP6j>CQHJBKbnAR$? zGC6?QEUvr^3QPh_+zKoTtSyQxlOHaXWXWb^te?!dEJTROktYkN9;`-#i36x?^ZR8P Fi~vve8QcH> diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm index 861eb4c60800e920bc63aa8632272991c5c03d73..441bee2cd5c37f208d2a4272bf9a2a0f9a3cde83 100644 GIT binary patch delta 310 zcmX|*F>b;@5JhMH7%9?Xu|3V$l`jz2StQro!|8GW+@K)p93cuFQY4O%CaKdz5rqp1 z8hU0{B--N7j{cwjHlKL=!uu~{^Km%x_v`Qk47^H|s6mn9V=XNT6(!|Z<H4UwgS#4C zNh<ds#eSjB>&jdfDS3*ppxdu2Iry3)f(6+#J|~N&*!$@sTp04#`O@r`1IMBkw?eta z38qFdnkH&-b{)}Yq@ZYQQ?cs_R%<$<5^F=6_Ewz_8F5C){27CtT4lekCi+ipV^_|d U+1yTQph!QGNhh;FhwW~~S9D=A%K!iX delta 131 zcmZ2_k*WOx(}qWkOfOGve!_TraY{TBQ$16iBZDJ@1`~^;K(-RI854^FvjT$xqkxhE zvndmYlR}#!P(*`?L5XRtA}f;vh|S{4%b>s{z{IV<qQKgs$O05)1PL(!g&Y|am>mVO aK<2P;XEQR^PqthZGWp6fq0Q>c>lgvfjvH<O diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm index b2576fa0741b2c3256eda346200d34a7c7818b7d..3ae531562eb46b2d5879e8dabdb75275115a67ed 100644 GIT binary patch delta 249 zcmey%dzo*--+CTyb|~OrVPaunEMQ<@WoBd$WZ%!o!<L(xn_pDP#K2RMT3iyJl30=$ zpP9$NDG27K<`$Gx#uufQlosVNaB+df3KH`&lNq?hz?|g#yp+t6%>2B>oOp-?4?kEU zDJL;I)hOP`)QmxqmlrHlQl4J{7T`nT8yZ<K@J~))6x9(BEGh-MASpFHGcUe0uRJp^ zg+Y)lH!&wCKbb*@C9Nnml|h)3k%4O#7x(0aj2pxR7?>Os7+rZ86c_}UxSbfdnHhk1 JvmeuX768GpM2G+Y delta 185 zcmcc2_m_9V-+E3Cb`aoTVPaunEMQ<@WoBd$WN&5UWXny>%`d8CV&ExBEiQ>qNi0c> z&&*@s<Og$;auTysjpB_=%^0|N!6GH)`4wP3Hxl2_$bx}K7%ZQfVq|J+Xc=FYT9lbq z$-paER0=d!H7PYcGcUe0uRJp^g@KPPH!&wCKbe7_C9Nnml|g`$k%6m`i(~RV#toAl MSq^MYXMV#B07h6fk^lez diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm index 1b9dc8a1cdf996fc29d9d523f4495fb06a4c4862..ac94a72cdee5c83cc5589f05510aba657675f862 100644 GIT binary patch delta 288 zcmYk0K~94}7=_;e7Nw~JR<Y`aE0m;0cczIa@BkAEf6YW@AarPD<srK0HJZ3}?Iqm0 z^$z0b!k4_{|Gu~Rcl?X*=PU`i|Cd9zkLP$EtAPWTA@V<2xD{;j5*b<<L8>;LXvnmU z#&KX>ooSha#}@KR7t+W|XQlWZLT-menLSY|(%Chlku_#hJzGBc$J6u%<FVbTNN2O@ ztyohdmk%9Iqo(a&SkR-?qSYIz3!DuUsl4tG+e6hj_j{wNHDU6jR%CE7P+3`4IWE0r jLxig%hTuKmTkh=R5YAn~?ng)vI>R}JF8aQ{IUn9P+=))b delta 227 zcmaFMKb?Pr6JtFu4?75OFarS#6AKGt0RsaoGb4i_`zl6Ww%pX*{Gv)G2A-1C;*$83 z#FE7L%sd8OelRyFCowzKDBj4_jDe3AEK*XQUjgRxBk>K5EEoiY!SbmoMy95Qmhok& zMVV=p41$71ex*QjlTy<&^WsbM$}{s)7=%EUCKpsP2!k291q>qWK#|=1vQ!39kWg`I s34<70ZemVOelmkNOIlHCDuV<kBLml3E}qFgOdBSzXF0I>DzgL&0B{OF+W-In diff --git a/substrate/wasm-runtime/test/src/lib.rs b/substrate/wasm-runtime/test/src/lib.rs index 6e257a091f..2b9a21c17f 100644 --- a/substrate/wasm-runtime/test/src/lib.rs +++ b/substrate/wasm-runtime/test/src/lib.rs @@ -43,4 +43,22 @@ fn test_data_in(input: &[u8]) -> Vec<u8> { b"all ok!".to_vec() } -impl_stubs!(test_data_in, test_blake2_256, test_twox_256, test_twox_128, test_ed25519_verify); +fn test_empty_return(_input: &[u8]) -> Vec<u8> { + Vec::new() +} + +fn test_panic(_input: &[u8]) -> Vec<u8> { + panic!("test panic"); +} + +fn test_conditional_panic(input: &[u8]) -> Vec<u8> { + if input.len() > 0 { + panic!("test panic"); + } else { + assert!(input.len() > 0); + } + input.to_vec() +} + +impl_stubs!(test_data_in, test_empty_return, test_panic, test_conditional_panic, + test_blake2_256, test_twox_256, test_twox_128, test_ed25519_verify); From a9c864e098c65a5a45ff436259f9c23b3f62df37 Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Fri, 26 Jan 2018 22:16:10 +0100 Subject: [PATCH 091/112] Attempt fix. --- substrate/wasm-runtime/support/src/lib.rs | 8 ++++++-- .../release/runtime_polkadot.compact.wasm | Bin 43095 -> 35733 bytes .../release/runtime_polkadot.wasm | Bin 43173 -> 35782 bytes .../release/runtime_test.compact.wasm | Bin 1875 -> 2636 bytes .../release/runtime_test.wasm | Bin 2029 -> 2761 bytes substrate/wasm-runtime/test/src/lib.rs | 2 -- 6 files changed, 6 insertions(+), 4 deletions(-) diff --git a/substrate/wasm-runtime/support/src/lib.rs b/substrate/wasm-runtime/support/src/lib.rs index d0b4c8a799..1f71973c18 100644 --- a/substrate/wasm-runtime/support/src/lib.rs +++ b/substrate/wasm-runtime/support/src/lib.rs @@ -139,8 +139,12 @@ macro_rules! impl_stubs { $( #[no_mangle] pub fn $name(input_data: *mut u8, input_len: usize) -> u64 { - let input = unsafe { - $crate::vec::Vec::from_raw_parts(input_data, input_len, input_len) + let input = if input_len == 0 { + $crate::vec::Vec::new() + } else { + unsafe { + $crate::vec::Vec::from_raw_parts(input_data, input_len, input_len) + } }; let output = super::$name(&input[..]); diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm index dfff5d575e5accbe8b199b51b524d51e270cbd8c..68996e2c265a309cb12b729f9efa2a0bb60446fe 100644 GIT binary patch literal 35733 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 Prbwvdb20JA*>C-SC8Tc% literal 43095 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 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm index 441bee2cd5c37f208d2a4272bf9a2a0f9a3cde83..0deae851a2fec60989afbea7ea9a82b08a91e75b 100644 GIT binary patch literal 35782 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 literal 43173 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 H-8B6_2XWo) diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm index 3ae531562eb46b2d5879e8dabdb75275115a67ed..d5026fc30a19ae56a1276d158a96eb4394780526 100644 GIT binary patch literal 2636 zcmd^B-EJF26h1RM`(uwCPudWL7QwMqAqOFFLgJ(;Kc1)&y{XDIH;x-`f;aKnayD(l z1?B?r09^1EeFjjk5zo+P;0ZWqCW)O$aFI($B!A~;_Uw1QIXk=1I~@uD5F4faU^<<` zzM|i$nC=U*IpR$EkylCB2VhtHApa2MAkAMaq_2wZ^ON3jy53#iYy)uc4hPfz`sU`^ z!|sc8GB`X3!HI+uhm$k~$?m)C9;HRMcXBd1=oM+dds>Vpy`vNY&X+kqbV*RNKsr1a zpZgUhUNN2w@&ZC$P-Fj;Dqhx!I9lOo@pAO4ySBdVDb7Nk^+Gicl!WBsPbo15Dk)$w z{!LV(VLBX5&Lu2P&Q7V{^k|TG&+?apybtB*f?-9u&Z?Cnr8WIt(d!O!s4Y4-9gd6h z?j$YFCOMe0i;a8v-~bkvopUhC`-5UI%6lhWpSV+Vi8*oaR$at(!nBv>eD3U>yDoo2 z`Q?&;@{gvPK+vgx23-aO6evxoBQlNhAoUv|qN(i6{t>Loni3j{ti)NtG0JCEzyM{| zNKjc(G-6CJes;eeqS~tp1iGRgA$ea{B}VnQ5@@%+p7@*#ghn;us^FY6F+#=HVEFXD z(RGE9kz7w|VjH(5F(on>l0^|>g9!&?3^Lb@zE{%#`Y$0vnokRsXeeur8&O*-*+EeS zE9w-k3vHLIHjzaevJxh?O&gmCBMVg0wroH*59-97I|(mVZ%|kg*Vt~`l8I!8u2GF} zkHm;95hTWroiCFRRA|Kl7fDDO0>xc%Nh)Ndml<7w@bxbKjKS-l>M<%3Me1E(ljJ1n zjMUr!-wDXJd_$A*9b?zCf%)_<=zxUyMM!mB2$Jrm5EydH35L63D*%$8^dZV2a}5}v ze#Mj8Xb>Sl<;Y4R8)0xsmP|*M8oNn0ydWFtKZ9$W-okO?pGW~Rw@2{6QG^e@_mPK> z8Ft_k51)Eyd06wX?%^{J8y+@2v^{Kj*!J+y!;XhX9zOT*g@-Rae8odUCT4~tv%f=T zSF#3;#wu)Y(MbA`$r_~KDzs*yB%=q3LQNN93%6+JLb@E~ssz8%WEfmIH0J8kp$lY( z*3jf3O`hbvAQo-;m^MzfT_xJhC!PSO{8m2pTiKc4$|two%D3PKFLHzTpWDxp*Y5wi zpTEj$&u8mj9#2C`(c`(q(1vC2-ShAs!w$Uf;e(6E#bkyK8hUE@?55dYX+(bD$@LaT z4M&j%nnN_{W;W@jE$KAiNvAxYTTNGvevBXV2Y%3Te$bn@9rV`RoWHq#mf|&C=!L>B z7J7~Gflti>9|=b6?Ldth5VHnETasSffK#t6SC~7AVQU$!bLZ}o@4?LXuyWfTaIOda zZ9*?lt-b*RU@JPN?<yP}(;IO~>-kS6i#i<S<Ff*6Q^%JdQnsao!_f%rh7O+hz6ZOl OONWDeaQa=^um25r&X_#_ literal 1875 zcmds2&2HO95T4y7sh_3ewPOTsQM4<eDC8h%WYs^4-L&2Sx%b=)O<S}>+9CysPU0S_ z9QqJN-XVQ~9@<OaBahHW=**5KyG381B_MwDeY3M1?ab~%IvWcB5Ie17HJ{JnIKcN@ z%#Q`yq<9lwa_I!J#gE4T@>kJPS^4T-_NGowF4K!_kPLSB07zUXF&hnbcekG=ud-== zb`63YO>&$~vkWBBkBFXUb&_6QR;Ov5jgnbiP1ExX6#3iaAA2VRB(zAFO!KmakoYR` z8BVYWi%5-0tzTDflI_8eGrE;H$yhgTo@O9}KuiE96tLF#O~lbS8&}h732~jx>SUDG zX_A-FTJtm;PwMMrn$=g+654IAP0}(y1^vL2)2bZhbzYU}Wx|el)jRI2(#ncge2$dR zy*r$8UcK-A|5!q^Hod}xPO|g7Os>k;c{zf$=w^M^1HZ2KTLRke+WHqE<lKRSo(!D1 z=&C)$4W~`$tP3qzVItRa4HH`BU{A)b?-ZJGVN^$2)st~Y+yv~PNBV%FYnf0UVOY== zFII3C7Zna3!}<Xb36MMy=Fk)Tbc_vQrJ-PH!AJ-A2~%J$R=j`y7N0-ir&SH04ag(w zr^I3UIcS9<{eD&=T>g;{aM6t@I>Ma65*)(k%)Vgukl_)*0es2ugrU!{%`jm2ieZOg zmtl`#pJB-Gl;MEkkl|~FXAIvkd~0zv(6ogCgx{fXn?)CuEg0_0g=C7ZB&mNZHH)qy zsploK>^?3`MB%t*TM~FIhK5!yDTZOq78Jwe5st$`*=3<fgnghYZ5B3I5>wc4Nty*u zO2d{Fi`)meTe7zSm+Ze@ndbktGJgmu@t9t0|2}VjztO=E9Kr^(2h2WZ_=Mm9K4tjK zH!<y3(?G=*4%<U*!Dct0CR9kV>)0mUkZ!H=684_C?LFU`zW4sM!<6g)t-&NW*fTo9 zV%NYtfcB6P9f|V_oLAA|gQwC9I(HPes#ScX7>;g&I*LJqjxgK=3{vawo8ST+d<O== z;XQ!Yi>)p?;5M|rdzCn=!@Qha)!=%%vAAGdU#qjK0=J{pN%{l0p>Cb!Wj=eEjXHk; DBNR#^ diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm index ac94a72cdee5c83cc5589f05510aba657675f862..df28ddb3cb77443fcc9754f7dd439848f8d3d91e 100644 GIT binary patch literal 2761 zcmd^BO>!GW6n@>)^CPunwGv|-I|V&cDN3d&kc}-n4nJyFTx3IqH5*y6#ztdnq>{%@ z%mT5XH~<Uw93Xd~asbYd1t;JHyw`18lB;0hB}i5J-cR?N@BMU-pnEo80Khg&2i{~d zfdhfR6E-<uD3isC_``3UZ~#Cm`+@(+t6rL4ETpfB&WqFTNxIS5*lGcg@g5n|-p1C} z`s2<;I_@7`0wYI6j-zp!0w?tWsmE#2>7Jer54%O$>zozCarZa{kNjow53Cc!)Q}Di z2cy{)Xc%2OgS1=H!C-hX7bG2=rG;Bkq9vnoKQF+ipf%Fbd-LpotQE2rFNd!>>l-^R zt*OanT34ZmAHgBI`Ut^BfKeIL!#|k{2I*ipzT{9JpPylw(&K*KInQ7A^Bz>mNwgQN zfC<$?v{>GDBk`>VSJ~eawrck)MT&uX-J;v+=kQM5s_9@<Tz1B3aX!vrscdbdZr(qH zcbBYkILv$fqCd>Lryb{5u35)S;~rG4#b!+Dt<30Dfz|ugf2*qxOAN}tDHVa&u7Ctt z1`V2Nu7auPPsMO5Ml!&)N;u&14P(KCx2InXMq~{Ri9ji`l6Ru{^D1ah^DK$9Fsw*I z9qI7-YV2#VUu7C_M;vI>zN&H^#9_sgc6}T<pEdYOBw>}2&x$(Gg7#?t>s7T73mqs< z@wmiv!WKuSNJjf8p#|CKh>W53GMnwfN=*XDzZm!Na2PO1Ll||E1T8LjTeB({7Na?4 z(kvRON=6%>N~OxCVM0~XfdLF@n#RM2dogmSO#G|Wn`q|9wQP1wNtJjT_lU&b$6^Eq z2_j?5&V`8(D!5{if<#yv1VLF*NDQR7E3>u%{MUQ>XYIZIDGs&3qHwtfBw{(Sbc#z# zfSv>>8+xG1=!v1tS;4G(52S~M_=RyXUkEJS?LuguQjWC0$F@Dd@?(9FvQJz+0*G&T zVj2k&0xc|Aj${MvU6V!8lEuVsll8C22J#PYj?-H>N&blxXyWz+9$AX;fzv*8@Daf- zeC*&82Tcd-4mKQo>R{8smV=gqZ3jCJ9y{1|@WjDq4nBAAg@Z3?Xi(Id!jhTaAv4Qa zf}^npJKH#t&ZM#gE4T*DsVU0vAfc&YO(f}U?3|C=HDBZ4R;o;UHwuoqxK?ljZ{r%A zJdKmbsTati#h+s1c*{n@Za#Aa$mLr3)U~ob+sbEmZRK0AgBRGr`_J{W;%fJQ?dPw2 z?tC`?<#;Nr6dq5!EAR$^C8w=8cu24d?>Tt?>bR&(;Z={PhVE{h{pBQZ1COec$g0Sy zaiGbBldh(du38*#1DbU7)4kQO;qXVfL4V{1UC$1B<F13=oSE}C^LMG9s|&tR=*2?0 z;f0UM0$mA;?e9Vj6JXN>Sc_x5C;?l&7GEarSPWCkaGkw(7hMi&HizZA=AdVCkl#l5 z0+r$$PynVPL;O>xhbQ<(T$FP5zn9U{@8_fQ0!%}O*Z&4hQ+h|kA(&0+z36@qW=EEe M`g#BCyR;Yo4W!PteE<Le literal 2029 zcmds2&2k$>5bl{-t$t=5jU8j0K*2~wQF1B}S@=h>33yVKd(K?eYin$F?cG&LYbWM_ zeBdE?33vuB@Eket06YTSGq$8qyZ~&K^!4}kbnonR&kQ8foB;saX&#H&YzD^x{?FL# zn4wLIGx3kloj^AG@fd*L@)co=>j(C26`x!t7j_U2cJ}~CTqDtr2D`i4&*N)5NzZP8 zk)uJ5vx&99i9RBFZmT%Cyev<X%8ue`RZfy~3xfPD^5@P8!9uY4X+B;afx`I43(|$y zJTI@`OJeh>t^ANC4H-|;qJkPFZ4*cD{M{j`5vkRi@@>3582ZmzNd8MzyMFgH1U>-| z0yYLr%3!trCsSc=^Kx>-A*$@OibqM6#AyL5tB%@yT;0SITU|{Gc+hg%I4ROoXm2=j zS{9?UO3Na-jJ-p(onvXaS67_k=1G%UTjDhDhYy|qAGKItom}CBPV9MF#8<_ev>3q$ zG+SE64QJp2e^^Jwt>Y$1w0@7myJ|cRTopfRGHCtLYX8a@pBXUF<AG5ZU9pF_Zlr1& zZE6}cQ!Udob=B0uz#flG-v~6LOo<NHqQ|2Sy9?Ms4|f4W(^O4<gkeFKy;{L6Cd>?c z0c!_9BtY_vsY6Hb)e*Lz=8A&32E`5FD^!Ma(d?I(xA^=8KeZ)*RKSn4ONqneOOOIZ z`u!|eZT=ze;G!E+bck~XO>hXGdG@(yPdq#&IDjubJoC`^u<c>s;VTb29(FzKdD!<b z^zhunfrmp6Uwe4r;TsR%YFrI8b*2E}H^|Ip)<tCthWq?pQdyUi)L%%AtSd<BIf*R2 zj|&r0IIh_i2R{}=Ynsm~hGEU_DTeVQ9EXL{^Fomb`#@FN%ycj(D$}(&X=FYr4Vzai zH1A-!WVeAY*?+w<(f_tGzcbG9Qn=s#eZT$PMh8W32<x70c=p)C#{>uPiHA>J6VrZG z5*3{pY!9&oo85q#P$0#w^ET;<bghMxu=muW_grhb-uu@M6Q=)OgK^(rFX#x1OdaO| zw1*VyaLmgvub{&RPo-CM?g-ziTKFSH`RE3SqX;C(7KY<)<SJa4wS`$<m<<`?SQU8S zQhwI}6Ug8-C;$`5I$nIbyy$>gmvZ@jGFsNsVtiGB>B;*2jcNK)oRuY*9Vt$dAHWP{ N^DHgW>GyWj`5TJoZkYf8 diff --git a/substrate/wasm-runtime/test/src/lib.rs b/substrate/wasm-runtime/test/src/lib.rs index 2b9a21c17f..ed4610a4df 100644 --- a/substrate/wasm-runtime/test/src/lib.rs +++ b/substrate/wasm-runtime/test/src/lib.rs @@ -54,8 +54,6 @@ fn test_panic(_input: &[u8]) -> Vec<u8> { fn test_conditional_panic(input: &[u8]) -> Vec<u8> { if input.len() > 0 { panic!("test panic"); - } else { - assert!(input.len() > 0); } input.to_vec() } From ace1387076ceaaf96ce4c257e62f92d769d978a8 Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Sat, 27 Jan 2018 13:32:30 +0100 Subject: [PATCH 092/112] Fix everything. --- substrate/executor/src/native_executor.rs | 1 - substrate/executor/src/wasm_executor.rs | 108 ++++++++++++++---- substrate/native-runtime/support/src/lib.rs | 22 ++++ substrate/wasm-runtime/polkadot/src/lib.rs | 5 +- .../polkadot/src/runtime/system.rs | 2 + substrate/wasm-runtime/support/src/lib.rs | 71 ++++++++---- .../release/runtime_polkadot.compact.wasm | Bin 35733 -> 62452 bytes .../release/runtime_polkadot.wasm | Bin 35782 -> 62501 bytes .../release/runtime_test.compact.wasm | Bin 2636 -> 13267 bytes .../release/runtime_test.wasm | Bin 2761 -> 13392 bytes 10 files changed, 154 insertions(+), 55 deletions(-) diff --git a/substrate/executor/src/native_executor.rs b/substrate/executor/src/native_executor.rs index 79e6af2ea9..2f050f77b7 100644 --- a/substrate/executor/src/native_executor.rs +++ b/substrate/executor/src/native_executor.rs @@ -99,7 +99,6 @@ mod tests { let foreign_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm"); let r = NativeExecutor.call(&mut t, &foreign_code[..], "execute_transaction", &CallData(tx())); - println!("{:?}", r); assert!(r.is_ok()); runtime_support::with_externalities(&mut t, || { diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index 05cb5580eb..2269de51d4 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -27,6 +27,7 @@ use error::{Error, ErrorKind, Result}; use wasm_utils::{MemoryInstance, UserDefinedElements, AddModuleWithoutFullDependentInstance}; use primitives::{ed25519, blake2_256, twox_128, twox_256}; +use primitives::hexdisplay::HexDisplay; struct Heap { end: u32, @@ -151,47 +152,63 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, this.ext.chain_id() }, ext_twox_128(data: *const u8, len: u32, out: *mut u8) => { - let result = - if let Ok(value) = this.memory.get(data, len as usize) { - twox_128(&value) - } else { - [0; 16] - }; + let maybe_value = if len == 0 { + Ok(vec![]) + } else { + this.memory.get(data, len as usize) + }; + let result = if let Ok(value) = maybe_value { + twox_128(&value) + } else { + [0; 16] + }; let _ = this.memory.set(out, &result); }, ext_twox_256(data: *const u8, len: u32, out: *mut u8) => { - let result = - if let Ok(value) = this.memory.get(data, len as usize) { - twox_256(&value) - } else { - [0; 32] - }; + let maybe_value = if len == 0 { + Ok(vec![]) + } else { + this.memory.get(data, len as usize) + }; + let result = if let Ok(value) = maybe_value { + twox_256(&value) + } else { + [0; 32] + }; let _ = this.memory.set(out, &result); }, ext_blake2_256(data: *const u8, len: u32, out: *mut u8) => { - let result = - if let Ok(value) = this.memory.get(data, len as usize) { - blake2_256(&value) - } else { - [0; 32] - }; + let maybe_value = if len == 0 { + Ok(vec![]) + } else { + this.memory.get(data, len as usize) + }; + let result = if let Ok(value) = maybe_value { + blake2_256(&value) + } else { + [0; 32] + }; let _ = this.memory.set(out, &result); }, ext_ed25519_verify(msg_data: *const u8, msg_len: u32, sig_data: *const u8, pubkey_data: *const u8) -> u32 => { (||{ let mut sig = [0u8; 64]; if let Err(_) = this.memory.get_into(sig_data, &mut sig[..]) { - return 0; + return 2; }; let mut pubkey = [0u8; 32]; if let Err(_) = this.memory.get_into(pubkey_data, &mut pubkey[..]) { - return 0; + return 3; }; if let Ok(msg) = this.memory.get(msg_data, msg_len as usize) { - if ed25519::Signature::from(sig).verify(&msg, &ed25519::Public::from(pubkey)) { 1 } else { 0 } + if ed25519::Signature::from(sig).verify(&msg, &ed25519::Public::from(pubkey)) { + 0 + } else { + 5 + } } else { - 0 + 4 } })() } @@ -253,6 +270,7 @@ mod tests { use super::*; use rustc_hex::FromHex; use native_runtime::testing::TestExternalities; + use primitives::hashing::blake2_256; #[test] fn returning_should_work() { @@ -299,11 +317,11 @@ mod tests { let test_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); assert_eq!( WasmExecutor.call(&mut ext, &test_code[..], "test_blake2_256", &CallData(b"".to_vec())).unwrap(), - FromHex::from_hex("0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8").unwrap() + blake2_256(&b""[..]).to_vec() ); assert_eq!( WasmExecutor.call(&mut ext, &test_code[..], "test_blake2_256", &CallData(b"Hello world!".to_vec())).unwrap(), - FromHex::from_hex("3fbc092db9350757e2ab4f7ee9792bfcd2f5220ada5a4bc684487f60c6034369").unwrap() + blake2_256(&b"Hello world!"[..]).to_vec() ); } @@ -346,7 +364,47 @@ mod tests { calldata.extend_from_slice(sig.as_ref()); assert_eq!( WasmExecutor.call(&mut ext, &test_code[..], "test_ed25519_verify", &CallData(calldata)).unwrap(), - vec![1] + vec![0] ); } + + use primitives::twox_128; + use native_runtime::testing::{one, two}; + use native_runtime::statichex::StaticHexInto; + use native_runtime::keyedvec::KeyedVec; + use native_runtime::runtime::staking::balance; + use runtime_support; + + fn tx() -> Vec<u8> { "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000".convert() } + + #[test] + fn panic_execution_gives_error() { + let one = one(); + let mut t = TestExternalities { storage: map![ + twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0] + ], }; + + let foreign_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm"); + let r = WasmExecutor.call(&mut t, &foreign_code[..], "execute_transaction", &CallData(tx())); + assert!(r.is_err()); + } + + #[test] + fn successful_execution_gives_ok() { + let one = one(); + let two = two(); + + let mut t = TestExternalities { storage: map![ + twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + ], }; + + let foreign_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm"); + let r = WasmExecutor.call(&mut t, &foreign_code[..], "execute_transaction", &CallData(tx())); + assert!(r.is_ok()); + + runtime_support::with_externalities(&mut t, || { + assert_eq!(balance(&one), 42); + assert_eq!(balance(&two), 69); + }); + } } diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index fc5a99ac48..4d665fc0de 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -105,6 +105,28 @@ pub fn with_externalities<R, F: FnOnce() -> R>(ext: &mut Externalities, f: F) -> ext::using(ext, f) } +pub trait Printable { + fn print(self); +} + +impl<'a> Printable for &'a [u8] { + fn print(self) { + if let Ok(s) = ::std::str::from_utf8(self) { + println!("Runtime: {}", s); + } + } +} + +impl Printable for u64 { + fn print(self) { + println!("Runtime: {}", self); + } +} + +pub fn print<T: Printable + Sized>(value: T) { + value.print(); +} + #[macro_export] macro_rules! impl_stubs { ($( $name:ident ),*) => {} diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index c03fcc83c5..c23622cec8 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -47,12 +47,9 @@ pub fn execute_block(input: &[u8]) -> Vec<u8> { /// Execute a given, serialised, transaction. Returns the empty vector. pub fn execute_transaction(input: &[u8]) -> Vec<u8> { - if input.len() == 0 { - panic!("no transaction data given!"); - } let utx = UncheckedTransaction::from_slice(input).unwrap(); runtime::system::execute_transaction(&utx); - input.to_vec()//Vec::new() + Vec::new() } impl_stubs!(execute_block, execute_transaction); diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 042d1af2d7..2749c3ad9f 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -20,6 +20,7 @@ use primitives::{Block, BlockNumber, Hash, UncheckedTransaction, TxOrder, Hashable}; use runtime_support::mem; use runtime_support::prelude::*; +use runtime_support::print; use storable::Storable; use keyedvec::KeyedVec; use environment::with_env; @@ -84,6 +85,7 @@ pub fn execute_block(mut block: Block) { /// Execute a given transaction. pub fn execute_transaction(utx: &UncheckedTransaction) { + print(&b"HERE"[..]); // Verify the signature is good. assert!(utx.ed25519_verify(), "All transactions should be properly signed"); diff --git a/substrate/wasm-runtime/support/src/lib.rs b/substrate/wasm-runtime/support/src/lib.rs index 1f71973c18..454ba8507f 100644 --- a/substrate/wasm-runtime/support/src/lib.rs +++ b/substrate/wasm-runtime/support/src/lib.rs @@ -1,9 +1,9 @@ #![no_std] #![feature(lang_items)] +#![feature(core_intrinsics)] #![feature(alloc)] #![cfg_attr(feature = "strict", deny(warnings))] -#![feature(alloc)] extern crate alloc; pub use alloc::vec; @@ -26,8 +26,13 @@ extern crate pwasm_alloc; #[lang = "panic_fmt"] #[no_mangle] -pub fn panic_fmt() -> ! { - loop {} +pub extern fn panic_fmt(_fmt: ::core::fmt::Arguments, _file: &'static str, _line: u32, _col: u32) { + unsafe { + ext_print(_file.as_ptr() as *const u8, _file.len() as u32); + ext_print_num(_line as u64); + ext_print_num(_col as u64); + ::core::intrinsics::abort() + } } extern "C" { @@ -46,7 +51,7 @@ extern "C" { pub fn storage(key: &[u8]) -> Vec<u8> { let mut length: u32 = 0; unsafe { - let ptr = ext_get_allocated_storage(&key[0], key.len() as u32, &mut length); + let ptr = ext_get_allocated_storage(key.as_ptr(), key.len() as u32, &mut length); Vec::from_raw_parts(ptr, length as usize, length as usize) } } @@ -54,15 +59,15 @@ pub fn storage(key: &[u8]) -> Vec<u8> { pub fn set_storage(key: &[u8], value: &[u8]) { unsafe { ext_set_storage( - &key[0] as *const u8, key.len() as u32, - &value[0] as *const u8, value.len() as u32 + key.as_ptr(), key.len() as u32, + value.as_ptr(), value.len() as u32 ); } } pub fn read_storage(key: &[u8], value_out: &mut [u8], value_offset: usize) -> usize { unsafe { - ext_get_storage_into(&key[0], key.len() as u32, &mut value_out[0], value_out.len() as u32, value_offset as u32) as usize + ext_get_storage_into(key.as_ptr(), key.len() as u32, value_out.as_mut_ptr(), value_out.len() as u32, value_offset as u32) as usize } } @@ -72,41 +77,61 @@ pub fn chain_id() -> u64 { ext_chain_id() } } +/* +trait AsPtr { + fn ptr(self) -> *const u8; +} +impl<'a> AsPtr for &'a[u8] { + fn ptr(self) -> *const u8 { + if self.len() > 0 { &self[0] } else { 0 as *const u8 } + } +} + +trait AsPtrMut { + fn ptr(self) -> *mut u8; +} + +impl<'a> AsPtrMut for &'a mut [u8] { + fn ptr(self) -> *mut u8 { + if self.len() > 0 { &mut self[0] } else { 0 as *mut u8 } + } +} +*/ /// Conduct a 256-bit Blake2 hash. pub fn blake2_256(data: &[u8]) -> [u8; 32] { + let mut result: [u8; 32] = Default::default(); + // guaranteed to write into result. unsafe { - let mut result: [u8; 32] = Default::default(); - // guaranteed to write into result. - ext_blake2_256(&data[0], data.len() as u32, &mut result[0]); - result + ext_blake2_256(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); } + result } /// Conduct four XX hashes to give a 256-bit result. pub fn twox_256(data: &[u8]) -> [u8; 32] { + let mut result: [u8; 32] = Default::default(); + // guaranteed to write into result. unsafe { - let mut result: [u8; 32] = Default::default(); - // guaranteed to write into result. - ext_twox_256(&data[0], data.len() as u32, &mut result[0]); - result + ext_twox_256(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); } + result } /// Conduct two XX hashes to give a 256-bit result. pub fn twox_128(data: &[u8]) -> [u8; 16] { + let mut result: [u8; 16] = Default::default(); + // guaranteed to write into result. unsafe { - let mut result: [u8; 16] = Default::default(); - // guaranteed to write into result. - ext_twox_128(&data[0], data.len() as u32, &mut result[0]); - result + ext_twox_128(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); } + result } /// Verify a ed25519 signature. pub fn ed25519_verify(sig: &[u8], msg: &[u8], pubkey: &[u8]) -> bool { sig.len() != 64 || pubkey.len() != 32 || unsafe { - ext_ed25519_verify(&msg[0], msg.len() as u32, &sig[0], &pubkey[0]) + ext_ed25519_verify(msg.as_ptr(), msg.len() as u32, sig.as_ptr(), pubkey.as_ptr()) } == 0 } @@ -150,11 +175,7 @@ macro_rules! impl_stubs { let output = super::$name(&input[..]); // things break if we try to take the address of an unallocated vec, so we // shortcircuit the empty output case. - if output.len() > 0 { - &output[0] as *const u8 as u64 + ((output.len() as u64) << 32) - } else { - 0 - } + output.as_ptr() as u64 + ((output.len() as u64) << 32) } )* } diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm index 68996e2c265a309cb12b729f9efa2a0bb60446fe..9a03a7370dd7065dabd446cf62100aedc0d9174e 100644 GIT binary patch literal 62452 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 MbllKe`imjG1GjV$TmS$7 literal 35733 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 Prbwvdb20JA*>C-SC8Tc% diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm index 0deae851a2fec60989afbea7ea9a82b08a91e75b..7c56e0c5d704d047142983e80a0f8ff8c5244eea 100644 GIT binary patch literal 62501 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 literal 35782 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 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm index d5026fc30a19ae56a1276d158a96eb4394780526..2e00c051fdd10385e19eaa7b26a7826ac331266a 100644 GIT binary patch literal 13267 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 Ang9R* literal 2636 zcmd^B-EJF26h1RM`(uwCPudWL7QwMqAqOFFLgJ(;Kc1)&y{XDIH;x-`f;aKnayD(l z1?B?r09^1EeFjjk5zo+P;0ZWqCW)O$aFI($B!A~;_Uw1QIXk=1I~@uD5F4faU^<<` zzM|i$nC=U*IpR$EkylCB2VhtHApa2MAkAMaq_2wZ^ON3jy53#iYy)uc4hPfz`sU`^ z!|sc8GB`X3!HI+uhm$k~$?m)C9;HRMcXBd1=oM+dds>Vpy`vNY&X+kqbV*RNKsr1a zpZgUhUNN2w@&ZC$P-Fj;Dqhx!I9lOo@pAO4ySBdVDb7Nk^+Gicl!WBsPbo15Dk)$w z{!LV(VLBX5&Lu2P&Q7V{^k|TG&+?apybtB*f?-9u&Z?Cnr8WIt(d!O!s4Y4-9gd6h z?j$YFCOMe0i;a8v-~bkvopUhC`-5UI%6lhWpSV+Vi8*oaR$at(!nBv>eD3U>yDoo2 z`Q?&;@{gvPK+vgx23-aO6evxoBQlNhAoUv|qN(i6{t>Loni3j{ti)NtG0JCEzyM{| zNKjc(G-6CJes;eeqS~tp1iGRgA$ea{B}VnQ5@@%+p7@*#ghn;us^FY6F+#=HVEFXD z(RGE9kz7w|VjH(5F(on>l0^|>g9!&?3^Lb@zE{%#`Y$0vnokRsXeeur8&O*-*+EeS zE9w-k3vHLIHjzaevJxh?O&gmCBMVg0wroH*59-97I|(mVZ%|kg*Vt~`l8I!8u2GF} zkHm;95hTWroiCFRRA|Kl7fDDO0>xc%Nh)Ndml<7w@bxbKjKS-l>M<%3Me1E(ljJ1n zjMUr!-wDXJd_$A*9b?zCf%)_<=zxUyMM!mB2$Jrm5EydH35L63D*%$8^dZV2a}5}v ze#Mj8Xb>Sl<;Y4R8)0xsmP|*M8oNn0ydWFtKZ9$W-okO?pGW~Rw@2{6QG^e@_mPK> z8Ft_k51)Eyd06wX?%^{J8y+@2v^{Kj*!J+y!;XhX9zOT*g@-Rae8odUCT4~tv%f=T zSF#3;#wu)Y(MbA`$r_~KDzs*yB%=q3LQNN93%6+JLb@E~ssz8%WEfmIH0J8kp$lY( z*3jf3O`hbvAQo-;m^MzfT_xJhC!PSO{8m2pTiKc4$|two%D3PKFLHzTpWDxp*Y5wi zpTEj$&u8mj9#2C`(c`(q(1vC2-ShAs!w$Uf;e(6E#bkyK8hUE@?55dYX+(bD$@LaT z4M&j%nnN_{W;W@jE$KAiNvAxYTTNGvevBXV2Y%3Te$bn@9rV`RoWHq#mf|&C=!L>B z7J7~Gflti>9|=b6?Ldth5VHnETasSffK#t6SC~7AVQU$!bLZ}o@4?LXuyWfTaIOda zZ9*?lt-b*RU@JPN?<yP}(;IO~>-kS6i#i<S<Ff*6Q^%JdQnsao!_f%rh7O+hz6ZOl OONWDeaQa=^um25r&X_#_ diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm index df28ddb3cb77443fcc9754f7dd439848f8d3d91e..e8be4d6d0ce19d2b34d164dca436042974ab6d33 100644 GIT binary patch literal 13392 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 literal 2761 zcmd^BO>!GW6n@>)^CPunwGv|-I|V&cDN3d&kc}-n4nJyFTx3IqH5*y6#ztdnq>{%@ z%mT5XH~<Uw93Xd~asbYd1t;JHyw`18lB;0hB}i5J-cR?N@BMU-pnEo80Khg&2i{~d zfdhfR6E-<uD3isC_``3UZ~#Cm`+@(+t6rL4ETpfB&WqFTNxIS5*lGcg@g5n|-p1C} z`s2<;I_@7`0wYI6j-zp!0w?tWsmE#2>7Jer54%O$>zozCarZa{kNjow53Cc!)Q}Di z2cy{)Xc%2OgS1=H!C-hX7bG2=rG;Bkq9vnoKQF+ipf%Fbd-LpotQE2rFNd!>>l-^R zt*OanT34ZmAHgBI`Ut^BfKeIL!#|k{2I*ipzT{9JpPylw(&K*KInQ7A^Bz>mNwgQN zfC<$?v{>GDBk`>VSJ~eawrck)MT&uX-J;v+=kQM5s_9@<Tz1B3aX!vrscdbdZr(qH zcbBYkILv$fqCd>Lryb{5u35)S;~rG4#b!+Dt<30Dfz|ugf2*qxOAN}tDHVa&u7Ctt z1`V2Nu7auPPsMO5Ml!&)N;u&14P(KCx2InXMq~{Ri9ji`l6Ru{^D1ah^DK$9Fsw*I z9qI7-YV2#VUu7C_M;vI>zN&H^#9_sgc6}T<pEdYOBw>}2&x$(Gg7#?t>s7T73mqs< z@wmiv!WKuSNJjf8p#|CKh>W53GMnwfN=*XDzZm!Na2PO1Ll||E1T8LjTeB({7Na?4 z(kvRON=6%>N~OxCVM0~XfdLF@n#RM2dogmSO#G|Wn`q|9wQP1wNtJjT_lU&b$6^Eq z2_j?5&V`8(D!5{if<#yv1VLF*NDQR7E3>u%{MUQ>XYIZIDGs&3qHwtfBw{(Sbc#z# zfSv>>8+xG1=!v1tS;4G(52S~M_=RyXUkEJS?LuguQjWC0$F@Dd@?(9FvQJz+0*G&T zVj2k&0xc|Aj${MvU6V!8lEuVsll8C22J#PYj?-H>N&blxXyWz+9$AX;fzv*8@Daf- zeC*&82Tcd-4mKQo>R{8smV=gqZ3jCJ9y{1|@WjDq4nBAAg@Z3?Xi(Id!jhTaAv4Qa zf}^npJKH#t&ZM#gE4T*DsVU0vAfc&YO(f}U?3|C=HDBZ4R;o;UHwuoqxK?ljZ{r%A zJdKmbsTati#h+s1c*{n@Za#Aa$mLr3)U~ob+sbEmZRK0AgBRGr`_J{W;%fJQ?dPw2 z?tC`?<#;Nr6dq5!EAR$^C8w=8cu24d?>Tt?>bR&(;Z={PhVE{h{pBQZ1COec$g0Sy zaiGbBldh(du38*#1DbU7)4kQO;qXVfL4V{1UC$1B<F13=oSE}C^LMG9s|&tR=*2?0 z;f0UM0$mA;?e9Vj6JXN>Sc_x5C;?l&7GEarSPWCkaGkw(7hMi&HizZA=AdVCkl#l5 z0+r$$PynVPL;O>xhbQ<(T$FP5zn9U{@8_fQ0!%}O*Z&4hQ+h|kA(&0+z36@qW=EEe M`g#BCyR;Yo4W!PteE<Le From d97520c7f047231dc92e34802e12911097de2813 Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Sat, 27 Jan 2018 13:42:40 +0100 Subject: [PATCH 093/112] Introduce hex/string printing in runtime. --- substrate/executor/src/wasm_executor.rs | 7 ++++++- substrate/native-runtime/support/src/lib.rs | 11 ++++++++--- substrate/primitives/src/hexdisplay.rs | 4 ++++ .../polkadot/src/runtime/system.rs | 1 - substrate/wasm-runtime/support/src/lib.rs | 15 ++++++++++++--- .../release/runtime_polkadot.compact.wasm | Bin 62452 -> 62459 bytes .../release/runtime_polkadot.wasm | Bin 62501 -> 62508 bytes .../release/runtime_test.compact.wasm | Bin 13267 -> 13280 bytes .../release/runtime_test.wasm | Bin 13392 -> 13405 bytes substrate/wasm-runtime/test/src/lib.rs | 8 ++++---- 10 files changed, 34 insertions(+), 12 deletions(-) diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index 2269de51d4..8a70271c1a 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -78,13 +78,18 @@ impl WritePrimitive<u32> for MemoryInstance { } impl_function_executor!(this: FunctionExecutor<'e, E>, - ext_print(utf8_data: *const u8, utf8_len: u32) => { + ext_print_utf8(utf8_data: *const u8, utf8_len: u32) => { if let Ok(utf8) = this.memory.get(utf8_data, utf8_len as usize) { if let Ok(message) = String::from_utf8(utf8) { println!("Runtime: {}", message); } } }, + ext_print_hex(data: *const u8, len: u32) => { + if let Ok(hex) = this.memory.get(data, len as usize) { + println!("Runtime: {}", HexDisplay::from(&hex)); + } + }, ext_print_num(number: u64) => { println!("Runtime: {}", number); }, diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/support/src/lib.rs index 4d665fc0de..fb74093d18 100644 --- a/substrate/native-runtime/support/src/lib.rs +++ b/substrate/native-runtime/support/src/lib.rs @@ -40,6 +40,7 @@ pub mod prelude { } pub use polkadot_state_machine::{Externalities, ExternalitiesError}; +use primitives::hexdisplay::HexDisplay; // TODO: use the real error, not NoError. @@ -111,9 +112,13 @@ pub trait Printable { impl<'a> Printable for &'a [u8] { fn print(self) { - if let Ok(s) = ::std::str::from_utf8(self) { - println!("Runtime: {}", s); - } + println!("Runtime: {}", HexDisplay::from(&self)); + } +} + +impl<'a> Printable for &'a str { + fn print(self) { + println!("Runtime: {}", self); } } diff --git a/substrate/primitives/src/hexdisplay.rs b/substrate/primitives/src/hexdisplay.rs index d6299a2e41..fa62d69869 100644 --- a/substrate/primitives/src/hexdisplay.rs +++ b/substrate/primitives/src/hexdisplay.rs @@ -39,6 +39,10 @@ pub trait AsBytesRef { fn as_bytes_ref(&self) -> &[u8]; } +impl<'a> AsBytesRef for &'a [u8] { + fn as_bytes_ref(&self) -> &[u8] { self } +} + impl AsBytesRef for [u8] { fn as_bytes_ref(&self) -> &[u8] { &self } } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 2749c3ad9f..b3d4640e78 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -85,7 +85,6 @@ pub fn execute_block(mut block: Block) { /// Execute a given transaction. pub fn execute_transaction(utx: &UncheckedTransaction) { - print(&b"HERE"[..]); // Verify the signature is good. assert!(utx.ed25519_verify(), "All transactions should be properly signed"); diff --git a/substrate/wasm-runtime/support/src/lib.rs b/substrate/wasm-runtime/support/src/lib.rs index 454ba8507f..d506e193cd 100644 --- a/substrate/wasm-runtime/support/src/lib.rs +++ b/substrate/wasm-runtime/support/src/lib.rs @@ -28,7 +28,7 @@ extern crate pwasm_alloc; #[no_mangle] pub extern fn panic_fmt(_fmt: ::core::fmt::Arguments, _file: &'static str, _line: u32, _col: u32) { unsafe { - ext_print(_file.as_ptr() as *const u8, _file.len() as u32); + ext_print_utf8(_file.as_ptr() as *const u8, _file.len() as u32); ext_print_num(_line as u64); ext_print_num(_col as u64); ::core::intrinsics::abort() @@ -36,7 +36,8 @@ pub extern fn panic_fmt(_fmt: ::core::fmt::Arguments, _file: &'static str, _line } extern "C" { - fn ext_print(utf8_data: *const u8, utf8_len: u32); + fn ext_print_utf8(utf8_data: *const u8, utf8_len: u32); + fn ext_print_hex(data: *const u8, len: u32); fn ext_print_num(value: u64); fn ext_set_storage(key_data: *const u8, key_len: u32, value_data: *const u8, value_len: u32); fn ext_get_allocated_storage(key_data: *const u8, key_len: u32, written_out: *mut u32) -> *mut u8; @@ -142,7 +143,15 @@ pub trait Printable { impl<'a> Printable for &'a [u8] { fn print(self) { unsafe { - ext_print(self.as_ptr(), self.len() as u32); + ext_print_hex(self.as_ptr(), self.len() as u32); + } + } +} + +impl<'a> Printable for &'a str { + fn print(self) { + unsafe { + ext_print_utf8(self.as_ptr() as *const u8, self.len() as u32); } } } diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm index 9a03a7370dd7065dabd446cf62100aedc0d9174e..9bf101d73fd663a6ed67a0af89597d6b7273e4cd 100644 GIT binary patch delta 14524 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 R%Wm|ijyK{sp6a4=`9BfYJHh|} delta 14659 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 Z!kBCKp1B~5@oT-my^uDht_7nP|1am9UEBZw diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm index 7c56e0c5d704d047142983e80a0f8ff8c5244eea..6cbc2ef9b954b61a94ec459c330f44ab9975f50d 100644 GIT binary patch delta 14568 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 delta 14662 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 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm index 2e00c051fdd10385e19eaa7b26a7826ac331266a..6005dbbca5a96f2ab601b89eb12eead782c3a7c6 100644 GIT binary patch delta 1918 zcmZuyUuaWT7(eISo7^O)Np2h4rm3~3PF-qh6780CY(o!B+d09(7~9yNHcfBp?b4(s zw^oPDyWv0>jFi)f10V9x2Okt7aW6iMz&emAC9uGRZIFiw4h4(zK^@4xdt+M#FP!_k z=lg!&-}Bvjf1hkj7UK&33XPFdr{-Vl!MEl=`1U2QcH9`9$?I8TG&?(uoRXG3=G&0X z8tI|=hX>t?3%iLTD~fm*|I_{Va8C#^947WnRux7rsZJ)rO&lhLt}>pAVe|$<%*9Vm zF*jd9S&j`}7JriWaaqKqVYtsp{}NLY8TqsY_vP;aD&IKziG`PxHr!J7^L}1bd71F4 zxbEun7Tb9rZ?yBXn46uIN3JI>xh#Y3zt$&#n{t8-F*igDPbJ6*U{$mPUdKz~K;Uz= z?nsb0$bj?;zyon55F@9R%B{dMRxc_|C2%ZdUHsA>bDeRkU5N4p@wol6e}yK<A?D$A zz!APEu68^kXMEzP&LIo#b$&-opEwyDvfy54ySN_g#jD~@aH;o##0Yb%L2y-+)DVCv zL6*dpK;6q-+Xow=1aUFMH&1b#fTkh~HZ@@Y;2}f}GE44)(!zkNVn=8TJ}>r%_J<a| z38FHIlLTpD5<JL2Vt}>EVrUP>3*wLNsm>;gG+BfJnK1&@eY813?s~=J?&08zDRrOt zc=JxYQt|gBF}^L1Zn@)G3R#sPL{~++cl$8oR8{x@cR-F<b@3|V3JislBdCU7LtJ7` zRq7+m2_w@d@h1O<B_~V*gBs#)RT0a*KN1rQou%=)N{#Jvocgu<9mHiSm%J)MyoD;s zOorvY=tG=QTF{Kqf|1K7CpE+es6)@r%o+%yQ)OLz4N)nb%OQRP9>$YjB8WxZX+5hK zj%X9$r-7))&<X~dNoMsFbQV#+wT~6@so4IEJ|4{%5H~Rmjv<6Rux4QSVGY6}un<4@ z0__keBwJe+wH?bTQ=)1WBh&`6y)r_rwyr4AU<0HP*s0*mk{*VAyRE(OjLjg}gl%b6 zqHT~@Dwo${>1iW2otv<8YzQ2Vzg?7R>zXz<W9Yf8tt`vb@kulq{S5je(_j_6!TF)G z1ECH;1_)uHmYXuoh@PF9y@)S4s9FM|mGUJQLT;N-cTi>m-3PlOAP`Uq5Dw@WHxC5s zKbtzOY<Rc~9)JcR78Dwc!=qL77~u0oUsPy#Exj5z-(lGR3(S!U=mcbd&2;OcYv<K{ zXWScceqN7La&I)MVC2^uRdrK3e!|e0o}JK+GZ+aGh(xxU9_nIYOHlw>(L<g6ESF|u zh?hJR1C+&BB#s+mKGN~3NvUsKo7A)H&9|7AonT=wp;WfEU_hzb&*qM3SyssCDLp%B zxhadkBHi&Cr6d|f@F}6{D%4?JHNfU5ty1cG&nnTn;Kirg;4rowK>U0QRpX$rn)L$= zmTk$)EiXLn8j#0;%z$hHS|<pjF6IZe?=ii!jg8M5%s8^v0o^Ki!An)9H2WI|+-ln_ zdg%ycFaqOn7YGOxn?TXJo`LD3o7U#ds#RNWbIC`YYaK3&+^&~Dt^25If(L8jN`PKF z#0p5){B~~m_0ta9-_uhn7|Fa*U`Yc~E%~X}E&&?<R8$uCcYTP9m4nd)#?{K#u|pUa z#d3TY&Z}ehc>=$SE4!yLyWK^DR$OcL;(*W3o*5F!NDTf>M+Z9&ErsBne@Za{17PwS woKo{OXoP5MDmjx(>Bb3`JErB+ncN(FD7t9?+5w-bTq>4N&W#?^Qt$%)4<1~s)&Kwi delta 1800 zcmZuxU2IcT96#sW+uPfowYyvQ(RIMiB*R<A+74!&QNm7)*+deTsNuoD=(^j{v9+bW z3^2siWJVGR={%EQLQG$MASre)VxlAI!{P&}fkcRy^nnLZA8sOv@F4iVcW#qtlXHLl ze}A6Sn7%b#in+<c0y>62TzYvsZY;g`@eYr1#+=CI(-{*fl98GBZPF8&Q*%py9rP$F z_7Fu@6fuq;cHbS{9zqQ3#QDgY!pK$4%_R7UcS)hEjAx=4y^0W1`MDY9;rCI7W0RLf zgS>;wVn`Z=?>XrYVi9ptUbNv)`658|6IYnn__ezgH<g=tm=`r(A-p2$YOk-@&U<;i zonOM->Zm?dpQ>_M=9SM{p9a?CI2mRh2&T`($rxZov;<zkE8?xdQLW~RlNj(oX$auH z_$Ck~kCf`Kfty&n;$9bmjxDT-wf3m`Sk<}^<%{B3`?coVG)@jNFRuZP@n!LS#}o3{ zC$4u6+wiFKQ)2nVN5Nqmz6}oHhOmOQp34#=%%cUtO;OT902a`UI2<VXR#zXcizi(@ zfd}9>$PhzZh2(X>hUgFNz!${9&>MJJltMwgTKy`t7vn{7uY0C**%v1oBb>xZ69fTZ zKrM<R+xp2ppLo_i8vK8inqM5<wj1BBwrx*fd`Hah_|3Z#vXeuI{w_}R^u6B3sitto zU62sgRIYP3OjzM4P7sfAi7A@YOPB)V@0Iwv_7JcMlR$fzdo)G-)bj<gkjS$XK3~1d zMqCRwy5B@xrgF)rA;g=gJ25-UvL|{GZ=<wem=gsvn@>y|h%@R+XL6@Z#C7W4<i@C! z%4QKCqS9pI1H^}^CzZ~m3&)Kq@KHz9YZ?WU<r0~6655AovrR_}`DAo9JsIKo0^$~; z!EuC;7tS#_&2aX?A#e~skN+zj27%;A%i@<^H<K2jS_LE23cLd{LM@K0DA8aYxcxQ- z&TQ`6K({;6%hHz3KCsapZbhQ4kXSOCH=?OIGdh=@ir6{Ug<p^1qBx*;>@LgH^?oE0 zIf8garojpr!<bOng-{2e1_)6g^)<1epWMIVqFM=b?BuSh2zeY?%|%%bH2pvo0YL$k z0AURO@^D`agfFEYDO(<{fd^0n?~864WboH6ZyfOX@~*h4zLD7~INt?Y79f~A4itc` zOlxksB4Xhsaeeo$k;m#*xbHT@l{{OWDVX`q&Qv^<PM$Rlmd;EWXBgtEg7x?Bv^-R0 zx-BRGujr*pm}OJ!7~&-_#Q<fmXx5{o?iC|?`%9LW`X`O)bcVgQpBb4crh^fsvQ2^s zrCOMsK5k@KVK$viXQpjOW%01TdtjAP5{V#q1gO?<I)l(E;QID7C{;)7TJ0ZyAO`n@ zJ1;a*jRDVY*ypfDjuCh}xu>IZ6=dTeV<5``+C#Ia|K*;(y;c)#Ws|2&W**<DHf<NT z=%bqEM#v7s0AFxymVI<g42H)JAbt-NEReQ=pk*_l<)dvIt7cbaY__!Ir^-e*;XxjF zF;eqWEeEdc{VD<aoDjExyWzKU%dcPjI1p+pHB+CHEp)TM5+)>C7S9F_<6`x2B#v>V zdNFzk!%F`g8-@37=in6rkN1tiIn3^K(V*3|zF7=HJ-=C2movC>$R6CGl@MIde{^zy z0m$qJ=>7VZ*F&@=naCxQY4a@0&KvpEZ1yzV_z(?1>G0NMlhJ(Q^u)Z8glqOUpbC|Z diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm index e8be4d6d0ce19d2b34d164dca436042974ab6d33..45e9c3bf2327d92d207a100b1838c1f97ef1fb4e 100644 GIT binary patch delta 1809 zcmZuxU2IcT96#sYcDJ`@?JoN)9b=~=&~Bsc29B9X*m)qE0iuZ-HAc6tyJekQJKDPq zd|)?*2aLv)oJk<Tq$GPF5n@Sw@kJY*kr+buum@gDY9t0D(IxT#FVo-c+y;p^Ip=rI z|NHBnm5HAx3UQ5|BcsZ~!o|ZK^vcCIzTV?A&sZZfxpc-F$;?iZI@Qd~`L}7aR%$@@ z(3866p}L~EG_Cw0_0#tCAs!^0hLzgpGQ3>5Y3N+VCcjV?X-N*MZP?#ZU&DSw9m4)d z{adkB`Mc}916lW{fbu`?h~i+Er;*l|8bm}C3{g@<MGosBU!g^WM72d+qQY(~&*|$P zSIGt5na1^|d#-+Efa_cr;mLkw7+8@XHN8le<@ZhR8LRGoB@P;d4gns?-sYHcUMr6^ z-=)S4ZG#CJhq)>TTVtLJy3t9PSd{avw;JxVe&q!BidEpSSdxd^o+uamvM(^;z*OL4 z#rDf5xB(9CJVe*z#Lnf;>nc~cZtRAcf@*Mpts+9DMnTTUgL`RJo(^{QJ%-%?C!7cm zf)4}NK!FNQPC6X;{G_1$C@>Mmq_`@-3mywD`5YltDE&%3S8;IFWL2?J4z>4Dx+q`Y zHA$D`x4T-DMW0M`bkT>Bb_{Qj=&Bs;=%)9}pL8TBeIWnb{fBos=)_3~Ta&+b?j7QS z8D7yN+=zr4OjL-_(A+vf5Q(@=gv#p-HKg!5v_7PY4f#6`UEwMeR*29IuRPALC^nV9 z@f5vWJ{cNxFZ|H{G7&E3D*6mUL_O0IQ&T+qeuxOpSl+Zo@>VvNIAs#i!`$i2%&bM= zooQR-+k~m9Y?g>SIE*DeAn?WXR63K+PnhGdQzgu6nR$!PBr@qFDoR*`bC2b7$=I=} z^jI{PC&H#IFiHsVV$EPRU>(F#u!y+)KimN@)Ec)WPwu~)v{hzQC?SoY9d!}1qsA+! zEKmit8#e>S9O^5$x74`TpVB!9op6m>QCTD6N@jCrEH!P#rnBR<7_0JJI8F=l%W!K~ z$;I67M5EDnQ4SXiRG^G@k&>H`Rv-t$3qrpq{|cWzvg~F?5i(A2H$8;tHQuV5aT}6; z+zLPlkRlMRc*?>f`FZ40>b$mX;T9}F4AvJl7Kr2Mq&EtDHoY4f3vWiY0^|D}9Y{f) z7{EFp2W~{Vs<E$RF>+CMb?+Ozpl`eTX3Jes->yvF%57DqqBAyj)-riIGj5*Ym;qVn z?%rd2nTLlRMjo_+m(@jhHpNGYD0&$Ml)Q2w98;=ZSqitjU^C_)Gf$;6{G}t@%#8Ce zlo)e4SEw*%MELxKnc?}VbTXYe<rpf-w|m+TtT3iTqXh2)GuDuh^Q{0kre}>Y&#O+Z z&L<wrYdw*+tM$x?gXR?MGmKG93D$n;X>D5pZxlQZo(*)GhB=o01AF^yA8X`evlh1| zHnUAT$u0Vr!L^N&#(~e(be4Q<SYC?^A0^@;1PB<-VC>j(X!}|7=BPPYnOh|-`dQs( zHB0j0f&I}{KQnAtaOSHB^wnJ42X)hK+qT^XDWbvVVgvKlqD3|HJYgZwlFUZmq=oX2 z(SAxR<@MMJijh9vJA@}t_Fh%+p!fDoQ~qEl3pg&E$%+G?oh&<8Yg{SlH15Q55I^sK zGB&UYIzOTI8&h5lvK`69Od^@K&hqS>nM+M&=kdq4vnHgD_a>W+<r4EFb7m61*}u_Q Bl5zk5 delta 1780 zcmZWpU1(ER96#sWn~$4+lU~~-P1D+*Zc|g+CQ(c5m~I|Ks$gef-y5!`X=>B8Nlb2? z+q#*D!URR)PB$EMkjK3^Qqq^bj1B^m4I~eJkj+6Kd=NJDf<EXTWdD0>+sQ7R`@8?| z&wKuyYD|^mE_U%EIYYm=c5o+My!O_QU0V8rF_tf6vIcP~>Fjy$7Cn}oo0a?Mh~{)t zjX71Pv-TzR(T;zHd6;k-VfIVaHO_A69<Ja^R@q{Eg-*vPd4&+}7W30w6L(2gP(xJY zY2^)Ck;}?3zMm)$naSjRb-@C|aTTGaI(wOgF?S1Xsx*sUQPM?~iK-mYdc388=n;*8 z_=XBISo=(S>Q*Z%%06#-+Imw>upzEtw8(UV9Y?IntF1576?wDuL%r@uusHHiX%OMA zO!#B$k+XKze~ao%t_>mTSi-tI7L2(cyY+4YVnNOamz&oh!A^3Is3RU1i}Fz06ZY6E z4~B*;I2XFiOs{;36vDYsK#sI`({(x9UhlrHaK<&g3tg2Iog<h?b7pg}?$Pir+K}hN z-L3b~cZd^Cgc}QpAg;^r!(H@>{3U#hE=q4lh_2RlckHKhLB7{HjjU5U1Ni-WXCJ%c zmGhm$8!T4$$v-;x(zV*Pok>b>%ZFWmc~-(!a6;g3d9QodQNI9P6I?hjAk{%cgbT;$ z6ePijhzo@~b)|=KC(gJ>5gXcr$YxwY?IEG*ntYRg%S<94@JV{9_IA$^$HkvJP7tAj zTK4LMh$e6)XJ&ZrqaGss0L8R1Ry1;j<k>V492}W!e$F5w0<JA?9F)mij)*}}#*?2C zF$CIVCYvcvr6<rwgMi0K7Y&|IW-}>l4}oTjjui{3*i2?TDhfp+Oah@%LWl>?89dE+ z4&Y&Uh`2=mFC9XGVoNLX{XMr*CIh`n328yzYbqf-Y*|TxPy@Mr7KP3%?kS`Lw)DEP zZF2x^A~v_GKno_8$`#VF$yp;do12JQIX2|wNSu{a`Jg{AP*K70K{OgYO+;0NP!+9l zPNd=>B#5XZVi?T*rV2B1x&I~k+uq|xiCA%fUPfgr%^Pk)G+U|e0G>w^A5tYmR3K$U z9LRrM-E}~jKJzt`A>xs9+t)JsLIVuA;DQjxPpjln#OF(1azSJ>*;Nd)8?{VCG`Af% z5w?@ByI^HA;#Wr=ySL;0v=y(cZMUmv6t>z`)d0pnG15Gfok(BcM6Am1`ubipHE{EY zB`6}V<N;?d&rR|(M3g;15h@;eB@$x|kJaaH(*wTo^w~_7A3Ds_*$Ey&BLLMR(L|2+ z2ToJ~f;>~?xjDmfHJ+QxP9SAFT?Js#D8V}b^mV&IgsdWNEY>=J`-oMt^@w}&hyLES zD@~wt<XL_D8aK=~!dviuf3R&8WuqwLD9a;SQ?wSNV_;XzY=Ra(jwu*Zn>AxjI1exA zx{DAi3`cyywpo<9fsw;^P-ddQkGvgQu}m-cHy5xtlS!qwdRq2@bF-az7Z2=-)_tJo z(W|v|Wkj#-eGR#re%rSF`sC};u)o|4UOQ22XOSlj%&{WpqwmmCZ7rIhv|5AsNlHud z-F?G&%T@L*F}$~5-9JnD?RE&6O&hz#G1T+BWwzUstAy>zt%UKXeWsH~Y{kre#kOy3 ed_%?ugKcIQTCq~RaB`_wA^Gvx`E&~ZwSNIxYm<cl diff --git a/substrate/wasm-runtime/test/src/lib.rs b/substrate/wasm-runtime/test/src/lib.rs index ed4610a4df..caa34856f4 100644 --- a/substrate/wasm-runtime/test/src/lib.rs +++ b/substrate/wasm-runtime/test/src/lib.rs @@ -30,16 +30,16 @@ fn test_ed25519_verify(input: &[u8]) -> Vec<u8> { } fn test_data_in(input: &[u8]) -> Vec<u8> { - print(b"set_storage" as &[u8]); + print("set_storage"); set_storage(b"input", &input); - print(b"storage" as &[u8]); + print("storage"); let foo = storage(b"foo"); - print(b"set_storage" as &[u8]); + print("set_storage"); set_storage(b"baz", &foo); - print(b"finished!" as &[u8]); + print("finished!"); b"all ok!".to_vec() } From f82e30bac349586293a14efaf8d252efa1db726a Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Sat, 27 Jan 2018 13:54:34 +0100 Subject: [PATCH 094/112] Kill superfluous code. --- substrate/wasm-runtime/support/src/lib.rs | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/substrate/wasm-runtime/support/src/lib.rs b/substrate/wasm-runtime/support/src/lib.rs index d506e193cd..878ef18ca0 100644 --- a/substrate/wasm-runtime/support/src/lib.rs +++ b/substrate/wasm-runtime/support/src/lib.rs @@ -78,27 +78,7 @@ pub fn chain_id() -> u64 { ext_chain_id() } } -/* -trait AsPtr { - fn ptr(self) -> *const u8; -} -impl<'a> AsPtr for &'a[u8] { - fn ptr(self) -> *const u8 { - if self.len() > 0 { &self[0] } else { 0 as *const u8 } - } -} - -trait AsPtrMut { - fn ptr(self) -> *mut u8; -} - -impl<'a> AsPtrMut for &'a mut [u8] { - fn ptr(self) -> *mut u8 { - if self.len() > 0 { &mut self[0] } else { 0 as *mut u8 } - } -} -*/ /// Conduct a 256-bit Blake2 hash. pub fn blake2_256(data: &[u8]) -> [u8; 32] { let mut result: [u8; 32] = Default::default(); From 5b337e3a9c2160e633bf55cc7008b5b5f879a0a0 Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Sat, 27 Jan 2018 19:52:24 +0100 Subject: [PATCH 095/112] Repot and fix a ser/de bug. --- .../polkadot/src/codec/slicable.rs | 32 ++ substrate/wasm-runtime/polkadot/src/lib.rs | 3 +- .../polkadot/src/primitives/block.rs | 60 ++ .../polkadot/src/primitives/digest.rs | 27 + .../src/{support => primitives}/function.rs | 0 .../polkadot/src/primitives/header.rs | 74 +++ .../polkadot/src/primitives/misc.rs | 41 ++ .../polkadot/src/primitives/mod.rs | 38 ++ .../src/{support => primitives}/proposal.rs | 0 .../polkadot/src/primitives/tests.rs | 242 ++++++++ .../polkadot/src/primitives/transaction.rs | 69 +++ .../src/primitives/uncheckedtransaction.rs | 85 +++ .../polkadot/src/runtime/governance.rs | 3 +- .../polkadot/src/runtime/system.rs | 3 +- .../polkadot/src/support/hashable.rs | 38 ++ .../wasm-runtime/polkadot/src/support/mod.rs | 4 +- .../polkadot/src/support/primitives.rs | 525 ------------------ substrate/wasm-runtime/support/src/lib.rs | 2 +- .../release/runtime_polkadot.compact.wasm | Bin 62459 -> 62629 bytes .../release/runtime_polkadot.wasm | Bin 62508 -> 62678 bytes 20 files changed, 713 insertions(+), 533 deletions(-) create mode 100644 substrate/wasm-runtime/polkadot/src/primitives/block.rs create mode 100644 substrate/wasm-runtime/polkadot/src/primitives/digest.rs rename substrate/wasm-runtime/polkadot/src/{support => primitives}/function.rs (100%) create mode 100644 substrate/wasm-runtime/polkadot/src/primitives/header.rs create mode 100644 substrate/wasm-runtime/polkadot/src/primitives/misc.rs create mode 100644 substrate/wasm-runtime/polkadot/src/primitives/mod.rs rename substrate/wasm-runtime/polkadot/src/{support => primitives}/proposal.rs (100%) create mode 100644 substrate/wasm-runtime/polkadot/src/primitives/tests.rs create mode 100644 substrate/wasm-runtime/polkadot/src/primitives/transaction.rs create mode 100644 substrate/wasm-runtime/polkadot/src/primitives/uncheckedtransaction.rs create mode 100644 substrate/wasm-runtime/polkadot/src/support/hashable.rs delete mode 100644 substrate/wasm-runtime/polkadot/src/support/primitives.rs diff --git a/substrate/wasm-runtime/polkadot/src/codec/slicable.rs b/substrate/wasm-runtime/polkadot/src/codec/slicable.rs index 002a506dc7..c702741ee3 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/slicable.rs +++ b/substrate/wasm-runtime/polkadot/src/codec/slicable.rs @@ -100,6 +100,38 @@ impl Slicable for Vec<u8> { } } +impl<T: Slicable> NonTrivialSlicable for Vec<T> where Vec<T>: Slicable {} + +impl<T: NonTrivialSlicable> Slicable for Vec<T> { + fn from_slice(value: &[u8]) -> Option<Self> { + let len = Self::size_of(&value[0..4])?; + let mut off = 4; + let mut r = Vec::new(); + while off < len { + let element_len = T::size_of(&value[off..])?; + r.push(T::from_slice(&value[off..off + element_len])?); + off += element_len; + } + Some(r) + } + + fn set_as_slice<F: Fn(&mut [u8], usize) -> bool>(_fill_slice: &F) -> Option<Self> { + unimplemented!(); + } + + fn to_vec(&self) -> Vec<u8> { + let vecs = self.iter().map(Slicable::to_vec).collect::<Vec<_>>(); + let len = vecs.iter().fold(0, |mut a, v| {a += v.len(); a}); + let mut r = Vec::new().join(&(len as u32)); + vecs.iter().for_each(|v| r.extend_from_slice(v)); + r + } + + fn size_of(data: &[u8]) -> Option<usize> { + u32::from_slice(&data[0..4]).map(|i| (i + 4) as usize) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index c23622cec8..9389145843 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -28,9 +28,10 @@ extern crate rustc_hex; mod codec; #[macro_use] mod support; +pub mod primitives; pub mod runtime; pub use codec::{endiansensitive, streamreader, joiner, slicable, keyedvec}; -pub use support::{primitives, function, proposal, environment, storable}; +pub use support::{environment, storable, hashable}; #[cfg(feature = "with-std")] pub use support::{testing, statichex}; diff --git a/substrate/wasm-runtime/polkadot/src/primitives/block.rs b/substrate/wasm-runtime/polkadot/src/primitives/block.rs new file mode 100644 index 0000000000..2975286479 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/primitives/block.rs @@ -0,0 +1,60 @@ +// 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/>. + +//! Block type. + +use runtime_support::prelude::*; +use streamreader::StreamReader; +use joiner::Joiner; +use slicable::{Slicable, NonTrivialSlicable}; +use primitives::{Header, UncheckedTransaction}; + +/// A Polkadot relay chain block. +#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] +pub struct Block { + /// The header of the block. + pub header: Header, + /// All transactions. + pub transactions: Vec<UncheckedTransaction>, +} + +impl Slicable for Block { + fn from_slice(value: &[u8]) -> Option<Self> { + let mut reader = StreamReader::new(value); + Some(Block { + header: reader.read()?, + transactions: reader.read()?, + }) + } + + fn set_as_slice<F: Fn(&mut [u8], usize) -> bool>(_fill_slice: &F) -> Option<Self> { + unimplemented!(); + } + + fn to_vec(&self) -> Vec<u8> { + Vec::new() + .join(&self.header) + .join(&self.transactions) + } + + fn size_of(data: &[u8]) -> Option<usize> { + let first_part = Header::size_of(data)?; + let second_part = <Vec<UncheckedTransaction>>::size_of(&data[first_part..])?; + Some(first_part + second_part) + } +} + +impl NonTrivialSlicable for Block {} diff --git a/substrate/wasm-runtime/polkadot/src/primitives/digest.rs b/substrate/wasm-runtime/polkadot/src/primitives/digest.rs new file mode 100644 index 0000000000..b51bc8df54 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/primitives/digest.rs @@ -0,0 +1,27 @@ +// 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/>. + +//! Digest type. + +use runtime_support::prelude::*; + +#[derive(Clone, Default)] +#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] +/// The digest of a block, useful for light-clients. +pub struct Digest { + /// All logs that have happened in the block. + pub logs: Vec<Vec<u8>>, +} diff --git a/substrate/wasm-runtime/polkadot/src/support/function.rs b/substrate/wasm-runtime/polkadot/src/primitives/function.rs similarity index 100% rename from substrate/wasm-runtime/polkadot/src/support/function.rs rename to substrate/wasm-runtime/polkadot/src/primitives/function.rs diff --git a/substrate/wasm-runtime/polkadot/src/primitives/header.rs b/substrate/wasm-runtime/polkadot/src/primitives/header.rs new file mode 100644 index 0000000000..76f3c012d1 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/primitives/header.rs @@ -0,0 +1,74 @@ +// 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/>. + +//! Block header type. + +use runtime_support::prelude::*; +use streamreader::StreamReader; +use joiner::Joiner; +use slicable::{Slicable, NonTrivialSlicable}; +use runtime_support::mem; +use primitives::{BlockNumber, Hash, Digest}; + +#[derive(Clone)] +#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] +/// The header for a block. +pub struct Header { + /// The parent block's "hash" (actually the Blake2-256 hash of its serialised header). + pub parent_hash: Hash, + /// The block's number (how many ancestors does it have?). + pub number: BlockNumber, + /// The root of the trie that represents this block's final storage map. + pub state_root: Hash, + /// The root of the trie that represents this block's transactions, indexed by a 32-bit integer. + pub transaction_root: Hash, + /// The digest for this block. + pub digest: Digest, +} + +impl Slicable for Header { + fn from_slice(value: &[u8]) -> Option<Self> { + let mut reader = StreamReader::new(value); + Some(Header { + parent_hash: reader.read()?, + number: reader.read()?, + state_root: reader.read()?, + transaction_root: reader.read()?, + digest: Digest { logs: reader.read()?, }, + }) + } + + fn set_as_slice<F: Fn(&mut [u8], usize) -> bool>(_fill_slice: &F) -> Option<Self> { + unimplemented!(); + } + + fn to_vec(&self) -> Vec<u8> { + Vec::new() + .join(&self.parent_hash) + .join(&self.number) + .join(&self.state_root) + .join(&self.transaction_root) + .join(&self.digest.logs) + } + + fn size_of(data: &[u8]) -> Option<usize> { + let first_part = mem::size_of::<Hash>() + mem::size_of::<BlockNumber>() + mem::size_of::<Hash>() + mem::size_of::<Hash>(); + let second_part = <Vec<Vec<u8>>>::size_of(&data[first_part..])?; + Some(first_part + second_part) + } +} + +impl NonTrivialSlicable for Header {} diff --git a/substrate/wasm-runtime/polkadot/src/primitives/misc.rs b/substrate/wasm-runtime/polkadot/src/primitives/misc.rs new file mode 100644 index 0000000000..2d6954f9e7 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/primitives/misc.rs @@ -0,0 +1,41 @@ +// 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/>. + +//! Miscellaneous small types. + +/// The Ed25519 pubkey that identifies an account. +pub type AccountID = [u8; 32]; + +/// Virtual account ID that represents the idea of a dispatch/statement being signed by everybody +/// (who matters). Essentially this means that a majority of validators have decided it is +/// "correct". +pub const EVERYBODY: AccountID = [255u8; 32]; + +/// The Ed25519 pub key of an session that belongs to an authority. This is used as what the +/// external environment/consensus algorithm calls an "authority". +pub type SessionKey = AccountID; + +/// Indentifier for a chain. +pub type ChainID = u64; + +/// Index of a block in the chain. +pub type BlockNumber = u64; + +/// Index of a transaction. +pub type TxOrder = u64; + +/// A hash of some data. +pub type Hash = [u8; 32]; diff --git a/substrate/wasm-runtime/polkadot/src/primitives/mod.rs b/substrate/wasm-runtime/polkadot/src/primitives/mod.rs new file mode 100644 index 0000000000..51ce3d121a --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/primitives/mod.rs @@ -0,0 +1,38 @@ +// 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/>. + +//! Primitive types for the runtime. + +mod misc; +mod proposal; +mod function; +mod digest; +mod header; +mod transaction; +mod uncheckedtransaction; +mod block; + +#[cfg(test)] +mod tests; + +pub use self::misc::{AccountID, EVERYBODY, SessionKey, ChainID, BlockNumber, TxOrder, Hash}; +pub use self::proposal::{Proposal, InternalFunction}; +pub use self::function::Function; +pub use self::digest::Digest; +pub use self::header::Header; +pub use self::transaction::Transaction; +pub use self::uncheckedtransaction::UncheckedTransaction; +pub use self::block::Block; diff --git a/substrate/wasm-runtime/polkadot/src/support/proposal.rs b/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs similarity index 100% rename from substrate/wasm-runtime/polkadot/src/support/proposal.rs rename to substrate/wasm-runtime/polkadot/src/primitives/proposal.rs diff --git a/substrate/wasm-runtime/polkadot/src/primitives/tests.rs b/substrate/wasm-runtime/polkadot/src/primitives/tests.rs new file mode 100644 index 0000000000..76412c10b9 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/primitives/tests.rs @@ -0,0 +1,242 @@ +// 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/>. + +//! Tests. + +use super::*; +use runtime_support::prelude::*; +use joiner::Joiner; +use slicable::{Slicable, NonTrivialSlicable}; +use function::Function; + +#[test] +fn serialise_transaction_works() { + let one: AccountID = [1u8; 32]; + let two: AccountID = [2u8; 32]; + let tx = Transaction { + signed: one.clone(), + nonce: 69, + function: Function::StakingTransfer, + input_data: Vec::new().join(&two).join(&69u64), + }; + let serialised = tx.to_vec(); + assert_eq!(serialised, vec![ + 1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 69, 0, 0, 0, 0, 0, 0, 0, + 2, + 40, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 69, 0, 0, 0, 0, 0, 0, 0 + ]); +} + +#[test] +fn deserialise_transaction_works() { + let one: AccountID = [1u8; 32]; + let two: AccountID = [2u8; 32]; + let tx = Transaction { + signed: one.clone(), + nonce: 69, + function: Function::StakingTransfer, + input_data: Vec::new().join(&two).join(&69u64), + }; + let data = [ + 1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 69, 0, 0, 0, 0, 0, 0, 0, + 2, + 40, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 69, 0, 0, 0, 0, 0, 0, 0 + ]; + let deserialised = Transaction::from_slice(&data).unwrap(); + assert_eq!(deserialised, tx); +} + +#[test] +fn serialise_header_works() { + let h = Header { + parent_hash: [4u8; 32], + number: 42, + state_root: [5u8; 32], + transaction_root: [6u8; 32], + digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, + }; + let serialised = h.to_vec(); + assert_eq!(serialised, vec![ + 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 42, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 26, 0, 0, 0, + 7, 0, 0, 0, + 111, 110, 101, 32, 108, 111, 103, + 11, 0, 0, 0, + 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103 + ]); +} + +#[test] +fn deserialise_header_works() { + let h = Header { + parent_hash: [4u8; 32], + number: 42, + state_root: [5u8; 32], + transaction_root: [6u8; 32], + digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, + }; + let data = [ + 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 42, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 26, 0, 0, 0, + 7, 0, 0, 0, + 111, 110, 101, 32, 108, 111, 103, + 11, 0, 0, 0, + 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103 + ]; + let deserialised = Header::from_slice(&data).unwrap(); + assert_eq!(deserialised, h); +} + +#[test] +fn serialise_block_works() { + let one: AccountID = [1u8; 32]; + let two: AccountID = [2u8; 32]; + let tx1 = UncheckedTransaction { + transaction: Transaction { + signed: one.clone(), + nonce: 69, + function: Function::StakingTransfer, + input_data: Vec::new().join(&two).join(&69u64), + }, + signature: [1u8; 64], + }; + let tx2 = UncheckedTransaction { + transaction: Transaction { + signed: two.clone(), + nonce: 42, + function: Function::StakingStake, + input_data: Vec::new(), + }, + signature: [2u8; 64], + }; + let h = Header { + parent_hash: [4u8; 32], + number: 42, + state_root: [5u8; 32], + transaction_root: [6u8; 32], + digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, + }; + let b = Block { + header: h, + transactions: vec![tx1, tx2], + }; + let serialised = b.to_vec(); + assert_eq!(serialised, vec![ + // header + 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 42, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 26, 0, 0, 0, + 7, 0, 0, 0, + 111, 110, 101, 32, 108, 111, 103, + 11, 0, 0, 0, + 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103, + // transactions + 2, 1, 0, 0, + // tx1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 69, 0, 0, 0, 0, 0, 0, 0, + 2, + 40, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 69, 0, 0, 0, 0, 0, 0, 0, + // tx2 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 42, 0, 0, 0, 0, 0, 0, 0, + 0, + 0, 0, 0, 0 + ]); +} + +#[test] +fn deserialise_block_works() { + let one: AccountID = [1u8; 32]; + let two: AccountID = [2u8; 32]; + let tx1 = UncheckedTransaction { + transaction: Transaction { + signed: one.clone(), + nonce: 69, + function: Function::StakingTransfer, + input_data: Vec::new().join(&two).join(&69u64), + }, + signature: [1u8; 64], + }; + let tx2 = UncheckedTransaction { + transaction: Transaction { + signed: two.clone(), + nonce: 42, + function: Function::StakingStake, + input_data: Vec::new(), + }, + signature: [2u8; 64], + }; + let h = Header { + parent_hash: [4u8; 32], + number: 42, + state_root: [5u8; 32], + transaction_root: [6u8; 32], + digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, + }; + let b = Block { + header: h, + transactions: vec![tx1, tx2], + }; + let data = [ + // header + 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 42, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 26, 0, 0, 0, + 7, 0, 0, 0, + 111, 110, 101, 32, 108, 111, 103, + 11, 0, 0, 0, + 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103, + // transactions + 2, 1, 0, 0, + // tx1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 69, 0, 0, 0, 0, 0, 0, 0, + 2, + 40, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 69, 0, 0, 0, 0, 0, 0, 0, + // tx2 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 42, 0, 0, 0, 0, 0, 0, 0, + 0, + 0, 0, 0, 0 + ]; + let deserialised = Block::from_slice(&data).unwrap(); + assert_eq!(deserialised, b); +} diff --git a/substrate/wasm-runtime/polkadot/src/primitives/transaction.rs b/substrate/wasm-runtime/polkadot/src/primitives/transaction.rs new file mode 100644 index 0000000000..96dba4e6fb --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/primitives/transaction.rs @@ -0,0 +1,69 @@ +// 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/>. + +//! Transaction type. + +use runtime_support::prelude::*; +use streamreader::StreamReader; +use joiner::Joiner; +use slicable::{Slicable, NonTrivialSlicable}; +use primitives::{AccountID, TxOrder, Function}; +use runtime_support::mem; + +/// A vetted and verified transaction from the external world. +#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] +pub struct Transaction { + /// Who signed it (note this is not a signature). + pub signed: AccountID, + /// The number of transactions have come before from the same signer. + pub nonce: TxOrder, + /// The function that should be called. + pub function: Function, + /// Serialised input data to the function. + pub input_data: Vec<u8>, +} + +impl Slicable for Transaction { + fn from_slice(value: &[u8]) -> Option<Self> { + let mut reader = StreamReader::new(value); + Some(Transaction { + signed: reader.read()?, + nonce: reader.read()?, + function: Function::from_u8(reader.read()?)?, + input_data: reader.read()?, + }) + } + + fn set_as_slice<F: Fn(&mut [u8], usize) -> bool>(_fill_slice: &F) -> Option<Self> { + unimplemented!(); + } + + fn to_vec(&self) -> Vec<u8> { + Vec::new() + .join(&self.signed) + .join(&self.nonce) + .join(&(self.function as u8)) + .join(&self.input_data) + } + + fn size_of(data: &[u8]) -> Option<usize> { + let first_part = mem::size_of::<AccountID>() + mem::size_of::<TxOrder>() + mem::size_of::<u8>(); + let second_part = <Vec<u8>>::size_of(&data[first_part..])?; + Some(first_part + second_part) + } +} + +impl NonTrivialSlicable for Transaction {} diff --git a/substrate/wasm-runtime/polkadot/src/primitives/uncheckedtransaction.rs b/substrate/wasm-runtime/polkadot/src/primitives/uncheckedtransaction.rs new file mode 100644 index 0000000000..bf3669ec95 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/primitives/uncheckedtransaction.rs @@ -0,0 +1,85 @@ +// 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/>. + +//! Unchecked Transaction type. + +use slicable::{Slicable, NonTrivialSlicable}; +use streamreader::StreamReader; +use joiner::Joiner; +use primitives::Transaction; +use runtime_support::{mem, ed25519_verify}; +use runtime_support::prelude::*; + +#[cfg(feature = "with-std")] +use std::fmt; + +/// A transactions right from the external world. Unchecked. +pub struct UncheckedTransaction { + /// The actual transaction information. + pub transaction: Transaction, + /// The signature; should be an Ed25519 signature applied to the serialised `transaction` field. + pub signature: [u8; 64], +} + +impl UncheckedTransaction { + /// Verify the signature. + pub fn ed25519_verify(&self) -> bool { + let msg = self.transaction.to_vec(); + ed25519_verify(&self.signature, &msg, &self.transaction.signed) + } +} + +#[cfg(feature = "with-std")] +impl PartialEq for UncheckedTransaction { + fn eq(&self, other: &Self) -> bool { + self.signature.iter().eq(other.signature.iter()) && self.transaction == other.transaction + } +} + +#[cfg(feature = "with-std")] +impl fmt::Debug for UncheckedTransaction { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "UncheckedTransaction({:?})", self.transaction) + } +} + +impl Slicable for UncheckedTransaction { + fn from_slice(value: &[u8]) -> Option<Self> { + let mut reader = StreamReader::new(value); + Some(UncheckedTransaction { + signature: reader.read()?, + transaction: reader.read()?, + }) + } + + fn set_as_slice<F: Fn(&mut [u8], usize) -> bool>(_fill_slice: &F) -> Option<Self> { + unimplemented!(); + } + + fn to_vec(&self) -> Vec<u8> { + Vec::new() + .join(&self.signature) + .join(&self.transaction) + } + + fn size_of(data: &[u8]) -> Option<usize> { + let first_part = mem::size_of::<[u8; 64]>(); + let second_part = <Transaction>::size_of(&data[first_part..])?; + Some(first_part + second_part) + } +} + +impl NonTrivialSlicable for UncheckedTransaction {} diff --git a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs index 4d944565a3..307e4bfa00 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs @@ -28,8 +28,7 @@ use runtime_support::prelude::*; use keyedvec::KeyedVec; use storable::{Storable, StorageVec, kill}; -use primitives::{AccountID, Hash, BlockNumber}; -use proposal::Proposal; +use primitives::{AccountID, Hash, BlockNumber, Proposal}; use runtime::{staking, system, session}; // TRANSACTION API diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index b3d4640e78..e37cc3cb32 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -17,10 +17,11 @@ //! System manager: Handles all of the top-level stuff; executing block/transaction, setting code //! and depositing logs. -use primitives::{Block, BlockNumber, Hash, UncheckedTransaction, TxOrder, Hashable}; +use primitives::{Block, BlockNumber, Hash, UncheckedTransaction, TxOrder}; use runtime_support::mem; use runtime_support::prelude::*; use runtime_support::print; +use hashable::Hashable; use storable::Storable; use keyedvec::KeyedVec; use environment::with_env; diff --git a/substrate/wasm-runtime/polkadot/src/support/hashable.rs b/substrate/wasm-runtime/polkadot/src/support/hashable.rs new file mode 100644 index 0000000000..31c133c3c3 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/support/hashable.rs @@ -0,0 +1,38 @@ +// 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/>. + +//! Hashable trait. + +use slicable::Slicable; +use runtime_support::{blake2_256, twox_128, twox_256}; + +pub trait Hashable: Sized { + fn blake2_256(&self) -> [u8; 32]; + fn twox_128(&self) -> [u8; 16]; + fn twox_256(&self) -> [u8; 32]; +} + +impl<T: Slicable> Hashable for T { + fn blake2_256(&self) -> [u8; 32] { + blake2_256(&self.to_vec()) + } + fn twox_128(&self) -> [u8; 16] { + twox_128(&self.to_vec()) + } + fn twox_256(&self) -> [u8; 32] { + twox_256(&self.to_vec()) + } +} diff --git a/substrate/wasm-runtime/polkadot/src/support/mod.rs b/substrate/wasm-runtime/polkadot/src/support/mod.rs index 3730483b25..c2e034c527 100644 --- a/substrate/wasm-runtime/polkadot/src/support/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/support/mod.rs @@ -16,11 +16,9 @@ //! Support code for the runtime. -pub mod primitives; -pub mod function; -pub mod proposal; pub mod environment; pub mod storable; +pub mod hashable; #[cfg(feature = "with-std")] pub mod statichex; diff --git a/substrate/wasm-runtime/polkadot/src/support/primitives.rs b/substrate/wasm-runtime/polkadot/src/support/primitives.rs deleted file mode 100644 index 48fa91dd79..0000000000 --- a/substrate/wasm-runtime/polkadot/src/support/primitives.rs +++ /dev/null @@ -1,525 +0,0 @@ -// 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/>. - -//! Primitive types. - -use runtime_support::prelude::*; -use streamreader::StreamReader; -use joiner::Joiner; -use slicable::{Slicable, NonTrivialSlicable}; -use function::Function; -use runtime_support::{mem, blake2_256, twox_128, twox_256, ed25519_verify}; - -#[cfg(feature = "with-std")] -use std::fmt; - -/// The Ed25519 pubkey that identifies an account. -pub type AccountID = [u8; 32]; - -/// Virtual account ID that represents the idea of a dispatch/statement being signed by everybody -/// (who matters). Essentially this means that a majority of validators have decided it is -/// "correct". -pub const EVERYBODY: AccountID = [255u8; 32]; - -/// The Ed25519 pub key of an session that belongs to an authority. This is used as what the -/// external environment/consensus algorithm calls an "authority". -pub type SessionKey = AccountID; - -/// Indentifier for a chain. -pub type ChainID = u64; - -/// Index of a block in the chain. -pub type BlockNumber = u64; - -/// Index of a transaction. -pub type TxOrder = u64; - -/// A hash of some data. -pub type Hash = [u8; 32]; - -#[derive(Clone, Default)] -#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] -/// The digest of a block, useful for light-clients. -pub struct Digest { - /// All logs that have happened in the block. - pub logs: Vec<Vec<u8>>, -} - -#[derive(Clone)] -#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] -/// The header for a block. -pub struct Header { - /// The parent block's "hash" (actually the Blake2-256 hash of its serialised header). - pub parent_hash: Hash, - /// The block's number (how many ancestors does it have?). - pub number: BlockNumber, - /// The root of the trie that represents this block's final storage map. - pub state_root: Hash, - /// The root of the trie that represents this block's transactions, indexed by a 32-bit integer. - pub transaction_root: Hash, - /// The digest for this block. - pub digest: Digest, -} - -impl Slicable for Header { - fn from_slice(value: &[u8]) -> Option<Self> { - let mut reader = StreamReader::new(value); - Some(Header { - parent_hash: reader.read()?, - number: reader.read()?, - state_root: reader.read()?, - transaction_root: reader.read()?, - digest: Digest { logs: reader.read()?, }, - }) - } - - fn set_as_slice<F: Fn(&mut [u8], usize) -> bool>(_fill_slice: &F) -> Option<Self> { - unimplemented!(); - } - - fn to_vec(&self) -> Vec<u8> { - Vec::new() - .join(&self.parent_hash) - .join(&self.number) - .join(&self.state_root) - .join(&self.transaction_root) - .join(&self.digest.logs) - } - - fn size_of(data: &[u8]) -> Option<usize> { - let first_part = mem::size_of::<Hash>() + mem::size_of::<BlockNumber>() + mem::size_of::<Hash>() + mem::size_of::<Hash>(); - let second_part = <Vec<Vec<u8>>>::size_of(&data[first_part..])?; - Some(first_part + second_part) - } -} - -impl NonTrivialSlicable for Header {} - -/// A vetted and verified transaction from the external world. -#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] -pub struct Transaction { - /// Who signed it (note this is not a signature). - pub signed: AccountID, - /// The number of transactions have come before from the same signer. - pub nonce: TxOrder, - /// The function that should be called. - pub function: Function, - /// Serialised input data to the function. - pub input_data: Vec<u8>, -} - -impl Slicable for Transaction { - fn from_slice(value: &[u8]) -> Option<Self> { - let mut reader = StreamReader::new(value); - Some(Transaction { - signed: reader.read()?, - nonce: reader.read()?, - function: Function::from_u8(reader.read()?)?, - input_data: reader.read()?, - }) - } - - fn set_as_slice<F: Fn(&mut [u8], usize) -> bool>(_fill_slice: &F) -> Option<Self> { - unimplemented!(); - } - - fn to_vec(&self) -> Vec<u8> { - Vec::new() - .join(&self.signed) - .join(&self.nonce) - .join(&(self.function as u8)) - .join(&self.input_data) - } - - fn size_of(data: &[u8]) -> Option<usize> { - let first_part = mem::size_of::<AccountID>() + mem::size_of::<TxOrder>() + mem::size_of::<u8>(); - let second_part = <Vec<u8>>::size_of(&data[first_part..])?; - Some(first_part + second_part) - } -} - -pub trait Hashable: Sized { - fn blake2_256(&self) -> [u8; 32]; - fn twox_128(&self) -> [u8; 16]; - fn twox_256(&self) -> [u8; 32]; -} - -impl<T: Slicable> Hashable for T { - fn blake2_256(&self) -> [u8; 32] { - blake2_256(&self.to_vec()) - } - fn twox_128(&self) -> [u8; 16] { - twox_128(&self.to_vec()) - } - fn twox_256(&self) -> [u8; 32] { - twox_256(&self.to_vec()) - } -} - -impl NonTrivialSlicable for Transaction {} - -/// A transactions right from the external world. Unchecked. -pub struct UncheckedTransaction { - /// The actual transaction information. - pub transaction: Transaction, - /// The signature; should be an Ed25519 signature applied to the serialised `transaction` field. - pub signature: [u8; 64], -} - -impl UncheckedTransaction { - /// Verify the signature. - pub fn ed25519_verify(&self) -> bool { - let msg = self.transaction.to_vec(); - ed25519_verify(&self.signature, &msg, &self.transaction.signed) - } -} - -#[cfg(feature = "with-std")] -impl PartialEq for UncheckedTransaction { - fn eq(&self, other: &Self) -> bool { - self.signature.iter().eq(other.signature.iter()) && self.transaction == other.transaction - } -} - -#[cfg(feature = "with-std")] -impl fmt::Debug for UncheckedTransaction { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "UncheckedTransaction({:?})", self.transaction) - } -} - -impl Slicable for UncheckedTransaction { - fn from_slice(value: &[u8]) -> Option<Self> { - let mut reader = StreamReader::new(value); - Some(UncheckedTransaction { - signature: reader.read()?, - transaction: reader.read()?, - }) - } - - fn set_as_slice<F: Fn(&mut [u8], usize) -> bool>(_fill_slice: &F) -> Option<Self> { - unimplemented!(); - } - - fn to_vec(&self) -> Vec<u8> { - Vec::new() - .join(&self.signature) - .join(&self.transaction) - } - - fn size_of(data: &[u8]) -> Option<usize> { - let first_part = mem::size_of::<[u8; 64]>(); - let second_part = <Transaction>::size_of(&data[first_part..])?; - Some(first_part + second_part) - } -} - -impl NonTrivialSlicable for UncheckedTransaction {} - -/// A Polkadot relay chain block. -#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] -pub struct Block { - /// The header of the block. - pub header: Header, - /// All transactions. - pub transactions: Vec<UncheckedTransaction>, -} - -impl Slicable for Block { - fn from_slice(value: &[u8]) -> Option<Self> { - let mut reader = StreamReader::new(value); - Some(Block { - header: reader.read()?, - transactions: reader.read()?, - }) - } - - fn set_as_slice<F: Fn(&mut [u8], usize) -> bool>(_fill_slice: &F) -> Option<Self> { - unimplemented!(); - } - - fn to_vec(&self) -> Vec<u8> { - Vec::new() - .join(&self.header) - .join(&self.transactions) - } - - fn size_of(data: &[u8]) -> Option<usize> { - let first_part = Header::size_of(data)?; - let second_part = <Vec<Transaction>>::size_of(&data[first_part..])?; - Some(first_part + second_part) - } -} - -impl NonTrivialSlicable for Block {} - -impl<T: Slicable> NonTrivialSlicable for Vec<T> where Vec<T>: Slicable {} - -impl<T: NonTrivialSlicable> Slicable for Vec<T> { - fn from_slice(value: &[u8]) -> Option<Self> { - let len = Self::size_of(&value[0..4])?; - let mut off = 4; - let mut r = Vec::new(); - while off < len { - let element_len = T::size_of(&value[off..])?; - r.push(T::from_slice(&value[off..off + element_len])?); - off += element_len; - } - Some(r) - } - - fn set_as_slice<F: Fn(&mut [u8], usize) -> bool>(_fill_slice: &F) -> Option<Self> { - unimplemented!(); - } - - fn to_vec(&self) -> Vec<u8> { - let vecs = self.iter().map(Slicable::to_vec).collect::<Vec<_>>(); - let len = vecs.iter().fold(0, |mut a, v| {a += v.len(); a}); - let mut r = Vec::new().join(&(len as u32)); - vecs.iter().for_each(|v| r.extend_from_slice(v)); - r - } - - fn size_of(data: &[u8]) -> Option<usize> { - u32::from_slice(&data[0..4]).map(|i| (i + 4) as usize) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use joiner::Joiner; - use function::Function; - - #[test] - fn serialise_transaction_works() { - let one: AccountID = [1u8; 32]; - let two: AccountID = [2u8; 32]; - let tx = Transaction { - signed: one.clone(), - nonce: 69, - function: Function::StakingTransfer, - input_data: Vec::new().join(&two).join(&69u64), - }; - let serialised = tx.to_vec(); - assert_eq!(serialised, vec![ - 1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 69, 0, 0, 0, 0, 0, 0, 0, - 2, - 40, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 69, 0, 0, 0, 0, 0, 0, 0 - ]); - } - - #[test] - fn deserialise_transaction_works() { - let one: AccountID = [1u8; 32]; - let two: AccountID = [2u8; 32]; - let tx = Transaction { - signed: one.clone(), - nonce: 69, - function: Function::StakingTransfer, - input_data: Vec::new().join(&two).join(&69u64), - }; - let data = [ - 1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 69, 0, 0, 0, 0, 0, 0, 0, - 2, - 40, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 69, 0, 0, 0, 0, 0, 0, 0 - ]; - let deserialised = Transaction::from_slice(&data).unwrap(); - assert_eq!(deserialised, tx); - } - - #[test] - fn serialise_header_works() { - let h = Header { - parent_hash: [4u8; 32], - number: 42, - state_root: [5u8; 32], - transaction_root: [6u8; 32], - digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, - }; - let serialised = h.to_vec(); - assert_eq!(serialised, vec![ - 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 42, 0, 0, 0, 0, 0, 0, 0, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 26, 0, 0, 0, - 7, 0, 0, 0, - 111, 110, 101, 32, 108, 111, 103, - 11, 0, 0, 0, - 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103 - ]); - } - - #[test] - fn deserialise_header_works() { - let h = Header { - parent_hash: [4u8; 32], - number: 42, - state_root: [5u8; 32], - transaction_root: [6u8; 32], - digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, - }; - let data = [ - 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 42, 0, 0, 0, 0, 0, 0, 0, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 26, 0, 0, 0, - 7, 0, 0, 0, - 111, 110, 101, 32, 108, 111, 103, - 11, 0, 0, 0, - 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103 - ]; - let deserialised = Header::from_slice(&data).unwrap(); - assert_eq!(deserialised, h); - } - - #[test] - fn serialise_block_works() { - let one: AccountID = [1u8; 32]; - let two: AccountID = [2u8; 32]; - let tx1 = UncheckedTransaction { - transaction: Transaction { - signed: one.clone(), - nonce: 69, - function: Function::StakingTransfer, - input_data: Vec::new().join(&two).join(&69u64), - }, - signature: [1u8; 64], - }; - let tx2 = UncheckedTransaction { - transaction: Transaction { - signed: two.clone(), - nonce: 42, - function: Function::StakingStake, - input_data: Vec::new(), - }, - signature: [2u8; 64], - }; - let h = Header { - parent_hash: [4u8; 32], - number: 42, - state_root: [5u8; 32], - transaction_root: [6u8; 32], - digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, - }; - let b = Block { - header: h, - transactions: vec![tx1, tx2], - }; - let serialised = b.to_vec(); - assert_eq!(serialised, vec![ - // header - 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 42, 0, 0, 0, 0, 0, 0, 0, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 26, 0, 0, 0, - 7, 0, 0, 0, - 111, 110, 101, 32, 108, 111, 103, - 11, 0, 0, 0, - 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103, - // transactions - 2, 1, 0, 0, - // tx1 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 69, 0, 0, 0, 0, 0, 0, 0, - 2, - 40, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 69, 0, 0, 0, 0, 0, 0, 0, - // tx2 - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 42, 0, 0, 0, 0, 0, 0, 0, - 0, - 0, 0, 0, 0 - ]); - } - - #[test] - fn deserialise_block_works() { - let one: AccountID = [1u8; 32]; - let two: AccountID = [2u8; 32]; - let tx1 = UncheckedTransaction { - transaction: Transaction { - signed: one.clone(), - nonce: 69, - function: Function::StakingTransfer, - input_data: Vec::new().join(&two).join(&69u64), - }, - signature: [1u8; 64], - }; - let tx2 = UncheckedTransaction { - transaction: Transaction { - signed: two.clone(), - nonce: 42, - function: Function::StakingStake, - input_data: Vec::new(), - }, - signature: [2u8; 64], - }; - let h = Header { - parent_hash: [4u8; 32], - number: 42, - state_root: [5u8; 32], - transaction_root: [6u8; 32], - digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, - }; - let b = Block { - header: h, - transactions: vec![tx1, tx2], - }; - let data = [ - // header - 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 42, 0, 0, 0, 0, 0, 0, 0, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 26, 0, 0, 0, - 7, 0, 0, 0, - 111, 110, 101, 32, 108, 111, 103, - 11, 0, 0, 0, - 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103, - // transactions - 2, 1, 0, 0, - // tx1 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 69, 0, 0, 0, 0, 0, 0, 0, - 2, - 40, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 69, 0, 0, 0, 0, 0, 0, 0, - // tx2 - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 42, 0, 0, 0, 0, 0, 0, 0, - 0, - 0, 0, 0, 0 - ]; - let deserialised = Block::from_slice(&data).unwrap(); - assert_eq!(deserialised, b); - } -} diff --git a/substrate/wasm-runtime/support/src/lib.rs b/substrate/wasm-runtime/support/src/lib.rs index 878ef18ca0..82e34f3297 100644 --- a/substrate/wasm-runtime/support/src/lib.rs +++ b/substrate/wasm-runtime/support/src/lib.rs @@ -99,7 +99,7 @@ pub fn twox_256(data: &[u8]) -> [u8; 32] { result } -/// Conduct two XX hashes to give a 256-bit result. +/// Conduct two XX hashes to give a 128-bit result. pub fn twox_128(data: &[u8]) -> [u8; 16] { let mut result: [u8; 16] = Default::default(); // guaranteed to write into result. diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm index 9bf101d73fd663a6ed67a0af89597d6b7273e4cd..63473ae445f0cf1d236ec0fc3f22f4d9baee3730 100644 GIT binary patch delta 16353 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 Q3;cgQnleTfKrwUw2R3&2%K!iX delta 15958 zcmcIr3v^vonLe-kNY1^<X_I?%bCb0D-lok>(>HC>rbT*EN~e@sL=h{X4JAO+($+R0 zI>HH3$BYx8atd^YB6TQ>;xii1s0G7I%R{MSg`&k3*J3RlDUuF#R&<!h_y2pJb8pfr z;ONTA*=PUz-~ZnG-~Vg>XWs|@-Tbd#o4YTqFg#DcX@iD;!@EiQ#-@ngx@55xj~hmr zrfE@2*L6+T<7K*DZo~n%6IOXLX<3$G#49STczK1c<JGA2AJFH%cXIUF&MjNEZPe1% zRXe)6w3=ks4P6_r>*@OF6@YHmW>p3Co*kWAcXn><*|cq|HoMHxHCMCC&uyr!&t<Y= zX?yvnA2ApEd1Jdie{g=;GTrKLcFr06So!>jZ<WmofcqL5h)FN-e^I#;&vlN_tNiUw z4c_~ldb~g29KieelcwUmd(yS>Ce3zF)jQMu#+vu*wSza*yr~<*GyQ98cTw?X?QJLq zZ^<?rRQ+204SKEL)Nrpp#ece?MV~TwvSE>>PxYJfU)Br$PxG_%!Z)WK()GH*M;mW9 z^+tbf;a<IQ@U=pP5pTpuuSPJE-tv;(=fB+Y2mOTq(^*UKOwR7tU-kcG_7Xgg&R(P+ z^~>ixH)R@i(4FZhj_RUJ7!E;#SO3j9J2Al3b2~unOLNb|`^mYF=#%{i=MlVa{z||* z=bu~hp7xCeb1<Fx3p({2$clt0cfbHqE-Yt;X5X&smS-$Cmb+TPIOQKXYrTHTpSkdS z<3xjh{lXO}2EVs(v!PG-o7!^5ky`)!wnhxHtu3RE`F(9I*&}rhR{8RWj9SmU$;BQP z49gveZO*6tk9HOOd%7wwOS$ISq%L%!6|`&e<?acsJ0D$_uU?rnMAV(SHff5qI~MJB zGu`=2ht_6js_t~>t<rkDJ0DYZD#oHB<43QW;iZMvtVuxH9f&ZYl*lw2iWY%DD<iCN zAds^}EC7jgGbpwh0}+fqAZHU3si2ubAd)Sm3oH=vYKnx3%0L8EqM$Nl@>C+lK^O!o zwF2U$W=B|{VvCvp#6&QaAz}=ek`R%giPn)6wP6(<D?DKbb?P}}5(gt9p@6j_sorc+ zQHqH1F+wUNo(bt%r&9!5irgqNftK#6m5f{an4z{IWUxyh-iG4Z3B=oQ+S<nqVxYxD ziUUg!h?H)xM`)l@vcEKyF$3$fAn?HqlHqPv6gQDMW=WYl#&ZrCmv#x@bcg(tfOz)= zHhOKwF_Pq_wMh%b54E+)2uY;K)nN@vuq#PoO9VS!TF2zeWW7>o?y%O);;e}{YKwzP z87lLFN}AB203`aJR*>(3?8ii9u+Izvzp^4e4ulbFL|Fi0c1@7|RLD1}4ik2cG(_#( z8TUVw{h|gD2vll|%x84~6?=jLy>r<oLG>hOc_-hU?8idc&xW#Jb4J-Oaw8L}uB9~A z!?x1kq2BjOv8@W_E$tErYoAoIb^>ATlTTlJuT_+NM^pv7#OeSdRbtXOkOwN0#N+@* zQ|X07v+O$xnheQQ6nitrl<e<iTU8?a1Q;j#1UOCh+l;-Y2ciEpggz>ikSp0P5$Ta} zB7H2ZkxU;6Yo$W1{T<76QIv}kJW+5xDY<`ci^lIzB;1&yES^~ei<Y-&bSowb2=xD5 z*xSF3%#|+4iwY-PQB^2mlTH_`cOw$1P!=+w0kkGqKI!K?cZ_{*I0qO#_PF6xBmlw_ zI$+ip?AusGl)Il=myDsHxFE%n6c<sETAeI&wOkCUptTx9Fm)YPn>i45t(;8(OYsl! z3wm2{0Isz*sX?TEqjl$O(xGT~t_B@y@t-o6iwseXP_a30QB)EYwn%m7BLz((0$Hk9 zBD)&%u|#G~G7i#d_|mL1Nu&#gmQSt308lVX)QePIt{&|%kD4BiuA&wS6P&rC2Dmi! z0s?_ttu1Or%uQ@T_#*1t&=(G^6*5!9c&-jORWU~zb#+otm^P-*oh=%H1|<SHxHwt} zU@6QOgHVf?!i!^IC2pb{G%{`vc#+g>@JUXMuq<GJpLSw0NH=4?x%z}2zRJ<^_R1u| zDCkI`kPb00EM&kk3hH!+(6~oD3w&b$rZJAe11p{oMcPVfX7a@dfcyyP)~GhT7GoXd zV`^0!%v=!Du)W<2V^49G7x=v-5Tz*Q!$2o+fR(BZ1Dxgw%TyZ%C@-D=7zJ_^4oV+h zD&IV7CEsNK8D*k?OBY=cI?{L;;+2Q)MtTmZ3E5E5BB2LQjQ7&yWA>VfO1YI4*mIHb zD4=&O8PEe@aexm=q5vPdAasS0A^=oN=LR97TozP$SW_?PAzLg~tAI+1$);o*R!qCY za^eLH3V0X9$|Nkrx)NbgTT1dmE%8u{NM1PnrodUn@FXyDKZ}%QD4$g=OquPk?1UX8 zNuo{@NC#UvWU81vkj0QRwLm%oX)BpDwUF?EGRg0F%6m=nwWdF5RT_afn+K>N={bqT zyly;b(e<RQq~&RMR<|IHm6bw(P+df5>=v02K?Dei5JA|jMjV9dVNe4+QP*a&AZ7^v z;b;+=?MSOp4e;|?cPNZ$_bJqhiny#hl+G}kS%^Nc%3+k0c3(xUc=|YwT8T<}^6>Ei z^g>9EXLUC^I90S;qdEa7QkRhW4$=2uu0qs5n5z^vOrEq(E-V^bAV~nd0tzL)^J%w_ z$uX(%jsT}h2)u}HhAZJ?CxjWB3Ih*|Pd<XGP@2^^eCh)3z!VlaAPcsUq!Qb*AIGka zc$>M`B)3r{FW+EZ*~_HeMcp~FIJ73bCfvA}iv~_6N~RZPAO56<{f%=rB;3^U^$+H= zu1>y!IRICH>UniAjzG<d*y?0l;CQtrNk)m7P$Oc_GQ2~k)nE%HM`_%J-Lo|<$0t@a zdkObRVz(R1)nNRH8#@o<U^iJI&<#9Uh}~@0G=akqs~L63)t~}(#FJ^G1(g~}3_wJx z5+P`YLI6Nw&Ettkt_H_f*OTKhDH-w>r%H2&?nr!AR+<(lNEEd+YQ`jKt#W!L^GV6h zSeQlnv(F?Zrbr{5IkNPin$QRABii?xxhT0rxh}E@iWV`obn-lqM3g8|NW_@71z3O* zmw8qZW*2BcdTQFWg=kv@UIrYXdC>Ui3x95ra%bU-v6af7)4bUa6Ky#1D3DM0<waLM zh8Tu?c^}*>J9Bc;`%F%nIEJW5nhA^D_dYXM@5Xb{M8bn{ry<}$379|-QNij|L9s(h z*ts;v4(Vd-0Gb>+q$zYrV@(JhQWQFf%9Rj7+c6Sl>|~Vj&vJ=Xg|0;U9(FA_2#CN- zNFSq|5X&G`mUVf&_68<X+J^v#EC%fp+l{~iV2V)RN@+J?sZ*kY-<3HObzYlE_O&`t z6fzGSK)wY#B@MEOwi-7$&3V|(I4pogX4Ao*!MtZ(uN8_R6`CE1<qC=orKz@>%}lNy zsIa<hoq>yk1hwJ~rlVkZ@m38!4?~%Vv>_&{E7?;(+Dxc63=E;WjooBws3Vzh7n@8W zp@G0INlySpKEv`-FfuF%6#h*N{fgp3kzY)OetvsTlLvB`1EhfhKV^F^L>i9u5XQ&* zlmio0FosP~M>%9dD5bB0R}b@Uq~zdrHb_@cotUHQRB)~f%Nix(+EVQll^y{9sQ`ae z<y%~~YyYFl|JBJf0vVg{kas0z195<wwJ|-fd?*P8ppjq;(KyPDU@|e==+l*HX20M% zpfuoNp2F1}(-o`92+|l7u9Tef7=*PYO1vOpVXWi?Ux@gOS4R^B5gZ$eVFN%MHUy3^ z#ZjCLO0W=g<g>V(8#-5rXxN#ShR&6tPc0rz*$G2vusWz!5YN_zfnhOk$C!P=C@OaH zA|=D91ZXrIh7B++6do#=49%6sL&R%^9zPpWsVR0QOqJ{?va`rVW?o5BW<YVTU>q{p z(PK9zipx8b7W8Y^dMPuA@@7?jT9vn`au=6gyY?9c_y<*fR+W9K{6|%OPL=<p%6?Ve zs><6`c{@s41Dn(gYZZqzF;_Sd)-3n{@W#}f<&ggzNi=kP4AS1Ax0x(JBwrfv7Z53e z6wscBR3LkS7=>&@iY!cw0>+?@kS+$X3+pg&F<7~<jx<dSVieX9e#Sgl%Mbv!6vJ-I zIvt=f2&`+2{D2%J4bvgI<zxdj<nt@dPFh^0hVV(!>hc1pk<}2jQ#$#*L!^{et7r6M zb%fi85<G$Jlwlj$EH@4gz`f!Xr}j7o)?f-i1A{=L!3D%a+$hIZY6*7|j@`!-3&!r( z^I0`EN?0I#6aa3(b7^FW?b6<2P+F}T6x8WpTQC+9|1-q@G^M350SVxk8o_f2U>9?^ z1b{8zfI7tRunB2O<%SS!LfTzcth0Mt9Mq9;0H);iJ7n=V4!guTW-YBUC6fZ<mkA8H z%ny_-bF^fJyiCOV;gorqNT!4UUM9`}A%IsoQUc&r;#}Z`D7;Rj{1iZKEGIyuyFnLO zlLA1Fuw+}Yi!4$oAEtaaTG`>qP!HibxC+^4K}u{vkZ*UpHLH_23t4XB+I-@x9f_Or z9BU(~gXr6Gy$cXyTaHE9jxv=?66|X;6el48oXg-ekVPyn-3II=jt4AxN|94!J7XA> zV{fU{R#Cc;r1Dt2Fkw=2#EHc6z`@C_j!4l~Y6X)UiZ;9(Dgh6mRtQ>{2Pj#q&<d@h z-RALW>q&ZGLcoR?&%;v!6)nyK8iT#ScN{uD;1mOSYz93#s3Nb#+CWht65I%3bI65J z4N(lmgf)l>kt@rBK_HUD_p6mS{A6JYg$-WhQeYUO6P}aEfQT1#x2U_7)R5CcHUeyQ zb@a566{9YcY&x@zBz7|M=m{&7LfFMjWZN~)QUw^L4E5+lRm#y4sRBn!q>4F;)-Z}l zQrLw-`*oSZ+pW{dkZe;fDiX?r6$}R3oLA(Xpu_|31SS|~`Ojyt1_WhtUn1&QfYTb$ z%F_`GaWwXV7!3zdivtb#AqR$BCov6TICg}G0jMPFM`NBb=_eB8ppc7@9*T}~pos)3 zb5y>=4p6$2^Qvt52BO4Z!l}w)9L_jKnE<6WIWojHaWYI>sy|F8POVk{7MDx)@2c_; zm+jhP5!hey(cf2qVO2h^$|qF$q$;0M<<qMCfhvEf%EPLBMwQR1@;OyLugV{(^2ZS* zWoZI0AfUn_jN=`LG?3y~xLa&!vvC+np#X*`4F0a!7%qW9$I%s0k%ZA}_>D(Kg2jY3 zJ56%LDxAXlWi(q1F1bHqp&`oYvb{+u4)0enIL@pbYqV<QG%1!Q;RL6(+f@AyRqo-k zUAs$_ck9C7P#O}*p|mGmCdSluhmkbJfv~pfD1;`6Au8l03CP>au_6Yg*$anL$ZoGL z4J<1L&aYJCGYKDMN$s6h$Y$x0)#Ed(v)Eaf!&guo6X-~kcKhLjU@Mkt#P{3CA<^on zatA7~va)3lDzTt)7b-Y6wKE#9nKyR>Si?Z~V6#h^!eHfc;dEY*Avbn0itnkxX+rV< zf$ux!LY$5fh?)2hmum=Dqt=n}-?yvUn=nB&wSm&9QA8fh<6RF=XCkmLUw<JoRxmI~ zTtSNJL_>!L3mo&-)ZHlRKi#2SM7AqrH+TX&|5xYuQ0cPRM^ftJZ@_W6=nnl;9pq<X zYj9eJ7zK=%qQgStU$(1k>zVgp++_dKJ#eu7imSose`eeFmGbAE4vFoQ$1*y<vhCpG zD|Q+?Dj9Lw>ivs%Ie%i=e-+WAWjhPU4NJ?u>dc%Tr-<)#*%KFyA^%n!4u*1vXM(l# ziH-SupxMRUGM7B#utldfcuP7Xk>NFL1e<R^AB0A9+LI>eFIYKwCCD+%4Ci9-m6Oha z=9)UnKhuN`aqbW<9XUQut-|D1P(!bkBSV0<K1+U`Ou3OB1hF!^icpNc6u|6qqzH?P z7>124Vz{&mJIf1&iRI%etSW*tWP%Wz#W?<@RBXoG)9iE*#R%s($@;@FA}otwzT<AP zz>TWU{&IX+g>uRfL4>Kmjg^Qr>sTS#{aRT=EJ%hwG2Y52WmP(GW!^o`+JG!pPy8mk zQyH37sXzeX`z#L%y*bUv5xeAPL0S?xFIdr3o{0Pd0t9Emg&8cYiay23yav9Em8MN5 z-Ww|u!MzI^aG-N}cmYF#Fh}GaONkUi3*^Z$gGt3Nf5Ek}$)X(JSR^}xyE9eAv9MU2 zjp%C>7A6Cfe0A}<2ZJz`lDi_(&d?>4@RkV?p(|vtvt^=MjaD8~@tpBDO*msjB8BWe z5(=+2IOm8e5|DBd5F{1L{(>DZ!}Y{Kn<|j;3cMzEHO#A>wyo$9#4e;xDt3_x8%>l^ zsP+GoJ)ViD0*OB-V8KiRJ0tb;tq6rr9P&~20Wo!q&RH=Wur|m87F4@n>|#wfG2I|d zjg$pRd5rVZh-*<5G9Hr=IcJmU)J&#IMrQCA#0+^%6q!}H^nh@R6z)&to8NJ&xdL{H zkA?D<!Re`Hxmfy8q2c<fAp=NtK$r2OI=REFynRX=NTrt<Ff<leLWTy|K>DmgRKA~) zQlD6$-5jcdd++K?3mXW0GYE$AZ|$!|JU<WvL#+-SAK!;_d`I^f7fuTfw!_T?p;t_X zLeNCFTP6>rC@3WkIP8@=xc1ex!r1_1s-rzy1(mQGsg<XH)=tndKxZBk0O3~SF!g&L z;W@$aN}4`aOV@DSry6)(e7pJSTNmof{6F5>Fdaus!~KoXjVH})jJ^@#xWF*3<qfCR zUv}I4m|WM8-?C)B|61E>T$nzwco8oDZeH9QzUP<R9KQd2$w9o|(w?i#PZ)i$eHU65 zFU`fNg(uXxwA%iLZkV`kZY+12{ld8q%m%-1vGtS}+#Eil<K{59EED?95}|WI>ki;p zGt(da=!}^1)`JZjt}?AdQ*gQZvl}n6j!tnp24C6OrW?Ie{d8Auaz9!y@BvvIC%hk@ zy8!pV^_6ep`TLdE;ko&|V^&`tJy)&zwoa6Bo!lLate#?6y-n!RwB`#T^!YVwOlwc0 z)8W^x`?-Ai!@BQUhY0fR3m@Z`!B4zzhGmhn9K8SHNxHSK-i`TNSFiQAuaEfUm(=Nt z{27<5vJTI1rVoDXlJj-F%|G;^%dLY=K>PkhAM!_5Mf^{$ca4E2|Izgyl(cI;{2yRs z`K9;iGyN}J+KgErz4T?ep8fU9KH@EL773_BMnv$T4#|{B?l2fNPnHmSvIbEx34x8C za}sIW9hHK+JI~zF;rQhDJB`2R;fogE_JEP#lC}*@6bf8W<$*>9Kh<~zm&au_z=|uZ zpxoQUIVW6XmmfgMw7I(^W!#hH4~iB_x|@QT;&g{+zwVsno`N*{zq|Z+MH?1`G^Eg7 zX7{m={4V!WnNbZv3gl))!v}x<;^hY0xaYRlu><&hfd84@uZG*W{qvOyddnTZGI2Qd z@7d!T2Mhj}{Qbs2!M|Y7ZeyU?|K*;0!0%7qxq&#HyRXWB<IZLDbAZ`*t+a-6*sj9e zXZcI_SNcPDr2>)kkKT18cpv=o-Jdt5R4%_~x=z0+xO!i$ZtN|9+9m$W_g?2uy>Gq$ z;1_N%_7ms@V<?B>a(~_aZN|Q4MymN@js6~g?iaTh#~b{6zj(yI`~IZ=$$$L<$`1d- z_n%F~viC3dr`{Rye|dio&He)izDkApz)F3g|LlP_TA2AjM<r$M25^}<;LT4Tcti^G zVE;oE#zvTfth*OkM2S@(`@pXf>?**>M2tSzl&lMIfPpap09XPjl}N*)zyIG~K3iYm zFa62~&HV+}A9*M{__eRx7}w|fvmQASa&79jIt+_`=;3z_jfT+6zSAIo{^8&F-RB63 zD8n6G_dVcJyy4&ZDC07;|1sb)^sC=LzHX=>CADZ4VWR_sq}dvTJ1#{pER`tYJ{5~( z2!AyLVLUc`k#VrepY`~bdK(uFp<cL5Rcj-&q{|xp{K2X7dzLQsQd!}+!(fPx&j7?x z)DR;vEQHY23WgUUj01QGf!6>|FQUSL4&DKw=r@2!%B46LpH3PdEQnAEY1s|%kkIM9 zkT5EC8oXuMXHES*gZA?G8Zb*A?wE_`=Q>v5`EMPqc$Tdo$P#{TS}~&n>(<a81JUIQ z|K1gIys9k1eS%r!Psy87q(FDonqfMmJ(6|^4Ge$*kqAPVj95@*vn<!^I{%2pSPrLl z4&4DY+~wVQ(=E^sPYm~Nd|o%`I*=hWca~0W6FXMWHo32BrE{RMiKLtZ4e8(g_*M0? z%6H;~iTiJ;BUQ>Xy2W4qbiKdmiD|IQ>z~+$=QB^-f#+pU_Tc%GC-*S?TGMnE_%A;7 z5Nf?o18Z>f=?C?x;0^BYi*mPstD$&0)mc$4>fM7<q5N<C@PfC+$sJzzb~uB#AD(K| zVX(NUra{~S9SW;U272b%!#T89V={3}CZ9dibOyiq+-4nnJLN}n^s2$NKYE-hl`qW3 z^XwPy$?!%q{akq|@xjp-Zqx<0;>Ig4RboZQVcq(Z3(RT2s;8fc;CUplAz%js0A@S# z)=~N$SN+cxO#yZl7+5E8%}l3@Q2AQd+esrZ;<leH1L9YHwyg$;wQ}jSMjnAN7QDDJ zk2c(l!#Py;1PR^-<mdSJDrC9-`NfaZ{G<58%&}GAkyD+k0zZp;HSeVrwJSt*P6tkE zT`~n{i`i8p%rc!7e*a4k(JbP$*AsX7f@5a|>_IEYOZKEo+2h}L>}Kc<2$alEi3t{v zi{mOUe$(X|>+pFZW83bLnKT&xdW>InejS+!`I4`rgdkssXJROc%da6qfV;N^Un=yA znFRVNFos1y0g~w=NuUvyz)^{{1h;NkU(u^tVfD7KNghE82GPef|J2JD$qmvZYj80x zRDjEW{(HS?@cq9SBvFgK(t_t%uk_k4&bdd&eQn#iFg^I#D>o;^s~J1fo6xitP16QY zPC~g(*R&K$&F!uA=bo5r4AlA?PNe8JZ0>KXTSsc`%)F$gL2R@QDA7yXjuO4lWehgm zL2U{_@ozG8ch>h_&l>|-|Leb<-#(JH6B}lgiyfP;zNV*LY|z}%tgWLsm9;Ix2bnBf zLj}KUR2mHJ^KX4^ZOxH7+Zn+SG}mu{euUdb{FASx%X;f=qg`n3F5fxPVDGE9V?CR$ zZNI*Ai{EnMJ6@!H<F+fiG<ZQfzH!^u_Ri~i+BFx5v8%UT-@bjvHcX+x&g^zHtqDYr zR6;XQ&cwf5NB<N%vjMF*SBI?&!`1_6orl)hC9U`(ulgRE@;*DGp_#}9q>-9e%}1x$ zahgTv_U)L{agf@L;i-Fo`<@WDcdD&pA9qjnfAG7d){&`p-oN?vl%IX0(&!a_%Nuiy z0pVZz#(ZN$__w_=+t{7+AAO_68_LOrc5dH+-%91|%n`7Vc3zu2ap#YrbpWmPXxxC3 zwi9_KwGX3c?FE!p611)lTl?~MeCH>2wr>T8G08lb0^B)Tx`@0XL>|cdYhFJ~&qF?@ znbYi<{@T|w{-dv_rcJZ!FYMgWwY5iF)4B5+vGba3*KN5{T+t=4nVYVhgI~W)W8v&= zB;oY-G-A-6&h{%hw_wnHs`l|sR6EdUXGE3U(_t)iDn?%r&frkclc)O>a7TcH6TcSV zE(&pvqqP^U^GjL@(}>{#eVOk6{pccVc)C3m8<O^)9kq>->HbTj?Z*BYe$~kqad-v< z2veac1ms;J!2L&N_#Zhr?ZVzBJ2MKT=_N?(@GfO=Z<Fl|qm?9c3HnXrt_Pd!7_Gl+ zN2lfvs0#g>*d1>2e{yn$KI)I1ocaE}1&OwGC)8lSs$Aa*w1cX$r3;k-RoS^6XhQ`% zb73_GE1Aw_yi2`1;<vo{9<RR{?C;u1ng)jNQMIi%kbdoJ#+Yc^x@9Z&qS-dLbm8To zf^OMD;{_FJ8B&!^Td&0Io3S5iZ~?1Cj5{YBe5Bc4(%I9~<u7=%&DuXxvfb<2xf4H) zp0i^oy3e$o0dylKJ&1qOH;7IN^lJdjW9SH=0zx{Tv7;r>_K@AZEtnSQl75h2V}{x@ xuz)a2T2^!SwiJi`JUTTHnmf?q*Pm)KMq2!pr-aoz%dYl+buw-2pM?!-{6C%TjC%k8 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm index 6cbc2ef9b954b61a94ec459c330f44ab9975f50d..f2492b00ecb4b75e28bc85cbdcbc45b7138c0af6 100644 GIT binary patch delta 16399 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 delta 16041 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 Q=B-z;aoRsC*s93?0r6#_p8x;= From daa77d09a66b5d10d855dae89356d56ddf101c36 Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Sun, 28 Jan 2018 13:41:22 +0100 Subject: [PATCH 096/112] Rearrange export structure to something a bit more convenient. --- substrate/Cargo.lock | 6 ++--- substrate/executor/Cargo.toml | 2 +- substrate/executor/src/lib.rs | 2 +- substrate/executor/src/native_executor.rs | 15 ++++++------- substrate/executor/src/wasm_executor.rs | 16 +++++-------- substrate/native-runtime/Cargo.toml | 2 +- .../{support => std}/Cargo.toml | 2 +- .../{support => std}/src/lib.rs | 0 substrate/wasm-runtime/Cargo.lock | 6 ++--- substrate/wasm-runtime/build.sh | 2 +- substrate/wasm-runtime/polkadot/Cargo.toml | 2 +- .../wasm-runtime/polkadot/src/codec/joiner.rs | 4 ++-- .../polkadot/src/codec/keyedvec.rs | 4 ++-- .../wasm-runtime/polkadot/src/codec/mod.rs | 16 ++++++++----- .../polkadot/src/codec/slicable.rs | 8 +++---- .../polkadot/src/codec/streamreader.rs | 2 +- substrate/wasm-runtime/polkadot/src/lib.rs | 14 +++++------- .../polkadot/src/primitives/block.rs | 6 ++--- .../polkadot/src/primitives/digest.rs | 2 +- .../polkadot/src/primitives/function.rs | 2 +- .../polkadot/src/primitives/header.rs | 8 +++---- .../polkadot/src/primitives/proposal.rs | 8 +++---- .../polkadot/src/primitives/tests.rs | 7 +++--- .../polkadot/src/primitives/transaction.rs | 8 +++---- .../src/primitives/uncheckedtransaction.rs | 8 +++---- .../polkadot/src/runtime/consensus.rs | 4 ++-- .../polkadot/src/runtime/governance.rs | 8 +++---- .../polkadot/src/runtime/session.rs | 8 +++---- .../polkadot/src/runtime/staking.rs | 10 ++++----- .../polkadot/src/runtime/system.rs | 13 +++++------ .../polkadot/src/runtime/timestamp.rs | 4 ++-- .../polkadot/src/support/environment.rs | 8 +++---- .../polkadot/src/support/hashable.rs | 4 ++-- .../wasm-runtime/polkadot/src/support/mod.rs | 19 +++++++++++----- .../polkadot/src/support/storable.rs | 21 +++++++++--------- .../polkadot/src/support/testing.rs | 4 ++-- .../wasm-runtime/{support => std}/Cargo.toml | 2 +- .../wasm-runtime/{support => std}/src/lib.rs | 0 .../release/runtime_polkadot.compact.wasm | Bin 62629 -> 62629 bytes .../release/runtime_polkadot.wasm | Bin 62678 -> 62678 bytes substrate/wasm-runtime/test/Cargo.toml | 2 +- substrate/wasm-runtime/test/src/lib.rs | 4 ++-- 42 files changed, 126 insertions(+), 137 deletions(-) rename substrate/native-runtime/{support => std}/Cargo.toml (93%) rename substrate/native-runtime/{support => std}/src/lib.rs (100%) rename substrate/wasm-runtime/{support => std}/Cargo.toml (90%) rename substrate/wasm-runtime/{support => std}/src/lib.rs (100%) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index a7047446eb..6d5f20ecdf 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -558,7 +558,7 @@ dependencies = [ name = "native-runtime" version = "0.1.0" dependencies = [ - "runtime-support 0.1.0", + "runtime-std 0.1.0", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -737,7 +737,7 @@ dependencies = [ "polkadot-primitives 0.1.0", "polkadot-serializer 0.1.0", "polkadot-state-machine 0.1.0", - "runtime-support 0.1.0", + "runtime-std 0.1.0", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -921,7 +921,7 @@ dependencies = [ ] [[package]] -name = "runtime-support" +name = "runtime-std" version = "0.1.0" dependencies = [ "environmental 0.1.0", diff --git a/substrate/executor/Cargo.toml b/substrate/executor/Cargo.toml index 6164bb1c51..498482c03f 100644 --- a/substrate/executor/Cargo.toml +++ b/substrate/executor/Cargo.toml @@ -14,7 +14,7 @@ parity-wasm = "0.15.0" byteorder = "1.1" rustc-hex = "1.0.0" native-runtime = { path = "../native-runtime", version = "0.1" } -runtime-support = { path = "../native-runtime/support", version = "0.1" } +runtime-std = { path = "../native-runtime/std", version = "0.1" } memcmp = { version = "0.0.6" } [dev-dependencies] diff --git a/substrate/executor/src/lib.rs b/substrate/executor/src/lib.rs index 9bea6958de..cfb0506352 100644 --- a/substrate/executor/src/lib.rs +++ b/substrate/executor/src/lib.rs @@ -35,7 +35,7 @@ extern crate parity_wasm; extern crate byteorder; extern crate rustc_hex; extern crate native_runtime; -extern crate runtime_support; +extern crate runtime_std; extern crate memcmp; #[macro_use] diff --git a/substrate/executor/src/native_executor.rs b/substrate/executor/src/native_executor.rs index 2f050f77b7..0925762f74 100644 --- a/substrate/executor/src/native_executor.rs +++ b/substrate/executor/src/native_executor.rs @@ -4,7 +4,7 @@ use state_machine::{Externalities, CodeExecutor}; use error::{Error, ErrorKind, Result}; use wasm_executor::WasmExecutor; use native_runtime as runtime; -use runtime_support; +use runtime_std; pub struct NativeExecutor; @@ -22,7 +22,7 @@ impl CodeExecutor for NativeExecutor { // get a proper build script, this must be strictly adhered to or things will go wrong. let native_equivalent = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm"); if code == &native_equivalent[..] { - runtime_support::with_externalities(ext, || match method { + runtime_std::with_externalities(ext, || match method { "execute_block" => catch_unwind(|| runtime::execute_block(&data.0)).map_err(|_| ErrorKind::Runtime.into()), "execute_transaction" => catch_unwind(|| runtime::execute_transaction(&data.0)).map_err(|_| ErrorKind::Runtime.into()), _ => Err(ErrorKind::MethodNotFound(method.to_owned()).into()), @@ -37,11 +37,10 @@ impl CodeExecutor for NativeExecutor { #[cfg(test)] mod tests { use super::*; - use primitives::twox_128; - use native_runtime::testing::{TestExternalities, one, two}; - use native_runtime::statichex::StaticHexInto; - use native_runtime::keyedvec::KeyedVec; + use native_runtime::codec::KeyedVec; + use native_runtime::support::{TestExternalities, one, two, StaticHexInto}; use native_runtime::runtime::staking::balance; + use primitives::twox_128; fn tx() -> Vec<u8> { "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000".convert() } @@ -82,7 +81,7 @@ mod tests { let r = NativeExecutor.call(&mut t, &native_equivalent_code[..], "execute_transaction", &CallData(tx())); assert!(r.is_ok()); - runtime_support::with_externalities(&mut t, || { + runtime_std::with_externalities(&mut t, || { assert_eq!(balance(&one), 42); assert_eq!(balance(&two), 69); }); @@ -101,7 +100,7 @@ mod tests { let r = NativeExecutor.call(&mut t, &foreign_code[..], "execute_transaction", &CallData(tx())); assert!(r.is_ok()); - runtime_support::with_externalities(&mut t, || { + runtime_std::with_externalities(&mut t, || { assert_eq!(balance(&one), 42); assert_eq!(balance(&two), 69); }); diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index 8a70271c1a..c184abab89 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -274,8 +274,11 @@ mod tests { use super::*; use rustc_hex::FromHex; - use native_runtime::testing::TestExternalities; - use primitives::hashing::blake2_256; + use primitives::{blake2_256, twox_128}; + use runtime_std; + use native_runtime::support::{one, two, StaticHexInto, TestExternalities}; + use native_runtime::codec::KeyedVec; + use native_runtime::runtime::staking::balance; #[test] fn returning_should_work() { @@ -373,13 +376,6 @@ mod tests { ); } - use primitives::twox_128; - use native_runtime::testing::{one, two}; - use native_runtime::statichex::StaticHexInto; - use native_runtime::keyedvec::KeyedVec; - use native_runtime::runtime::staking::balance; - use runtime_support; - fn tx() -> Vec<u8> { "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000".convert() } #[test] @@ -407,7 +403,7 @@ mod tests { let r = WasmExecutor.call(&mut t, &foreign_code[..], "execute_transaction", &CallData(tx())); assert!(r.is_ok()); - runtime_support::with_externalities(&mut t, || { + runtime_std::with_externalities(&mut t, || { assert_eq!(balance(&one), 42); assert_eq!(balance(&two), 69); }); diff --git a/substrate/native-runtime/Cargo.toml b/substrate/native-runtime/Cargo.toml index eb5eb82408..25091c2cef 100644 --- a/substrate/native-runtime/Cargo.toml +++ b/substrate/native-runtime/Cargo.toml @@ -9,5 +9,5 @@ with-std = [] without-std = [] [dependencies] -runtime-support = { path = "./support", version = "0.1" } +runtime-std = { path = "./std", version = "0.1" } rustc-hex = "1.0" diff --git a/substrate/native-runtime/support/Cargo.toml b/substrate/native-runtime/std/Cargo.toml similarity index 93% rename from substrate/native-runtime/support/Cargo.toml rename to substrate/native-runtime/std/Cargo.toml index 1c24c014e6..0976e4b378 100644 --- a/substrate/native-runtime/support/Cargo.toml +++ b/substrate/native-runtime/std/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "runtime-support" +name = "runtime-std" version = "0.1.0" authors = ["Parity Technologies <admin@parity.io>"] diff --git a/substrate/native-runtime/support/src/lib.rs b/substrate/native-runtime/std/src/lib.rs similarity index 100% rename from substrate/native-runtime/support/src/lib.rs rename to substrate/native-runtime/std/src/lib.rs diff --git a/substrate/wasm-runtime/Cargo.lock b/substrate/wasm-runtime/Cargo.lock index d134139a3c..15ccc67c64 100644 --- a/substrate/wasm-runtime/Cargo.lock +++ b/substrate/wasm-runtime/Cargo.lock @@ -13,11 +13,11 @@ version = "0.1.0" name = "runtime-polkadot" version = "0.1.0" dependencies = [ - "runtime-support 0.1.0", + "runtime-std 0.1.0", ] [[package]] -name = "runtime-support" +name = "runtime-std" version = "0.1.0" dependencies = [ "pwasm-alloc 0.1.0", @@ -28,6 +28,6 @@ dependencies = [ name = "runtime-test" version = "0.1.0" dependencies = [ - "runtime-support 0.1.0", + "runtime-std 0.1.0", ] diff --git a/substrate/wasm-runtime/build.sh b/substrate/wasm-runtime/build.sh index c3030f99d3..2c78bc67c7 100755 --- a/substrate/wasm-runtime/build.sh +++ b/substrate/wasm-runtime/build.sh @@ -1,7 +1,7 @@ #!/bin/sh cargo +nightly build --target=wasm32-unknown-unknown --release -dirs=`find * -maxdepth 0 -type d | grep -v pwasm- | grep -v support` +dirs=`find * -maxdepth 0 -type d | grep -v pwasm- | grep -v std` for i in $dirs do if [[ -e $i/Cargo.toml ]] diff --git a/substrate/wasm-runtime/polkadot/Cargo.toml b/substrate/wasm-runtime/polkadot/Cargo.toml index ce2d9909a7..669ccac6fa 100644 --- a/substrate/wasm-runtime/polkadot/Cargo.toml +++ b/substrate/wasm-runtime/polkadot/Cargo.toml @@ -7,7 +7,7 @@ authors = ["Parity Technologies <admin@parity.io>"] crate-type = ["cdylib"] [dependencies] -runtime-support = { path = "../support", version = "0.1" } +runtime-std = { path = "../std", version = "0.1" } [features] default = ["without-std"] diff --git a/substrate/wasm-runtime/polkadot/src/codec/joiner.rs b/substrate/wasm-runtime/polkadot/src/codec/joiner.rs index 7fdb1e1645..a7a9f618eb 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/joiner.rs +++ b/substrate/wasm-runtime/polkadot/src/codec/joiner.rs @@ -16,8 +16,8 @@ //! Vec<u8> serialiser. -use runtime_support::prelude::*; -use slicable::Slicable; +use runtime_std::prelude::*; +use super::slicable::Slicable; /// Trait to allow itself to be serialised into a `Vec<u8>` pub trait Joiner { diff --git a/substrate/wasm-runtime/polkadot/src/codec/keyedvec.rs b/substrate/wasm-runtime/polkadot/src/codec/keyedvec.rs index 210606ab7c..2c55cb5648 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/keyedvec.rs +++ b/substrate/wasm-runtime/polkadot/src/codec/keyedvec.rs @@ -16,8 +16,8 @@ //! Serialiser and prepender. -use runtime_support::prelude::*; -use slicable::Slicable; +use runtime_std::prelude::*; +use super::slicable::Slicable; /// Trait to allow itselg to be serialised and prepended by a given slice. pub trait KeyedVec { diff --git a/substrate/wasm-runtime/polkadot/src/codec/mod.rs b/substrate/wasm-runtime/polkadot/src/codec/mod.rs index 7d9bc90c4f..94afc574c1 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/codec/mod.rs @@ -16,8 +16,14 @@ //! Codec utils. -pub mod endiansensitive; -pub mod streamreader; -pub mod joiner; -pub mod slicable; -pub mod keyedvec; +mod endiansensitive; +mod slicable; +mod streamreader; +mod joiner; +mod keyedvec; + +pub use self::endiansensitive::EndianSensitive; +pub use self::slicable::{Slicable, NonTrivialSlicable}; +pub use self::streamreader::StreamReader; +pub use self::joiner::Joiner; +pub use self::keyedvec::KeyedVec; diff --git a/substrate/wasm-runtime/polkadot/src/codec/slicable.rs b/substrate/wasm-runtime/polkadot/src/codec/slicable.rs index c702741ee3..3ac3d880e4 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/slicable.rs +++ b/substrate/wasm-runtime/polkadot/src/codec/slicable.rs @@ -16,10 +16,10 @@ //! Serialisation. -use runtime_support::prelude::*; -use runtime_support::{mem, slice}; -use joiner::Joiner; -use endiansensitive::EndianSensitive; +use runtime_std::prelude::*; +use runtime_std::{mem, slice}; +use super::joiner::Joiner; +use super::endiansensitive::EndianSensitive; /// Trait that allows zero-copy read/write of value-references to/from slices in LE format. pub trait Slicable: Sized { diff --git a/substrate/wasm-runtime/polkadot/src/codec/streamreader.rs b/substrate/wasm-runtime/polkadot/src/codec/streamreader.rs index 33056a5ac3..b745f8afd9 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/streamreader.rs +++ b/substrate/wasm-runtime/polkadot/src/codec/streamreader.rs @@ -16,7 +16,7 @@ //! Deserialiser. -use slicable::Slicable; +use super::slicable::Slicable; /// Simple deserialiser. pub struct StreamReader<'a> { diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 9389145843..43830a05b0 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -20,23 +20,19 @@ #![cfg_attr(feature = "strict", deny(warnings))] #[macro_use] -extern crate runtime_support; +extern crate runtime_std; #[cfg(feature = "with-std")] extern crate rustc_hex; -mod codec; +pub mod codec; #[macro_use] -mod support; +pub mod support; pub mod primitives; pub mod runtime; -pub use codec::{endiansensitive, streamreader, joiner, slicable, keyedvec}; -pub use support::{environment, storable, hashable}; -#[cfg(feature = "with-std")] -pub use support::{testing, statichex}; -use runtime_support::prelude::*; -use slicable::Slicable; +use runtime_std::prelude::*; +use codec::Slicable; use primitives::{Block, UncheckedTransaction}; /// Execute a block, with `input` being the canonical serialisation of the block. Returns the diff --git a/substrate/wasm-runtime/polkadot/src/primitives/block.rs b/substrate/wasm-runtime/polkadot/src/primitives/block.rs index 2975286479..d33b51609c 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/block.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/block.rs @@ -16,10 +16,8 @@ //! Block type. -use runtime_support::prelude::*; -use streamreader::StreamReader; -use joiner::Joiner; -use slicable::{Slicable, NonTrivialSlicable}; +use runtime_std::prelude::*; +use codec::{StreamReader, Joiner, Slicable, NonTrivialSlicable}; use primitives::{Header, UncheckedTransaction}; /// A Polkadot relay chain block. diff --git a/substrate/wasm-runtime/polkadot/src/primitives/digest.rs b/substrate/wasm-runtime/polkadot/src/primitives/digest.rs index b51bc8df54..18107460b0 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/digest.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/digest.rs @@ -16,7 +16,7 @@ //! Digest type. -use runtime_support::prelude::*; +use runtime_std::prelude::*; #[derive(Clone, Default)] #[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] diff --git a/substrate/wasm-runtime/polkadot/src/primitives/function.rs b/substrate/wasm-runtime/polkadot/src/primitives/function.rs index 875bb98326..112c6e8b80 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/function.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/function.rs @@ -17,7 +17,7 @@ //! Function data: This describes a function that can be called from an external transaction. use primitives::AccountID; -use streamreader::StreamReader; +use codec::StreamReader; use runtime::{staking, session, timestamp, governance}; /// Public functions that can be dispatched to. diff --git a/substrate/wasm-runtime/polkadot/src/primitives/header.rs b/substrate/wasm-runtime/polkadot/src/primitives/header.rs index 76f3c012d1..c97d5ebf29 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/header.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/header.rs @@ -16,11 +16,9 @@ //! Block header type. -use runtime_support::prelude::*; -use streamreader::StreamReader; -use joiner::Joiner; -use slicable::{Slicable, NonTrivialSlicable}; -use runtime_support::mem; +use runtime_std::prelude::*; +use codec::{StreamReader, Joiner, Slicable, NonTrivialSlicable}; +use runtime_std::mem; use primitives::{BlockNumber, Hash, Digest}; #[derive(Clone)] diff --git a/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs b/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs index 663692a4f7..a4a2a3106b 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs @@ -17,11 +17,9 @@ //! Proposal: This describes a combination of a function ID and data that can be used to call into //! an internal function. -use runtime_support::prelude::*; -use runtime_support::mem; -use slicable::Slicable; -use joiner::Joiner; -use streamreader::StreamReader; +use runtime_std::prelude::*; +use runtime_std::mem; +use codec::{Slicable, Joiner, StreamReader}; use runtime::{system, governance, staking, session}; /// Internal functions that can be dispatched to. diff --git a/substrate/wasm-runtime/polkadot/src/primitives/tests.rs b/substrate/wasm-runtime/polkadot/src/primitives/tests.rs index 76412c10b9..fdb600a5bb 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/tests.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/tests.rs @@ -17,10 +17,9 @@ //! Tests. use super::*; -use runtime_support::prelude::*; -use joiner::Joiner; -use slicable::{Slicable, NonTrivialSlicable}; -use function::Function; +use runtime_std::prelude::*; +use codec::{Joiner, Slicable}; +use primitives::Function; #[test] fn serialise_transaction_works() { diff --git a/substrate/wasm-runtime/polkadot/src/primitives/transaction.rs b/substrate/wasm-runtime/polkadot/src/primitives/transaction.rs index 96dba4e6fb..9c72e31d34 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/transaction.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/transaction.rs @@ -16,12 +16,10 @@ //! Transaction type. -use runtime_support::prelude::*; -use streamreader::StreamReader; -use joiner::Joiner; -use slicable::{Slicable, NonTrivialSlicable}; +use runtime_std::prelude::*; +use codec::{StreamReader, Joiner, Slicable, NonTrivialSlicable}; use primitives::{AccountID, TxOrder, Function}; -use runtime_support::mem; +use runtime_std::mem; /// A vetted and verified transaction from the external world. #[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] diff --git a/substrate/wasm-runtime/polkadot/src/primitives/uncheckedtransaction.rs b/substrate/wasm-runtime/polkadot/src/primitives/uncheckedtransaction.rs index bf3669ec95..ec14befb55 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/uncheckedtransaction.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/uncheckedtransaction.rs @@ -16,12 +16,10 @@ //! Unchecked Transaction type. -use slicable::{Slicable, NonTrivialSlicable}; -use streamreader::StreamReader; -use joiner::Joiner; +use runtime_std::{mem, ed25519_verify}; +use runtime_std::prelude::*; +use codec::{Slicable, NonTrivialSlicable, StreamReader, Joiner}; use primitives::Transaction; -use runtime_support::{mem, ed25519_verify}; -use runtime_support::prelude::*; #[cfg(feature = "with-std")] use std::fmt; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs b/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs index 689fdca21e..7d7a0f5ec5 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs @@ -16,8 +16,8 @@ //! Conensus module for runtime; manages the authority set ready for the native code. -use runtime_support::prelude::*; -use storable::StorageVec; +use runtime_std::prelude::*; +use support::StorageVec; use primitives::SessionKey; struct AuthorityStorageVec {} diff --git a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs index 307e4bfa00..85a24196bb 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs @@ -25,9 +25,9 @@ //! At the end of the era, all validators approvals are tallied and if there are sufficient to pass //! the proposal then it is enacted. All items in storage concerning the proposal are reset. -use runtime_support::prelude::*; -use keyedvec::KeyedVec; -use storable::{Storable, StorageVec, kill}; +use runtime_std::prelude::*; +use codec::KeyedVec; +use support::{Storable, StorageVec, kill}; use primitives::{AccountID, Hash, BlockNumber, Proposal}; use runtime::{staking, system, session}; @@ -105,7 +105,7 @@ pub fn end_of_an_era() { #[cfg(test)] mod tests { use super::*; - use runtime_support::{with_externalities, twox_128}; + use runtime_std::{with_externalities, twox_128}; use keyedvec::KeyedVec; use joiner::Joiner; use testing::{one, two, TestExternalities}; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs index fdce6e167e..d6dc1e3764 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -17,9 +17,9 @@ //! Session manager: is told the validators and allows them to manage their session keys for the //! consensus module. -use runtime_support::prelude::*; -use keyedvec::KeyedVec; -use storable::{kill, Storable, StorageVec}; +use runtime_std::prelude::*; +use codec::KeyedVec; +use support::{kill, Storable, StorageVec}; use primitives::{AccountID, SessionKey, BlockNumber}; use runtime::{system, staking, consensus}; @@ -118,7 +118,7 @@ fn rotate_session() { #[cfg(test)] mod tests { - use runtime_support::{with_externalities, twox_128}; + use runtime_std::{with_externalities, twox_128}; use keyedvec::KeyedVec; use joiner::Joiner; use testing::{one, two, TestExternalities}; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index d9755b55a6..b87d26c360 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -16,10 +16,10 @@ //! Staking manager: Handles balances and periodically determines the best set of validators. -use runtime_support::prelude::*; -use runtime_support::cell::RefCell; -use keyedvec::KeyedVec; -use storable::{Storable, StorageVec}; +use runtime_std::prelude::*; +use runtime_std::cell::RefCell; +use codec::KeyedVec; +use support::{Storable, StorageVec}; use primitives::{BlockNumber, AccountID}; use runtime::{system, session, governance}; @@ -190,7 +190,7 @@ fn new_era() { #[cfg(test)] mod tests { - use runtime_support::{with_externalities, twox_128}; + use runtime_std::{with_externalities, twox_128}; use keyedvec::KeyedVec; use joiner::Joiner; use testing::{one, two, TestExternalities}; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index e37cc3cb32..d6236beb78 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -17,14 +17,11 @@ //! System manager: Handles all of the top-level stuff; executing block/transaction, setting code //! and depositing logs. +use runtime_std::prelude::*; +use runtime_std::{mem, print}; +use codec::KeyedVec; +use support::{Hashable, Storable, with_env}; use primitives::{Block, BlockNumber, Hash, UncheckedTransaction, TxOrder}; -use runtime_support::mem; -use runtime_support::prelude::*; -use runtime_support::print; -use hashable::Hashable; -use storable::Storable; -use keyedvec::KeyedVec; -use environment::with_env; use runtime::{staking, session}; /// The current block number being processed. Set by `execute_block`. @@ -120,7 +117,7 @@ mod tests { use function::Function; use keyedvec::KeyedVec; use slicable::Slicable; - use runtime_support::{with_externalities, twox_128}; + use runtime_std::{with_externalities, twox_128}; use primitives::{UncheckedTransaction, Transaction}; use statichex::StaticHexInto; use runtime::{system, staking}; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs index 7040473b1a..09fb36a606 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs @@ -16,7 +16,7 @@ //! Timestamp manager: just handles the current timestamp. -use storable::Storable; +use support::Storable; /// Representation of a time. pub type Timestamp = u64; @@ -35,7 +35,7 @@ pub fn set(now: Timestamp) { mod tests { use joiner::Joiner; use keyedvec::KeyedVec; - use runtime_support::{with_externalities, twox_128}; + use runtime_std::{with_externalities, twox_128}; use runtime::timestamp; use testing::TestExternalities; diff --git a/substrate/wasm-runtime/polkadot/src/support/environment.rs b/substrate/wasm-runtime/polkadot/src/support/environment.rs index 1011b3168b..7670a4801f 100644 --- a/substrate/wasm-runtime/polkadot/src/support/environment.rs +++ b/substrate/wasm-runtime/polkadot/src/support/environment.rs @@ -16,10 +16,10 @@ //! Environment API: Allows certain information to be accessed throughout the runtime. -use runtime_support::boxed::Box; -use runtime_support::mem; -use runtime_support::cell::RefCell; -use runtime_support::rc::Rc; +use runtime_std::boxed::Box; +use runtime_std::mem; +use runtime_std::cell::RefCell; +use runtime_std::rc::Rc; use primitives::{BlockNumber, Digest}; diff --git a/substrate/wasm-runtime/polkadot/src/support/hashable.rs b/substrate/wasm-runtime/polkadot/src/support/hashable.rs index 31c133c3c3..66c3844fda 100644 --- a/substrate/wasm-runtime/polkadot/src/support/hashable.rs +++ b/substrate/wasm-runtime/polkadot/src/support/hashable.rs @@ -16,8 +16,8 @@ //! Hashable trait. -use slicable::Slicable; -use runtime_support::{blake2_256, twox_128, twox_256}; +use codec::Slicable; +use runtime_std::{blake2_256, twox_128, twox_256}; pub trait Hashable: Sized { fn blake2_256(&self) -> [u8; 32]; diff --git a/substrate/wasm-runtime/polkadot/src/support/mod.rs b/substrate/wasm-runtime/polkadot/src/support/mod.rs index c2e034c527..854a8f9f01 100644 --- a/substrate/wasm-runtime/polkadot/src/support/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/support/mod.rs @@ -16,12 +16,19 @@ //! Support code for the runtime. -pub mod environment; -pub mod storable; -pub mod hashable; - +mod environment; +mod storable; +mod hashable; #[cfg(feature = "with-std")] -pub mod statichex; +mod statichex; #[macro_use] #[cfg(feature = "with-std")] -pub mod testing; +mod testing; + +pub use self::environment::{Environment, with_env}; +pub use self::storable::{StorageVec, Storable, kill}; +pub use self::hashable::Hashable; +#[cfg(feature = "with-std")] +pub use self::statichex::{StaticHexConversion, StaticHexInto}; +#[cfg(feature = "with-std")] +pub use self::testing::{AsBytesRef, HexDisplay, TestExternalities, one, two}; diff --git a/substrate/wasm-runtime/polkadot/src/support/storable.rs b/substrate/wasm-runtime/polkadot/src/support/storable.rs index 2af5c83a2d..97f6384c10 100644 --- a/substrate/wasm-runtime/polkadot/src/support/storable.rs +++ b/substrate/wasm-runtime/polkadot/src/support/storable.rs @@ -16,10 +16,9 @@ //! Stuff to do with the runtime's storage. -use slicable::Slicable; -use keyedvec::KeyedVec; -use runtime_support::prelude::*; -use runtime_support::{self, twox_128}; +use runtime_std::prelude::*; +use runtime_std::{self, twox_128}; +use codec::{Slicable, KeyedVec}; /// Trait for a value which may be stored in the storage DB. pub trait Storable { @@ -51,23 +50,23 @@ pub trait Storable { /// Remove `key` from storage. pub fn kill(key: &[u8]) { - runtime_support::set_storage(&twox_128(key)[..], b""); + runtime_std::set_storage(&twox_128(key)[..], b""); } impl<T: Sized + Slicable> Storable for T { fn lookup(key: &[u8]) -> Option<Self> { Slicable::set_as_slice(&|out, offset| - runtime_support::read_storage(&twox_128(key)[..], out, offset) >= out.len() + runtime_std::read_storage(&twox_128(key)[..], out, offset) >= out.len() ) } fn store(&self, key: &[u8]) { - self.as_slice_then(|slice| runtime_support::set_storage(&twox_128(key)[..], slice)); + self.as_slice_then(|slice| runtime_std::set_storage(&twox_128(key)[..], slice)); } } impl Storable for [u8] { fn store(&self, key: &[u8]) { - runtime_support::set_storage(&twox_128(key)[..], self) + runtime_std::set_storage(&twox_128(key)[..], self) } } @@ -110,9 +109,9 @@ pub trait StorageVec { mod tests { use super::*; use std::collections::HashMap; - use runtime_support::with_externalities; + use runtime_std::with_externalities; use testing::{TestExternalities, HexDisplay}; - use runtime_support::{storage, twox_128}; + use runtime_std::{storage, twox_128}; #[test] fn integers_can_be_stored() { @@ -153,7 +152,7 @@ mod tests { fn vecs_can_be_retrieved() { let mut t = TestExternalities { storage: HashMap::new(), }; with_externalities(&mut t, || { - runtime_support::set_storage(&twox_128(b":test"), b"\x0b\0\0\0Hello world"); + runtime_std::set_storage(&twox_128(b":test"), b"\x0b\0\0\0Hello world"); let x = b"Hello world".to_vec(); println!("Hex: {}", HexDisplay::from(&storage(&twox_128(b":test")))); let y = <Vec<u8>>::lookup(b":test").unwrap(); diff --git a/substrate/wasm-runtime/polkadot/src/support/testing.rs b/substrate/wasm-runtime/polkadot/src/support/testing.rs index 63aca0f8ae..e0e1a336c8 100644 --- a/substrate/wasm-runtime/polkadot/src/support/testing.rs +++ b/substrate/wasm-runtime/polkadot/src/support/testing.rs @@ -16,10 +16,10 @@ //! Testing helpers. -use runtime_support::{Externalities, ExternalitiesError}; use std::collections::HashMap; +use runtime_std::{Externalities, ExternalitiesError}; use primitives::AccountID; -use statichex::StaticHexInto; +use super::statichex::StaticHexInto; #[derive(Debug, Default)] /// Simple externaties implementation. diff --git a/substrate/wasm-runtime/support/Cargo.toml b/substrate/wasm-runtime/std/Cargo.toml similarity index 90% rename from substrate/wasm-runtime/support/Cargo.toml rename to substrate/wasm-runtime/std/Cargo.toml index 828fdab534..802d1fabde 100644 --- a/substrate/wasm-runtime/support/Cargo.toml +++ b/substrate/wasm-runtime/std/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "runtime-support" +name = "runtime-std" version = "0.1.0" authors = ["Parity Technologies <admin@parity.io>"] diff --git a/substrate/wasm-runtime/support/src/lib.rs b/substrate/wasm-runtime/std/src/lib.rs similarity index 100% rename from substrate/wasm-runtime/support/src/lib.rs rename to substrate/wasm-runtime/std/src/lib.rs diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm index 63473ae445f0cf1d236ec0fc3f22f4d9baee3730..1f94e5511576c6db6c3f58819f74307aa2d7cf0c 100644 GIT binary patch delta 971 zcmZuvZAep57{2H1&Z$@1UGsChO9S(3x;0I7R?r}&BJoE-Nq#h!mb5w3<rijyhFGa( zC!-=rN+FX%JM{5$sS)*~4_XQpNDzWLVWCC!qk7M^=uh{@^PKa%&--y+?(n=~cwRBq zkHRB)p2s+xCs)vSltV2MTM&Jzuq);Bu`n_xI#4dzrRhgL`a#2EWTqdr5=J8V8M^^( zq$zP2ksIm)Fuhkd0hWsF+$~np)c7KducZ@LqL0yXVjmDarORL{y(?v^@hu&BXZ(hG z$eS!HV03m5@{z0AR=_}Z9$wK=!K6ZXP$Dtr0dUh%^L@m!sx7D4b;(kTNk)DVlN$2l z(Ph$|Z&ZbJVk##*B1Wr)EarDWu_FZ!0F$f_0cWhQ!vm6-#tAkb87sU4Qsw4&x@XfX ztn@LRdN!9uAQO49JqKQbik1Pt6deaVT3m;;^lkC1nhzLkDpJ3*gfx^XY2?1^Jjx@t z4`hHTaG(`wNlE!MvXGRD9Z=p?u^$iV$<vDUXcL{U2*W6khN`4BXf2JdAL5aQ-fNuU zaZsXXTa*Y&^tb+E*v9s$Z2yFE=|a1Q1*$r_0OvZU07p+e26T1yK=?=JE)`p9ahIKE zJaVQRN15P-uhQ8=MHAWDo5q$@+q?JQ<0pDYSyOjkqza~Q9~ft;*_R5!7$3eim4I?+ z*8M|*_V2pnt%)h}=5G2eEP2|Wgy3iR`nVc~DVuNuKAX4zSU%|id_8$l)?EsPm`kRo zM&Ras0xlYQaxMkc6YoM-tT-6W$sc3PPBs{|Z*g~gNGFJ15H+BUD>zOm2fgI;VqE&5 zUciOPoNY)iB>2H&gjnd0w-j+)tnBsci8*M-Aw4-5j6La-goNZZtM#@4Yr*pzI!4Ie zK}pa!><xBDou@6?-CWaH>vXqpHoqijopsfAr_=2)H`-gOnrj@U#wN}d_)oPcsFo;K z3qtff^k8%OS9?Zt{{}m6kO%V{*kD4yAgDZbuEJ)!lgtL=lB|%lx``Eokl<BwTqY<7 Tf!6`=BQZ-xR7tlj)u?_05KtpT delta 1000 zcmZWnZAg<*6u#%~om1a*uQ``)@6y0h^JA{2*%vfO(;y-U%F=W$4Qp#<OG`?GLi(7d zU5koBsQgh<n3oFrQ|Y9SA7x|~{?Q^LO<~ZAilEM2MNog9=iGar^PGFmz1<U<?g>qA z2SiHIk|a?Y$<D%8SjcTr%YZ-CIJMz;cLaNrPylvjHts<@VHEL0;}&*N@4_fT>3|SF zqev8T`GuJ(g*bM{Fc)lm+(3cPn^j2ZPzLiP9TxO4sSSxAGG&NeeqEifr+zaV&HMsE z_B?AbVobIl-m`PrixG#j^XMxxmveML+bzssJ%wuCW4#F?tIBp%ET?TXly?;jQ7NP< zX>6T+mC0|;r->=VLG!60g<uf5J)fo{e`kI6Oge04WA;7>v6FeX5KHoJBf_F*kpYX6 zMr22bjV`)2OSlo45IL666)8{{gGLIKxo>G{6j<4ll?$+aDEx@{sc<jij-pyn_=}=3 zy%aJzbZlqI8n&xc%cD1RNsz;?Zq7i_@aBD>ur*~Puz;nO7h_>h`9|8QvIpgJAdgR! zM^MP&!3s4N;(5%@%M#4weRVG-dd9?$H)sJZI`;h#xL-Vnw(%|4`DCL{98?@=L40>0 zfY@{JKBA||kH_DdR_nyLi&~tL;48<D&>2>2bSPc4s94$Z)-*BEn%4DyXVBl;BZ_+4 zqIG!t##1*$YWC@Z2*KOV2NLmnWZm2<$N!mHcwS0scz~Dg*+lZly=1@-@%ergUZ%9) zi}<MjBx2cs5AoSRXL#SE(I|E{61ak^=0Q~P;NXc=*v*<JTP%sWF@$6iLMoBtkk<ks z3CP6JYhrCvRyuBCcc&84LMB<~tMx3Yce?SVO|qiI3Kb!OsR$f?vs}#duZxq2W7sS! z!QYNIG=ylwf*@=9U`%gUWx52vOQ$L)=3;WVI`Ti&)nC<BQGI&|we7z(y~y$C_ZX{2 zg?-yCa-7S#%jv51?N9O6SJ&0Jy$#raMUHpZRyo~nughBJY^bQOcIDLVA&!9Mf43Rv omV|C>Y|5Ct41-@ig;3h8CuBbER3gtt-oy;knc(CrrmJ;70gEmw761SM diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm index f2492b00ecb4b75e28bc85cbdcbc45b7138c0af6..4fa5a8ae0d5e9a9f09ccbe1329f4a5a79f3bfca7 100644 GIT binary patch delta 950 zcmZuvT}V_>5WaKvuGhSlcQakxy;};Fn(3yQf0eY5_CrxnVm~UH83_K=x@wl14~tZ2 zS<{b&*#-th6v@d-2--{|>cwC&=m&{<sa6o|L3*({x5Ags!#8tg=9}})a3;Q)Ccc>- zT!7FpS(X_KmH9PT3b2L`v+E&-Sq~h;)|xTgQVE%O#Bv_IoGq3atmeuRoq>i4(aRy7 zZ;NJtuOf1&2($*mMoswlwKBflx{I;CB<zp%3X@<vONKwRC5tGZ)K^BZ+cs2J%|aK- zskwytsa@d3H{^TCk4AgiGWOHP*QY7Kd^#35FA;-(bPj=FV)|)uU7B&2;r{Fb5xSXe zg<c%aPEn?9TB4*r!IIo`)N@*?;nkc+gu8Md6Ncu!4Grj8lBBx4_&M($h0d+Ba&P81 zGkZmx-&(hC0XT7PQwB|wQ7}WeqOg&$udo^-dC2C;2sz+zDR^V+4t%y-;Twvt%aDa1 z4kS~Nx#So`VtdI1WMEP07HZ#Lx|a>uakexb)^b}}2!kvhU#>5L#XP@mKn4r{;(jNy zpw6E*n}J%49Ger^B6gZ}{3~Q~`w5Ro^t5&oTH8hmKejz5>~HU)bjrzXidbxOXN4^6 z`!lClxRWLvPZEP_POR%r6id3&y=Q*-neMydQQz4xh1B1@G$^QLmvcgd?d=<lq2EwC zbV!Z-w=QFA+Hzxa0e`w6E6<k!eTc-7gCyq6NIl`Nkqd;~FFb^7^r8{3HJP+bRL1Vm zZE%dLc>K$A2~dZF-#eo;-$Kba!ZP8xNb0j6+l!`cs@6e43&jRal4LfL9d^}HQ+=?q z-d*K%S2Z-&c+%VrlFMgTSzesv8nCM|ej=q%@$_HvPLQN1gY36sdC<wG?RY*ImF?Bl zn7BoM9@t1Wl4@R)gat;ePggCK6-O#6t354o^-Wdo!!`BIlFP5-r=T@I@E>kCabpc` zkg`40QK<0$ePLcjkHb*mcL)_~z@aLh>e{@fiW=0Wq9GR(ryNj>1yd<d#*a=_DZc@H CX&X2I delta 981 zcmZWnU2IH26rMACyLa`{-l}ffyLV}m(yh|nuI?&IY@(D962x!IT9s6mQq}sGh&0HS z)l)waEe|}1h}I~Ph@W<e@KQ-rf&}5gU!{qC5Rq_Z5eYBfch1Z?-#2q+`rljn-&;Cb zz@{WCio&@~oPv=6CE^BevnHqv1Sb2E&}J_M9|r7O2)h#TXL}VsNDWawPCp89aZ6V? z6pNnWCWkb9HDWY)g*AhNn47tP^WFk%&)zR7&p1pZt{Me$RlGFErt*jbwQ*lz5S8(h z2&avYz&m_I@jHs`=qMV+pE^WYkqSKO#B%pB>JTs7T_8KL_@GQjde?E$TiVN&xT(8v zU&$;Z;_&mV92VeyJ|c%vU|a9!F5>U_rlgSfIZ*dqfjIW~t`Y9=UnlfVd~Az3br;hD zanwpLWlA-sF{Y(3K0OD@hmnxZHF18*vLWEXA2Yl(0&n>j!Z9<q5}uw}1G=!zdYP)k zjev@0X3xXh3so_7Nt*(0e7>T9ijr1t10DCQ?1u@sxUzzb+bfsyRujKg=7L`sRaOpe zk-OSVfpjr#<2eO}i#K&o6n@eWHye|HB)Yf#khonwiGRmi@CnDxdbttZ)kK)NJ4X0o z_g%vFJrUY2+&f2=BX4X9Dw3ZaI>3i|=%T$Yc}3lW8=LdxL{Bs?`a6R!%@?KV*~7^y zo&MsnPT5*@ywocB<mp%zl!(f%wOab0sU_y6k4_A*?@qC7R_~4i`V{%yYv?eCx@!r) zb+-^U_tX>eSZiW^gT<ozP`!77vd(){C35c{$%D<<`Ju^~<r&6UA!BScaT@V_U@U`} z1v(78{mIQ=894YUBR_6vYJJUy$qm6Uy|kg}dWx)KOfr{2AmY#}aQf?tY!>KqX!_u9 z#ZC)jNr{3%y!_GbikcdqOy8x|)UrI(oNy=p$KCwpZc6v{ajK2}uIV67C%uQ{IwYYR zb!us$;HF@xrha=)Z9{e4x^QhHUBIcOhildZ!{OSHyDr$cs-ZemRJVl%V$T27hLTz~ Zsi8h#hce6`aKdsdA1H*N*gR0J{seXGB}o7P diff --git a/substrate/wasm-runtime/test/Cargo.toml b/substrate/wasm-runtime/test/Cargo.toml index 57015d2683..c7191fb805 100644 --- a/substrate/wasm-runtime/test/Cargo.toml +++ b/substrate/wasm-runtime/test/Cargo.toml @@ -7,4 +7,4 @@ authors = ["Parity Technologies <admin@parity.io>"] crate-type = ["cdylib"] [dependencies] -runtime-support = { path = "../support", version = "0.1" } +runtime-std = { path = "../std", version = "0.1" } diff --git a/substrate/wasm-runtime/test/src/lib.rs b/substrate/wasm-runtime/test/src/lib.rs index caa34856f4..c63ca73fca 100644 --- a/substrate/wasm-runtime/test/src/lib.rs +++ b/substrate/wasm-runtime/test/src/lib.rs @@ -7,8 +7,8 @@ extern crate alloc; use alloc::vec::Vec; #[macro_use] -extern crate runtime_support; -use runtime_support::{set_storage, storage, print, blake2_256, twox_128, twox_256, ed25519_verify}; +extern crate runtime_std; +use runtime_std::{set_storage, storage, print, blake2_256, twox_128, twox_256, ed25519_verify}; fn test_blake2_256(input: &[u8]) -> Vec<u8> { blake2_256(&input).to_vec() From bc6eb7d70a097b619ea2f3f6203df48b285839fc Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Sun, 28 Jan 2018 13:48:24 +0100 Subject: [PATCH 097/112] Refactor executor. --- substrate/executor/src/native_executor.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/substrate/executor/src/native_executor.rs b/substrate/executor/src/native_executor.rs index 0925762f74..3018157001 100644 --- a/substrate/executor/src/native_executor.rs +++ b/substrate/executor/src/native_executor.rs @@ -8,6 +8,10 @@ use runtime_std; pub struct NativeExecutor; +fn safe_call<F: ::std::panic::UnwindSafe + FnOnce() -> Vec<u8>>(f: F) -> Result<Vec<u8>> { + catch_unwind(f).map_err(|_| ErrorKind::Runtime.into()) +} + impl CodeExecutor for NativeExecutor { type Error = Error; @@ -23,8 +27,8 @@ impl CodeExecutor for NativeExecutor { let native_equivalent = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm"); if code == &native_equivalent[..] { runtime_std::with_externalities(ext, || match method { - "execute_block" => catch_unwind(|| runtime::execute_block(&data.0)).map_err(|_| ErrorKind::Runtime.into()), - "execute_transaction" => catch_unwind(|| runtime::execute_transaction(&data.0)).map_err(|_| ErrorKind::Runtime.into()), + "execute_block" => safe_call(|| runtime::execute_block(&data.0)), + "execute_transaction" => safe_call(|| runtime::execute_transaction(&data.0)), _ => Err(ErrorKind::MethodNotFound(method.to_owned()).into()), }) } else { From 59469995b214b98fbde40487a990dbc54ff9563c Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Sun, 28 Jan 2018 14:36:40 +0100 Subject: [PATCH 098/112] Introduce module structure over comments. --- substrate/wasm-runtime/polkadot/src/lib.rs | 4 +- .../polkadot/src/primitives/function.rs | 29 +- .../polkadot/src/primitives/proposal.rs | 27 +- .../polkadot/src/runtime/consensus.rs | 22 +- .../polkadot/src/runtime/governance.rs | 175 +++++----- .../polkadot/src/runtime/session.rs | 169 +++++----- .../polkadot/src/runtime/staking.rs | 301 +++++++++--------- .../polkadot/src/runtime/system.rs | 131 ++++---- .../polkadot/src/runtime/timestamp.rs | 24 +- .../polkadot/src/support/storable.rs | 4 +- 10 files changed, 460 insertions(+), 426 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 43830a05b0..1eeff3c649 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -38,14 +38,14 @@ use primitives::{Block, UncheckedTransaction}; /// Execute a block, with `input` being the canonical serialisation of the block. Returns the /// empty vector. pub fn execute_block(input: &[u8]) -> Vec<u8> { - runtime::system::execute_block(Block::from_slice(input).unwrap()); + runtime::system::internal::execute_block(Block::from_slice(input).unwrap()); Vec::new() } /// Execute a given, serialised, transaction. Returns the empty vector. pub fn execute_transaction(input: &[u8]) -> Vec<u8> { let utx = UncheckedTransaction::from_slice(input).unwrap(); - runtime::system::execute_transaction(&utx); + runtime::system::internal::execute_transaction(&utx); Vec::new() } diff --git a/substrate/wasm-runtime/polkadot/src/primitives/function.rs b/substrate/wasm-runtime/polkadot/src/primitives/function.rs index 112c6e8b80..35273e2cfa 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/function.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/function.rs @@ -23,14 +23,15 @@ use runtime::{staking, session, timestamp, governance}; /// Public functions that can be dispatched to. #[derive(Clone, Copy)] #[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] +#[repr(u8)] pub enum Function { - StakingStake, - StakingUnstake, - StakingTransfer, - SessionSetKey, - TimestampSet, - GovernancePropose, - GovernanceApprove, + StakingStake = 0, + StakingUnstake = 1, + StakingTransfer = 2, + SessionSetKey = 3, + TimestampSet = 4, + GovernancePropose = 5, + GovernanceApprove = 6, } impl Function { @@ -55,31 +56,31 @@ impl Function { let mut params = StreamReader::new(data); match *self { Function::StakingStake => { - staking::stake(transactor); + staking::public::stake(transactor); } Function::StakingUnstake => { - staking::unstake(transactor); + staking::public::unstake(transactor); } Function::StakingTransfer => { let dest = params.read().unwrap(); let value = params.read().unwrap(); - staking::transfer(transactor, &dest, value); + staking::public::transfer(transactor, &dest, value); } Function::SessionSetKey => { let session = params.read().unwrap(); - session::set_key(transactor, &session); + session::public::set_key(transactor, &session); } Function::TimestampSet => { let t = params.read().unwrap(); - timestamp::set(t); + timestamp::public::set(t); } Function::GovernancePropose => { let proposal = params.read().unwrap(); - governance::propose(transactor, &proposal); + governance::public::propose(transactor, &proposal); } Function::GovernanceApprove => { let era_index = params.read().unwrap(); - governance::approve(transactor, era_index); + governance::public::approve(transactor, era_index); } } } diff --git a/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs b/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs index a4a2a3106b..33539c2f17 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs @@ -25,13 +25,14 @@ use runtime::{system, governance, staking, session}; /// Internal functions that can be dispatched to. #[derive(Clone, Copy)] #[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] +#[repr(u8)] pub enum InternalFunction { - SystemSetCode, - StakingSetSessionsPerEra, - StakingSetBondingDuration, - StakingSetValidatorCount, - GovernanceSetApprovalPpmRequired, - SessionSetLength, + SystemSetCode = 0, + StakingSetSessionsPerEra = 1, + StakingSetBondingDuration = 2, + StakingSetValidatorCount = 3, + GovernanceSetApprovalPpmRequired = 4, + SessionSetLength = 5, } impl InternalFunction { @@ -85,27 +86,27 @@ impl Proposal { match self.function { InternalFunction::SystemSetCode => { let code: Vec<u8> = params.read().unwrap(); - system::set_code(&code); + system::privileged::set_code(&code); } InternalFunction::StakingSetSessionsPerEra => { let value = params.read().unwrap(); - staking::set_sessions_per_era(value); + staking::privileged::set_sessions_per_era(value); } InternalFunction::StakingSetBondingDuration => { let value = params.read().unwrap(); - staking::set_bonding_duration(value); + staking::privileged::set_bonding_duration(value); } InternalFunction::StakingSetValidatorCount => { let value = params.read().unwrap(); - staking::set_validator_count(value); + staking::privileged::set_validator_count(value); } InternalFunction::GovernanceSetApprovalPpmRequired => { let value = params.read().unwrap(); - governance::set_approval_ppm_required(value); + governance::privileged::set_approval_ppm_required(value); } InternalFunction::SessionSetLength => { let value = params.read().unwrap(); - session::set_length(value); + session::privileged::set_length(value); } } } @@ -114,7 +115,7 @@ impl Proposal { #[cfg(test)] mod test { use super::*; - use statichex::StaticHexInto; + use support::StaticHexInto; #[test] fn slicing_should_work() { diff --git a/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs b/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs index 7d7a0f5ec5..51666666cf 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs @@ -31,14 +31,18 @@ pub fn authorities() -> Vec<SessionKey> { AuthorityStorageVec::items() } -/// Set the current set of authorities' session keys. -/// -/// Called by `next_session` only. -pub fn set_authorities(authorities: &[SessionKey]) { - AuthorityStorageVec::set_items(authorities); -} +pub mod internal { + use super::*; -/// Set a single authority by index. -pub fn set_authority(index: u32, key: &SessionKey) { - AuthorityStorageVec::set_item(index, key); + /// Set the current set of authorities' session keys. + /// + /// Called by `next_session` only. + pub fn set_authorities(authorities: &[SessionKey]) { + AuthorityStorageVec::set_items(authorities); + } + + /// Set a single authority by index. + pub fn set_authority(index: u32, key: &SessionKey) { + AuthorityStorageVec::set_item(index, key); + } } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs index 85a24196bb..4b78e4944f 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs @@ -31,48 +31,6 @@ use support::{Storable, StorageVec, kill}; use primitives::{AccountID, Hash, BlockNumber, Proposal}; use runtime::{staking, system, session}; -// TRANSACTION API - -/// Propose a sensitive action to be taken. Any action that is enactable by `Proposal` is valid. -/// Proposal is by the `transactor` and will automatically count as an approval. Transactor must -/// be a current validator. It is illegal to propose when there is already a proposal in effect. -pub fn propose(validator: &AccountID, proposal: &Proposal) { - if Proposal::lookup(b"gov:pro").is_some() { - panic!("there may only be one proposal per era."); - } - proposal.store(b"gov:pro"); - approve(validator, staking::current_era()); -} - -/// Approve the current era's proposal. Transactor must be a validator. This may not be done more -/// than once for any validator in an era. -pub fn approve(validator: &AccountID, era_index: BlockNumber) { - if era_index != staking::current_era() { - panic!("approval vote applied on non-current era.") - } - if Proposal::lookup(b"gov:pro").is_none() { - panic!("there must be a proposal in order to approve."); - } - if session::validators().into_iter().position(|v| &v == validator).is_none() { - panic!("transactor must be a validator to approve."); - } - let key = validator.to_keyed_vec(b"gov:app:"); - if bool::lookup(&key).is_some() { - panic!("transactor may not approve a proposal twice in one era."); - } - true.store(&key); -} - -/// Set the proportion of validators that must approve for a proposal to be enacted at the end of -/// its era. The value, `ppm`, is measured as a fraction of 1000 rounded down to the nearest whole -/// validator. `1000` would require the approval of all validators; `667` would require two-thirds -/// (or there abouts) of validators. -pub fn set_approval_ppm_required(ppm: u32) { - ppm.store(b"gov:apr"); -} - -// INSPECTION API - /// The proportion of validators required for a propsal to be approved measured as the number out /// of 1000. pub fn approval_ppm_required() -> u32 { @@ -84,20 +42,68 @@ pub fn approvals_required() -> u32 { approval_ppm_required() * session::validator_count() as u32 / 1000 } -// PUBLIC API +pub mod public { + use super::*; -/// Current era is ending; we should finish up any proposals. -pub fn end_of_an_era() { - // tally up votes for the current proposal, if any. enact if there are sufficient approvals. - if let Some(proposal) = Proposal::lookup(b"gov:pro") { - kill(b"gov:pro"); - let approvals_required = approvals_required(); - let approved = session::validators().into_iter() - .filter_map(|v| bool::take(&v.to_keyed_vec(b"gov:app:"))) - .take(approvals_required as usize) - .count() as u32; - if approved == approvals_required { - proposal.enact(); + /// Propose a sensitive action to be taken. Any action that is enactable by `Proposal` is valid. + /// Proposal is by the `transactor` and will automatically count as an approval. Transactor must + /// be a current validator. It is illegal to propose when there is already a proposal in effect. + pub fn propose(validator: &AccountID, proposal: &Proposal) { + if Proposal::lookup(b"gov:pro").is_some() { + panic!("there may only be one proposal per era."); + } + proposal.store(b"gov:pro"); + approve(validator, staking::current_era()); + } + + /// Approve the current era's proposal. Transactor must be a validator. This may not be done more + /// than once for any validator in an era. + pub fn approve(validator: &AccountID, era_index: BlockNumber) { + if era_index != staking::current_era() { + panic!("approval vote applied on non-current era.") + } + if Proposal::lookup(b"gov:pro").is_none() { + panic!("there must be a proposal in order to approve."); + } + if session::validators().into_iter().position(|v| &v == validator).is_none() { + panic!("transactor must be a validator to approve."); + } + let key = validator.to_keyed_vec(b"gov:app:"); + if bool::lookup(&key).is_some() { + panic!("transactor may not approve a proposal twice in one era."); + } + true.store(&key); + } +} + +pub mod privileged { + use super::*; + + /// Set the proportion of validators that must approve for a proposal to be enacted at the end of + /// its era. The value, `ppm`, is measured as a fraction of 1000 rounded down to the nearest whole + /// validator. `1000` would require the approval of all validators; `667` would require two-thirds + /// (or there abouts) of validators. + pub fn set_approval_ppm_required(ppm: u32) { + ppm.store(b"gov:apr"); + } +} + +pub mod internal { + use super::*; + + /// Current era is ending; we should finish up any proposals. + pub fn end_of_an_era() { + // tally up votes for the current proposal, if any. enact if there are sufficient approvals. + if let Some(proposal) = Proposal::lookup(b"gov:pro") { + kill(b"gov:pro"); + let approvals_required = approvals_required(); + let approved = session::validators().into_iter() + .filter_map(|v| bool::take(&v.to_keyed_vec(b"gov:app:"))) + .take(approvals_required as usize) + .count() as u32; + if approved == approvals_required { + proposal.enact(); + } } } } @@ -106,13 +112,10 @@ pub fn end_of_an_era() { mod tests { use super::*; use runtime_std::{with_externalities, twox_128}; - use keyedvec::KeyedVec; - use joiner::Joiner; - use testing::{one, two, TestExternalities}; - use primitives::AccountID; - use proposal::InternalFunction; + use codec::{KeyedVec, Joiner}; + use support::{one, two, TestExternalities, with_env}; + use primitives::{AccountID, InternalFunction}; use runtime::{staking, session}; - use environment::with_env; fn new_test_ext() -> TestExternalities { let one = one(); @@ -152,12 +155,12 @@ mod tests { // Block 1: Make proposal. Approve it. Era length changes. with_env(|e| e.block_number = 1); - propose(&one, &Proposal { + public::propose(&one, &Proposal { function: InternalFunction::StakingSetSessionsPerEra, input_data: vec![].join(&2u64), }); - approve(&two, 1); - staking::check_new_era(); + public::approve(&two, 1); + staking::internal::check_new_era(); assert_eq!(staking::era_length(), 2); }); } @@ -178,21 +181,21 @@ mod tests { // Block 1: Make proposal. Fail it. with_env(|e| e.block_number = 1); - propose(&one, &Proposal { + public::propose(&one, &Proposal { function: InternalFunction::StakingSetSessionsPerEra, input_data: vec![].join(&2u64), }); - staking::check_new_era(); + staking::internal::check_new_era(); assert_eq!(staking::era_length(), 1); // Block 2: Make proposal. Approve it. It should change era length. with_env(|e| e.block_number = 2); - propose(&one, &Proposal { + public::propose(&one, &Proposal { function: InternalFunction::StakingSetSessionsPerEra, input_data: vec![].join(&2u64), }); - approve(&two, 2); - staking::check_new_era(); + public::approve(&two, 2); + staking::internal::check_new_era(); assert_eq!(staking::era_length(), 2); }); } @@ -213,11 +216,11 @@ mod tests { // Block 1: Make proposal. Will have only 1 vote. No change. with_env(|e| e.block_number = 1); - propose(&one, &Proposal { + public::propose(&one, &Proposal { function: InternalFunction::StakingSetSessionsPerEra, input_data: vec![].join(&2u64), }); - staking::check_new_era(); + staking::internal::check_new_era(); assert_eq!(staking::era_length(), 1); }); } @@ -239,12 +242,12 @@ mod tests { // Block 1: Make proposal. Will have only 1 vote. No change. with_env(|e| e.block_number = 1); - propose(&one, &Proposal { + public::propose(&one, &Proposal { function: InternalFunction::StakingSetSessionsPerEra, input_data: vec![].join(&2u64), }); - approve(&two, 0); - staking::check_new_era(); + public::approve(&two, 0); + staking::internal::check_new_era(); assert_eq!(staking::era_length(), 1); }); } @@ -266,13 +269,13 @@ mod tests { // Block 1: Make proposal. Will have only 1 vote. No change. with_env(|e| e.block_number = 1); - propose(&one, &Proposal { + public::propose(&one, &Proposal { function: InternalFunction::StakingSetSessionsPerEra, input_data: vec![].join(&2u64), }); - approve(&two, 1); - approve(&two, 1); - staking::check_new_era(); + public::approve(&two, 1); + public::approve(&two, 1); + staking::internal::check_new_era(); assert_eq!(staking::era_length(), 1); }); } @@ -294,15 +297,15 @@ mod tests { // Block 1: Make proposal. Will have only 1 vote. No change. with_env(|e| e.block_number = 1); - propose(&one, &Proposal { + public::propose(&one, &Proposal { function: InternalFunction::StakingSetSessionsPerEra, input_data: vec![].join(&2u64), }); - propose(&two, &Proposal { + public::propose(&two, &Proposal { function: InternalFunction::StakingSetSessionsPerEra, input_data: vec![].join(&2u64), }); - staking::check_new_era(); + staking::internal::check_new_era(); assert_eq!(staking::era_length(), 1); }); } @@ -324,8 +327,8 @@ mod tests { // Block 1: Make proposal. Will have only 1 vote. No change. with_env(|e| e.block_number = 1); - approve(&two, 1); - staking::check_new_era(); + public::approve(&two, 1); + staking::internal::check_new_era(); assert_eq!(staking::era_length(), 1); }); } @@ -348,12 +351,12 @@ mod tests { // Block 1: Make proposal. Will have only 1 vote. No change. with_env(|e| e.block_number = 1); - propose(&one, &Proposal { + public::propose(&one, &Proposal { function: InternalFunction::StakingSetSessionsPerEra, input_data: vec![].join(&2u64), }); - approve(&four, 1); - staking::check_new_era(); + public::approve(&four, 1); + staking::internal::check_new_era(); assert_eq!(staking::era_length(), 1); }); } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs index d6dc1e3764..c88aabbbe6 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -23,50 +23,6 @@ use support::{kill, Storable, StorageVec}; use primitives::{AccountID, SessionKey, BlockNumber}; use runtime::{system, staking, consensus}; -struct ValidatorStorageVec {} -impl StorageVec for ValidatorStorageVec { - type Item = AccountID; - const PREFIX: &'static[u8] = b"ses:val:"; -} - -// TRANSACTION API (available to all transactors) - -/// Sets the session key of `_validator` to `_key`. This doesn't take effect until the next -/// session. -pub fn set_key(validator: &AccountID, key: &SessionKey) { - // set new value for next session - key.store(&validator.to_keyed_vec(b"ses:nxt:")); -} -// PRIVILEGED API (available to proposals) - -/// Set a new era length. Won't kick in until the next era change (at current length). -pub fn set_length(new: BlockNumber) { - new.store(b"ses:nln"); -} - -// INTERNAL API (available to other runtime modules) - -/// Set the current set of validators. -/// -/// Called by staking::next_era() only. `next_session` should be called after this in order to -/// update the session keys to the next validator set. -pub fn set_validators(new: &[AccountID]) { - ValidatorStorageVec::set_items(new); - consensus::set_authorities(new); -} - -/// Hook to be called after transaction processing. -pub fn check_rotate_session() { - // do this last, after the staking system has had chance to switch out the authorities for the - // new set. - // check block number and call next_session if necessary. - if (system::block_number() - last_length_change()) % length() == 0 { - rotate_session(); - } -} - -// Inspection API - /// Get the current set of authorities. These are the session keys. pub fn validators() -> Vec<AccountID> { ValidatorStorageVec::items() @@ -92,7 +48,56 @@ pub fn last_length_change() -> BlockNumber { Storable::lookup_default(b"ses:llc") } -// PRIVATE (not available for use externally) +pub mod public { + use super::*; + + /// Sets the session key of `_validator` to `_key`. This doesn't take effect until the next + /// session. + pub fn set_key(validator: &AccountID, key: &SessionKey) { + // set new value for next session + key.store(&validator.to_keyed_vec(b"ses:nxt:")); + } +} + +pub mod privileged { + use super::*; + + /// Set a new era length. Won't kick in until the next era change (at current length). + pub fn set_length(new: BlockNumber) { + new.store(b"ses:nln"); + } +} + +// INTERNAL API (available to other runtime modules) + +pub mod internal { + use super::*; + + /// Set the current set of validators. + /// + /// Called by staking::next_era() only. `next_session` should be called after this in order to + /// update the session keys to the next validator set. + pub fn set_validators(new: &[AccountID]) { + ValidatorStorageVec::set_items(new); + consensus::internal::set_authorities(new); + } + + /// Hook to be called after transaction processing. + pub fn check_rotate_session() { + // do this last, after the staking system has had chance to switch out the authorities for the + // new set. + // check block number and call next_session if necessary. + if (system::block_number() - last_length_change()) % length() == 0 { + rotate_session(); + } + } +} + +struct ValidatorStorageVec {} +impl StorageVec for ValidatorStorageVec { + type Item = AccountID; + const PREFIX: &'static[u8] = b"ses:val:"; +} /// Move onto next session: register the new authority set. fn rotate_session() { @@ -110,7 +115,7 @@ fn rotate_session() { validators().iter().enumerate().for_each(|(i, v)| { let k = v.to_keyed_vec(b"ses:nxt:"); if let Some(n) = Storable::lookup(&k) { - consensus::set_authority(i as u32, &n); + consensus::internal::set_authority(i as u32, &n); kill(&k); } }); @@ -118,13 +123,15 @@ fn rotate_session() { #[cfg(test)] mod tests { + use super::*; + use super::public::*; + use super::privileged::*; + use super::internal::*; use runtime_std::{with_externalities, twox_128}; - use keyedvec::KeyedVec; - use joiner::Joiner; - use testing::{one, two, TestExternalities}; + use codec::{KeyedVec, Joiner}; + use support::{one, two, TestExternalities, with_env}; use primitives::AccountID; use runtime::{consensus, session}; - use environment::with_env; fn simple_setup() -> TestExternalities { TestExternalities { storage: map![ @@ -145,8 +152,8 @@ mod tests { let mut t = simple_setup(); with_externalities(&mut t, || { assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); - assert_eq!(session::length(), 2u64); - assert_eq!(session::validators(), vec![[10u8; 32], [20u8; 32]]); + assert_eq!(length(), 2u64); + assert_eq!(validators(), vec![[10u8; 32], [20u8; 32]]); }); } @@ -156,48 +163,48 @@ mod tests { with_externalities(&mut t, || { // Block 1: Change to length 3; no visible change. with_env(|e| e.block_number = 1); - session::set_length(3); - session::check_rotate_session(); - assert_eq!(session::length(), 2); - assert_eq!(session::current_index(), 0); + set_length(3); + check_rotate_session(); + assert_eq!(length(), 2); + assert_eq!(current_index(), 0); // Block 2: Length now changed to 3. Index incremented. with_env(|e| e.block_number = 2); - session::set_length(3); - session::check_rotate_session(); - assert_eq!(session::length(), 3); - assert_eq!(session::current_index(), 1); + set_length(3); + check_rotate_session(); + assert_eq!(length(), 3); + assert_eq!(current_index(), 1); // Block 3: Length now changed to 3. Index incremented. with_env(|e| e.block_number = 3); - session::check_rotate_session(); - assert_eq!(session::length(), 3); - assert_eq!(session::current_index(), 1); + check_rotate_session(); + assert_eq!(length(), 3); + assert_eq!(current_index(), 1); // Block 4: Change to length 2; no visible change. with_env(|e| e.block_number = 4); - session::set_length(2); - session::check_rotate_session(); - assert_eq!(session::length(), 3); - assert_eq!(session::current_index(), 1); + set_length(2); + check_rotate_session(); + assert_eq!(length(), 3); + assert_eq!(current_index(), 1); // Block 5: Length now changed to 2. Index incremented. with_env(|e| e.block_number = 5); - session::check_rotate_session(); - assert_eq!(session::length(), 2); - assert_eq!(session::current_index(), 2); + check_rotate_session(); + assert_eq!(length(), 2); + assert_eq!(current_index(), 2); // Block 6: No change. with_env(|e| e.block_number = 6); - session::check_rotate_session(); - assert_eq!(session::length(), 2); - assert_eq!(session::current_index(), 2); + check_rotate_session(); + assert_eq!(length(), 2); + assert_eq!(current_index(), 2); // Block 7: Next index. with_env(|e| e.block_number = 7); - session::check_rotate_session(); - assert_eq!(session::length(), 2); - assert_eq!(session::current_index(), 3); + check_rotate_session(); + assert_eq!(length(), 2); + assert_eq!(current_index(), 3); }); } @@ -207,25 +214,25 @@ mod tests { with_externalities(&mut t, || { // Block 1: No change with_env(|e| e.block_number = 1); - session::check_rotate_session(); + check_rotate_session(); assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); // Block 2: Session rollover, but no change. with_env(|e| e.block_number = 2); - session::check_rotate_session(); + check_rotate_session(); assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); // Block 3: Set new key for validator 2; no visible change. with_env(|e| e.block_number = 3); - session::set_key(&[20; 32], &[22; 32]); + set_key(&[20; 32], &[22; 32]); assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); - session::check_rotate_session(); + check_rotate_session(); assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); // Block 4: Session rollover, authority 2 changes. with_env(|e| e.block_number = 4); - session::check_rotate_session(); + check_rotate_session(); assert_eq!(consensus::authorities(), vec![[11u8; 32], [22u8; 32]]); }); } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index b87d26c360..b0e8a9ddaf 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -29,88 +29,6 @@ pub type Balance = u64; /// The amount of bonding period left in an account. Measured in eras. pub type Bondage = u64; -struct IntentionStorageVec {} -impl StorageVec for IntentionStorageVec { - type Item = AccountID; - const PREFIX: &'static[u8] = b"sta:wil:"; -} - -// Each identity's stake may be in one of three bondage states, given by an integer: -// - n | n <= current_era(): inactive: free to be transferred. -// - ~0: active: currently representing a validator. -// - n | n > current_era(): deactivating: recently representing a validator and not yet -// ready for transfer. - -// TRANSACTION API - -/// Transfer some unlocked staking balance to another staker. -pub fn transfer(transactor: &AccountID, dest: &AccountID, value: Balance) { - let from_key = transactor.to_keyed_vec(b"sta:bal:"); - let from_balance = Balance::lookup_default(&from_key); - assert!(from_balance >= value); - let to_key = dest.to_keyed_vec(b"sta:bal:"); - let to_balance: Balance = Storable::lookup_default(&to_key); - assert!(bondage(transactor) <= bondage(dest)); - assert!(to_balance + value > to_balance); // no overflow - (from_balance - value).store(&from_key); - (to_balance + value).store(&to_key); -} - -/// Declare the desire to stake for the transactor. -/// -/// Effects will be felt at the beginning of the next era. -pub fn stake(transactor: &AccountID) { - let mut intentions = IntentionStorageVec::items(); - // can't be in the list twice. - assert!(intentions.iter().find(|t| *t == transactor).is_none(), "Cannot stake if already staked."); - intentions.push(transactor.clone()); - IntentionStorageVec::set_items(&intentions); - u64::max_value().store(&transactor.to_keyed_vec(b"sta:bon:")); -} - -/// Retract the desire to stake for the transactor. -/// -/// Effects will be felt at the beginning of the next era. -pub fn unstake(transactor: &AccountID) { - let mut intentions = IntentionStorageVec::items(); - if let Some(position) = intentions.iter().position(|t| t == transactor) { - intentions.swap_remove(position); - } else { - panic!("Cannot unstake if not already staked."); - } - IntentionStorageVec::set_items(&intentions); - (current_era() + bonding_duration()).store(&transactor.to_keyed_vec(b"sta:bon:")); -} - -// PRIVILEDGED API - -/// Set the number of sessions in an era. -pub fn set_sessions_per_era(new: BlockNumber) { - new.store(b"sta:nse"); -} - -/// The length of the bonding duration in eras. -pub fn set_bonding_duration(new: BlockNumber) { - new.store(b"sta:loc"); -} - -/// The length of a staking era in sessions. -pub fn set_validator_count(new: usize) { - (new as u32).store(b"sta:vac"); -} - -// INTERNAL API - -/// Hook to be called after to transaction processing. -pub fn check_new_era() { - // check block number and call new_era if necessary. - if (system::block_number() - last_era_length_change()) % era_length() == 0 { - new_era(); - } -} - -// INSPECTION API - /// The length of the bonding duration in eras. pub fn bonding_duration() -> BlockNumber { Storable::lookup_default(b"sta:loc") @@ -151,7 +69,91 @@ pub fn bondage(who: &AccountID) -> Bondage { Storable::lookup_default(&who.to_keyed_vec(b"sta:bon:")) } -// PRIVATE +// Each identity's stake may be in one of three bondage states, given by an integer: +// - n | n <= current_era(): inactive: free to be transferred. +// - ~0: active: currently representing a validator. +// - n | n > current_era(): deactivating: recently representing a validator and not yet +// ready for transfer. + +pub mod public { + use super::*; + + /// Transfer some unlocked staking balance to another staker. + pub fn transfer(transactor: &AccountID, dest: &AccountID, value: Balance) { + let from_key = transactor.to_keyed_vec(b"sta:bal:"); + let from_balance = Balance::lookup_default(&from_key); + assert!(from_balance >= value); + let to_key = dest.to_keyed_vec(b"sta:bal:"); + let to_balance: Balance = Storable::lookup_default(&to_key); + assert!(bondage(transactor) <= bondage(dest)); + assert!(to_balance + value > to_balance); // no overflow + (from_balance - value).store(&from_key); + (to_balance + value).store(&to_key); + } + + /// Declare the desire to stake for the transactor. + /// + /// Effects will be felt at the beginning of the next era. + pub fn stake(transactor: &AccountID) { + let mut intentions = IntentionStorageVec::items(); + // can't be in the list twice. + assert!(intentions.iter().find(|t| *t == transactor).is_none(), "Cannot stake if already staked."); + intentions.push(transactor.clone()); + IntentionStorageVec::set_items(&intentions); + u64::max_value().store(&transactor.to_keyed_vec(b"sta:bon:")); + } + + /// Retract the desire to stake for the transactor. + /// + /// Effects will be felt at the beginning of the next era. + pub fn unstake(transactor: &AccountID) { + let mut intentions = IntentionStorageVec::items(); + if let Some(position) = intentions.iter().position(|t| t == transactor) { + intentions.swap_remove(position); + } else { + panic!("Cannot unstake if not already staked."); + } + IntentionStorageVec::set_items(&intentions); + (current_era() + bonding_duration()).store(&transactor.to_keyed_vec(b"sta:bon:")); + } +} + +pub mod privileged { + use super::*; + + /// Set the number of sessions in an era. + pub fn set_sessions_per_era(new: BlockNumber) { + new.store(b"sta:nse"); + } + + /// The length of the bonding duration in eras. + pub fn set_bonding_duration(new: BlockNumber) { + new.store(b"sta:loc"); + } + + /// The length of a staking era in sessions. + pub fn set_validator_count(new: usize) { + (new as u32).store(b"sta:vac"); + } +} + +pub mod internal { + use super::*; + + /// Hook to be called after to transaction processing. + pub fn check_new_era() { + // check block number and call new_era if necessary. + if (system::block_number() - last_era_length_change()) % era_length() == 0 { + new_era(); + } + } +} + +struct IntentionStorageVec {} +impl StorageVec for IntentionStorageVec { + type Item = AccountID; + const PREFIX: &'static[u8] = b"sta:wil:"; +} /// The era has changed - enact new staking set. /// @@ -159,7 +161,7 @@ pub fn bondage(who: &AccountID) -> Bondage { /// get a chance to set their session keys. fn new_era() { // Inform governance module that it's the end of an era - governance::end_of_an_era(); + governance::internal::end_of_an_era(); // Increment current era. (current_era() + 1).store(b"sta:era"); @@ -172,7 +174,7 @@ fn new_era() { } // evaluate desired staking amounts and nominations and optimise to find the best - // combination of validators, then use session::set_validators(). + // combination of validators, then use session::internal::set_validators(). // for now, this just orders would-be stakers by their balances and chooses the top-most // validator_count() of them. let mut intentions = IntentionStorageVec::items() @@ -180,7 +182,7 @@ fn new_era() { .map(|v| (balance(&v), v)) .collect::<Vec<_>>(); intentions.sort_unstable_by(|&(b1, _), &(b2, _)| b2.cmp(&b1)); - session::set_validators( + session::internal::set_validators( &intentions.into_iter() .map(|(_, v)| v) .take(validator_count()) @@ -190,13 +192,16 @@ fn new_era() { #[cfg(test)] mod tests { + use super::*; + use super::internal::*; + use super::public::*; + use super::privileged::*; + use runtime_std::{with_externalities, twox_128}; - use keyedvec::KeyedVec; - use joiner::Joiner; - use testing::{one, two, TestExternalities}; + use codec::{KeyedVec, Joiner}; + use support::{one, two, TestExternalities, with_env}; use primitives::AccountID; use runtime::{staking, session}; - use environment::with_env; #[test] fn staking_should_work() { @@ -220,54 +225,54 @@ mod tests { ], }; with_externalities(&mut t, || { - assert_eq!(staking::era_length(), 2u64); - assert_eq!(staking::validator_count(), 2usize); - assert_eq!(staking::bonding_duration(), 3u64); + assert_eq!(era_length(), 2u64); + assert_eq!(validator_count(), 2usize); + assert_eq!(bonding_duration(), 3u64); assert_eq!(session::validators(), vec![[10u8; 32], [20u8; 32]]); // Block 1: Add three validators. No obvious change. with_env(|e| e.block_number = 1); - staking::stake(&one); - staking::stake(&two); - staking::stake(&four); - staking::check_new_era(); + stake(&one); + stake(&two); + stake(&four); + check_new_era(); assert_eq!(session::validators(), vec![[10u8; 32], [20u8; 32]]); // Block 2: New validator set now. with_env(|e| e.block_number = 2); - staking::check_new_era(); + check_new_era(); assert_eq!(session::validators(), vec![four.clone(), two.clone()]); // Block 3: Unstake highest, introduce another staker. No change yet. with_env(|e| e.block_number = 3); - staking::stake(&three); - staking::unstake(&four); - staking::check_new_era(); + stake(&three); + unstake(&four); + check_new_era(); // Block 4: New era - validators change. with_env(|e| e.block_number = 4); - staking::check_new_era(); + check_new_era(); assert_eq!(session::validators(), vec![three.clone(), two.clone()]); // Block 5: Transfer stake from highest to lowest. No change yet. with_env(|e| e.block_number = 5); - staking::transfer(&four, &one, 40); - staking::check_new_era(); + transfer(&four, &one, 40); + check_new_era(); // Block 6: Lowest now validator. with_env(|e| e.block_number = 6); - staking::check_new_era(); + check_new_era(); assert_eq!(session::validators(), vec![one.clone(), three.clone()]); // Block 7: Unstake three. No change yet. with_env(|e| e.block_number = 7); - staking::unstake(&three); - staking::check_new_era(); + unstake(&three); + check_new_era(); assert_eq!(session::validators(), vec![one.clone(), three.clone()]); // Block 8: Back to one and two. with_env(|e| e.block_number = 8); - staking::check_new_era(); + check_new_era(); assert_eq!(session::validators(), vec![one.clone(), two.clone()]); }); } @@ -279,60 +284,60 @@ mod tests { twox_128(b"sta:spe").to_vec() => vec![].join(&2u64) ], }; with_externalities(&mut t, || { - assert_eq!(staking::era_length(), 2u64); - assert_eq!(staking::sessions_per_era(), 2u64); - assert_eq!(staking::last_era_length_change(), 0u64); - assert_eq!(staking::current_era(), 0u64); + assert_eq!(era_length(), 2u64); + assert_eq!(sessions_per_era(), 2u64); + assert_eq!(last_era_length_change(), 0u64); + assert_eq!(current_era(), 0u64); // Block 1: No change. with_env(|e| e.block_number = 1); - staking::check_new_era(); - assert_eq!(staking::sessions_per_era(), 2u64); - assert_eq!(staking::last_era_length_change(), 0u64); - assert_eq!(staking::current_era(), 0u64); + check_new_era(); + assert_eq!(sessions_per_era(), 2u64); + assert_eq!(last_era_length_change(), 0u64); + assert_eq!(current_era(), 0u64); // Block 2: Simple era change. with_env(|e| e.block_number = 2); - staking::check_new_era(); - assert_eq!(staking::sessions_per_era(), 2u64); - assert_eq!(staking::last_era_length_change(), 0u64); - assert_eq!(staking::current_era(), 1u64); + check_new_era(); + assert_eq!(sessions_per_era(), 2u64); + assert_eq!(last_era_length_change(), 0u64); + assert_eq!(current_era(), 1u64); // Block 3: Schedule an era length change; no visible changes. with_env(|e| e.block_number = 3); - staking::set_sessions_per_era(3); - staking::check_new_era(); - assert_eq!(staking::sessions_per_era(), 2u64); - assert_eq!(staking::last_era_length_change(), 0u64); - assert_eq!(staking::current_era(), 1u64); + set_sessions_per_era(3); + check_new_era(); + assert_eq!(sessions_per_era(), 2u64); + assert_eq!(last_era_length_change(), 0u64); + assert_eq!(current_era(), 1u64); // Block 4: Era change kicks in. with_env(|e| e.block_number = 4); - staking::check_new_era(); - assert_eq!(staking::sessions_per_era(), 3u64); - assert_eq!(staking::last_era_length_change(), 4u64); - assert_eq!(staking::current_era(), 2u64); + check_new_era(); + assert_eq!(sessions_per_era(), 3u64); + assert_eq!(last_era_length_change(), 4u64); + assert_eq!(current_era(), 2u64); // Block 5: No change. with_env(|e| e.block_number = 5); - staking::check_new_era(); - assert_eq!(staking::sessions_per_era(), 3u64); - assert_eq!(staking::last_era_length_change(), 4u64); - assert_eq!(staking::current_era(), 2u64); + check_new_era(); + assert_eq!(sessions_per_era(), 3u64); + assert_eq!(last_era_length_change(), 4u64); + assert_eq!(current_era(), 2u64); // Block 6: No change. with_env(|e| e.block_number = 6); - staking::check_new_era(); - assert_eq!(staking::sessions_per_era(), 3u64); - assert_eq!(staking::last_era_length_change(), 4u64); - assert_eq!(staking::current_era(), 2u64); + check_new_era(); + assert_eq!(sessions_per_era(), 3u64); + assert_eq!(last_era_length_change(), 4u64); + assert_eq!(current_era(), 2u64); // Block 7: Era increment. with_env(|e| e.block_number = 7); - staking::check_new_era(); - assert_eq!(staking::sessions_per_era(), 3u64); - assert_eq!(staking::last_era_length_change(), 4u64); - assert_eq!(staking::current_era(), 3u64); + check_new_era(); + assert_eq!(sessions_per_era(), 3u64); + assert_eq!(last_era_length_change(), 4u64); + assert_eq!(current_era(), 3u64); }); } @@ -346,8 +351,8 @@ mod tests { ], }; with_externalities(&mut t, || { - assert_eq!(staking::balance(&one), 42); - assert_eq!(staking::balance(&two), 0); + assert_eq!(balance(&one), 42); + assert_eq!(balance(&two), 0); }); } @@ -361,9 +366,9 @@ mod tests { ], }; with_externalities(&mut t, || { - staking::transfer(&one, &two, 69); - assert_eq!(staking::balance(&one), 42); - assert_eq!(staking::balance(&two), 69); + transfer(&one, &two, 69); + assert_eq!(balance(&one), 42); + assert_eq!(balance(&two), 69); }); } @@ -378,8 +383,8 @@ mod tests { ], }; with_externalities(&mut t, || { - staking::stake(&one); - staking::transfer(&one, &two, 69); + stake(&one); + transfer(&one, &two, 69); }); } } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index d6236beb78..2327ffc3c4 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -34,75 +34,83 @@ pub fn block_hash(number: BlockNumber) -> Hash { Storable::lookup_default(&number.to_keyed_vec(b"sys:old:")) } -/// Deposits a log and ensures it matches the blocks log data. -pub fn deposit_log(log: &[u8]) { - with_env(|e| { - assert_eq!(log, &e.digest.logs[e.next_log_index][..]); - e.next_log_index += 1; - }); +pub mod privileged { + use super::*; + + /// Set the new code. + pub fn set_code(new: &[u8]) { + new.store(b":code"); + } } -/// Actually execute all transitioning for `block`. -pub fn execute_block(mut block: Block) { - // populate environment from header. - with_env(|e| { - e.block_number = block.header.number; - mem::swap(&mut e.digest, &mut block.header.digest); - e.next_log_index = 0; - }); +pub mod internal { + use super::*; - let ref header = block.header; + /// Deposits a log and ensures it matches the blocks log data. + pub fn deposit_log(log: &[u8]) { + with_env(|e| { + assert_eq!(log, &e.digest.logs[e.next_log_index][..]); + e.next_log_index += 1; + }); + } - // check parent_hash is correct. - assert!( - header.number > 0 && block_hash(header.number - 1) == header.parent_hash, - "Parent hash should be valid." - ); + /// Actually execute all transitioning for `block`. + pub fn execute_block(mut block: Block) { + // populate environment from header. + with_env(|e| { + e.block_number = block.header.number; + mem::swap(&mut e.digest, &mut block.header.digest); + e.next_log_index = 0; + }); - // TODO: check transaction trie root represents the transactions. - // this requires non-trivial changes to the externals API or compiling trie rooting into wasm - // so will wait until a little later. + let ref header = block.header; - // store the header hash in storage. - let header_hash_key = header.number.to_keyed_vec(b"sys:old:"); - header.blake2_256().store(&header_hash_key); + // check parent_hash is correct. + assert!( + header.number > 0 && block_hash(header.number - 1) == header.parent_hash, + "Parent hash should be valid." + ); - // execute transactions - block.transactions.iter().for_each(execute_transaction); + // TODO: check transaction trie root represents the transactions. + // this requires non-trivial changes to the externals API or compiling trie rooting into wasm + // so will wait until a little later. - staking::check_new_era(); - session::check_rotate_session(); + // store the header hash in storage. + let header_hash_key = header.number.to_keyed_vec(b"sys:old:"); + header.blake2_256().store(&header_hash_key); - // any final checks - final_checks(&block); + // execute transactions + block.transactions.iter().for_each(execute_transaction); - // TODO: check storage root. - // this requires non-trivial changes to the externals API or compiling trie rooting into wasm - // so will wait until a little later. -} + staking::internal::check_new_era(); + session::internal::check_rotate_session(); -/// Execute a given transaction. -pub fn execute_transaction(utx: &UncheckedTransaction) { - // Verify the signature is good. - assert!(utx.ed25519_verify(), "All transactions should be properly signed"); + // any final checks + final_checks(&block); - let ref tx = utx.transaction; + // TODO: check storage root. + // this requires non-trivial changes to the externals API or compiling trie rooting into wasm + // so will wait until a little later. + } - // check nonce - let nonce_key = tx.signed.to_keyed_vec(b"sys:non:"); - let expected_nonce: TxOrder = Storable::lookup_default(&nonce_key); - assert!(tx.nonce == expected_nonce, "All transactions should have the correct nonce"); + /// Execute a given transaction. + pub fn execute_transaction(utx: &UncheckedTransaction) { + // Verify the signature is good. + assert!(utx.ed25519_verify(), "All transactions should be properly signed"); - // increment nonce in storage - (expected_nonce + 1).store(&nonce_key); + let ref tx = utx.transaction; - // decode parameters and dispatch - tx.function.dispatch(&tx.signed, &tx.input_data); -} + // check nonce + let nonce_key = tx.signed.to_keyed_vec(b"sys:non:"); + let expected_nonce: TxOrder = Storable::lookup_default(&nonce_key); + assert!(tx.nonce == expected_nonce, "All transactions should have the correct nonce"); -/// Set the new code. -pub fn set_code(new: &[u8]) { - new.store(b":code"); + // increment nonce in storage + (expected_nonce + 1).store(&nonce_key); + + // decode parameters and dispatch + tx.function.dispatch(&tx.signed, &tx.input_data); + } } fn final_checks(_block: &Block) { @@ -113,15 +121,14 @@ fn final_checks(_block: &Block) { #[cfg(test)] mod tests { - use joiner::Joiner; - use function::Function; - use keyedvec::KeyedVec; - use slicable::Slicable; + use super::*; + use super::internal::*; + use runtime_std::{with_externalities, twox_128}; - use primitives::{UncheckedTransaction, Transaction}; - use statichex::StaticHexInto; - use runtime::{system, staking}; - use testing::{TestExternalities, HexDisplay, one, two}; + use codec::{Joiner, KeyedVec, Slicable}; + use support::{StaticHexInto, TestExternalities, HexDisplay, one, two}; + use primitives::{UncheckedTransaction, Transaction, Function}; + use runtime::staking; #[test] fn staking_balance_transfer_dispatch_works() { @@ -147,7 +154,7 @@ mod tests { println!("tx is {}", HexDisplay::from(&tx.transaction.to_vec())); with_externalities(&mut t, || { - system::execute_transaction(&tx); + execute_transaction(&tx); assert_eq!(staking::balance(&one), 42); assert_eq!(staking::balance(&two), 69); }); diff --git a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs index 09fb36a606..0f471f4a98 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs @@ -26,18 +26,24 @@ pub fn get() -> Timestamp { Storable::lookup_default(b"tim:val") } -/// Set the current time. -pub fn set(now: Timestamp) { - now.store(b"tim:val") +pub mod public { + use super::*; + + /// Set the current time. + pub fn set(now: Timestamp) { + now.store(b"tim:val") + } } #[cfg(test)] mod tests { - use joiner::Joiner; - use keyedvec::KeyedVec; + use super::*; + use super::public::*; + use runtime_std::{with_externalities, twox_128}; use runtime::timestamp; - use testing::TestExternalities; + use codec::{Joiner, KeyedVec}; + use support::TestExternalities; #[test] fn timestamp_works() { @@ -46,9 +52,9 @@ mod tests { ], }; with_externalities(&mut t, || { - assert_eq!(timestamp::get(), 42); - timestamp::set(69); - assert_eq!(timestamp::get(), 69); + assert_eq!(get(), 42); + set(69); + assert_eq!(get(), 69); }); } } diff --git a/substrate/wasm-runtime/polkadot/src/support/storable.rs b/substrate/wasm-runtime/polkadot/src/support/storable.rs index 97f6384c10..dc1a6fde2d 100644 --- a/substrate/wasm-runtime/polkadot/src/support/storable.rs +++ b/substrate/wasm-runtime/polkadot/src/support/storable.rs @@ -110,7 +110,7 @@ mod tests { use super::*; use std::collections::HashMap; use runtime_std::with_externalities; - use testing::{TestExternalities, HexDisplay}; + use support::{TestExternalities, HexDisplay}; use runtime_std::{storage, twox_128}; #[test] @@ -180,7 +180,7 @@ mod tests { #[test] fn proposals_can_be_stored() { - use proposal::{Proposal, InternalFunction}; + use primitives::{Proposal, InternalFunction}; let mut t = TestExternalities { storage: HashMap::new(), }; with_externalities(&mut t, || { let x = Proposal { function: InternalFunction::StakingSetSessionsPerEra, input_data: b"Hello world".to_vec() }; From bfd599e5dea0e659739e87f84e36a2aceffce4a5 Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Sun, 28 Jan 2018 17:08:45 +0100 Subject: [PATCH 099/112] Revise storage API. --- .../polkadot/src/codec/endiansensitive.rs | 4 +- .../polkadot/src/codec/slicable.rs | 2 + .../polkadot/src/primitives/function.rs | 17 +- .../polkadot/src/primitives/proposal.rs | 21 ++- .../polkadot/src/runtime/governance.rs | 21 ++- .../polkadot/src/runtime/session.rs | 25 ++- .../polkadot/src/runtime/staking.rs | 44 ++--- .../polkadot/src/runtime/system.rs | 12 +- .../polkadot/src/runtime/timestamp.rs | 6 +- .../wasm-runtime/polkadot/src/support/mod.rs | 6 +- .../src/support/{storable.rs => storage.rs} | 151 +++++++++++------- 11 files changed, 175 insertions(+), 134 deletions(-) rename substrate/wasm-runtime/polkadot/src/support/{storable.rs => storage.rs} (50%) diff --git a/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs b/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs index ec9be8e465..1b550edffa 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs +++ b/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs @@ -17,7 +17,9 @@ //! Endian manager. /// Trait to allow conversion to a know endian representation when sensitive. -// note: the copy bound and static lifetimes are necessary for safety of `Slicable` blanket implementation. +/// Types implementing this trait must have a size > 0. +// note: the copy bound and static lifetimes are necessary for safety of `Slicable` blanket +// implementation. pub trait EndianSensitive: Copy + 'static { fn to_le(self) -> Self { self } fn to_be(self) -> Self { self } diff --git a/substrate/wasm-runtime/polkadot/src/codec/slicable.rs b/substrate/wasm-runtime/polkadot/src/codec/slicable.rs index 3ac3d880e4..0f1ef812a6 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/slicable.rs +++ b/substrate/wasm-runtime/polkadot/src/codec/slicable.rs @@ -49,6 +49,7 @@ pub trait NonTrivialSlicable: Slicable {} impl<T: EndianSensitive> Slicable for T { fn set_as_slice<F: Fn(&mut [u8], usize) -> bool>(fill_slice: &F) -> Option<Self> { let size = mem::size_of::<T>(); + assert!(size > 0, "EndianSensitive can never be implemented for a zero-sized type."); let mut result: T = unsafe { mem::zeroed() }; let result_slice = unsafe { let ptr = &mut result as *mut _ as *mut u8; @@ -62,6 +63,7 @@ impl<T: EndianSensitive> Slicable for T { } fn as_slice_then<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R { let size = mem::size_of::<Self>(); + assert!(size > 0, "EndianSensitive can never be implemented for a zero-sized type."); self.as_le_then(|le| { let value_slice = unsafe { let ptr = le as *const _ as *const u8; diff --git a/substrate/wasm-runtime/polkadot/src/primitives/function.rs b/substrate/wasm-runtime/polkadot/src/primitives/function.rs index 35273e2cfa..e906cdc718 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/function.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/function.rs @@ -37,15 +37,14 @@ pub enum Function { impl Function { /// Derive `Some` value from a `u8`, or `None` if it's invalid. pub fn from_u8(value: u8) -> Option<Function> { - match value { - x if x == Function::StakingStake as u8 => Some(Function::StakingStake), - x if x == Function::StakingUnstake as u8 => Some(Function::StakingUnstake), - x if x == Function::StakingTransfer as u8 => Some(Function::StakingTransfer), - x if x == Function::SessionSetKey as u8 => Some(Function::SessionSetKey), - x if x == Function::TimestampSet as u8 => Some(Function::TimestampSet), - x if x == Function::GovernancePropose as u8 => Some(Function::GovernancePropose), - x if x == Function::GovernanceApprove as u8 => Some(Function::GovernanceApprove), - _ => None, + use self::*; + let functions = [Function::StakingStake, Function::StakingUnstake, + Function::StakingTransfer, Function::SessionSetKey, Function::TimestampSet, + Function::GovernancePropose, Function::GovernanceApprove]; + if (value as usize) < functions.len() { + Some(functions[value as usize]) + } else { + None } } } diff --git a/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs b/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs index 33539c2f17..1b8aa6b13e 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs @@ -38,14 +38,19 @@ pub enum InternalFunction { impl InternalFunction { /// Derive `Some` value from a `u8`, or `None` if it's invalid. pub fn from_u8(value: u8) -> Option<InternalFunction> { - match value { - x if x == InternalFunction::SystemSetCode as u8 => Some(InternalFunction::SystemSetCode), - x if x == InternalFunction::StakingSetSessionsPerEra as u8 => Some(InternalFunction::StakingSetSessionsPerEra), - x if x == InternalFunction::StakingSetBondingDuration as u8 => Some(InternalFunction::StakingSetBondingDuration), - x if x == InternalFunction::StakingSetValidatorCount as u8 => Some(InternalFunction::StakingSetValidatorCount), - x if x == InternalFunction::GovernanceSetApprovalPpmRequired as u8 => Some(InternalFunction::GovernanceSetApprovalPpmRequired), - x if x == InternalFunction::SessionSetLength as u8 => Some(InternalFunction::SessionSetLength), - _ => None, + use self::*; + let functions = [ + InternalFunction::SystemSetCode, + InternalFunction::StakingSetSessionsPerEra, + InternalFunction::StakingSetBondingDuration, + InternalFunction::StakingSetValidatorCount, + InternalFunction::GovernanceSetApprovalPpmRequired, + InternalFunction::SessionSetLength + ]; + if (value as usize) < functions.len() { + Some(functions[value as usize]) + } else { + None } } } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs index 4b78e4944f..b811daf1c2 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs @@ -27,14 +27,14 @@ use runtime_std::prelude::*; use codec::KeyedVec; -use support::{Storable, StorageVec, kill}; +use support::storage; use primitives::{AccountID, Hash, BlockNumber, Proposal}; use runtime::{staking, system, session}; /// The proportion of validators required for a propsal to be approved measured as the number out /// of 1000. pub fn approval_ppm_required() -> u32 { - Storable::lookup(b"gov:apr").unwrap_or(1000) + storage::get_or(b"gov:apr", 1000) } /// The number of concrete validator approvals required for a proposal to pass. @@ -49,10 +49,10 @@ pub mod public { /// Proposal is by the `transactor` and will automatically count as an approval. Transactor must /// be a current validator. It is illegal to propose when there is already a proposal in effect. pub fn propose(validator: &AccountID, proposal: &Proposal) { - if Proposal::lookup(b"gov:pro").is_some() { + if storage::exists(b"gov:pro") { panic!("there may only be one proposal per era."); } - proposal.store(b"gov:pro"); + storage::put(b"gov:pro", proposal); approve(validator, staking::current_era()); } @@ -62,17 +62,17 @@ pub mod public { if era_index != staking::current_era() { panic!("approval vote applied on non-current era.") } - if Proposal::lookup(b"gov:pro").is_none() { + if !storage::exists(b"gov:pro") { panic!("there must be a proposal in order to approve."); } if session::validators().into_iter().position(|v| &v == validator).is_none() { panic!("transactor must be a validator to approve."); } let key = validator.to_keyed_vec(b"gov:app:"); - if bool::lookup(&key).is_some() { + if storage::exists(&key) { panic!("transactor may not approve a proposal twice in one era."); } - true.store(&key); + storage::put(&key, &true); } } @@ -84,7 +84,7 @@ pub mod privileged { /// validator. `1000` would require the approval of all validators; `667` would require two-thirds /// (or there abouts) of validators. pub fn set_approval_ppm_required(ppm: u32) { - ppm.store(b"gov:apr"); + storage::put(b"gov:apr", &ppm); } } @@ -94,11 +94,10 @@ pub mod internal { /// Current era is ending; we should finish up any proposals. pub fn end_of_an_era() { // tally up votes for the current proposal, if any. enact if there are sufficient approvals. - if let Some(proposal) = Proposal::lookup(b"gov:pro") { - kill(b"gov:pro"); + if let Some(proposal) = storage::take::<Proposal>(b"gov:pro") { let approvals_required = approvals_required(); let approved = session::validators().into_iter() - .filter_map(|v| bool::take(&v.to_keyed_vec(b"gov:app:"))) + .filter_map(|v| storage::take::<bool>(&v.to_keyed_vec(b"gov:app:"))) .take(approvals_required as usize) .count() as u32; if approved == approvals_required { diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs index c88aabbbe6..9322653d20 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -19,7 +19,7 @@ use runtime_std::prelude::*; use codec::KeyedVec; -use support::{kill, Storable, StorageVec}; +use support::{storage, StorageVec}; use primitives::{AccountID, SessionKey, BlockNumber}; use runtime::{system, staking, consensus}; @@ -30,7 +30,7 @@ pub fn validators() -> Vec<AccountID> { /// The number of blocks in each session. pub fn length() -> BlockNumber { - Storable::lookup_default(b"ses:len") + storage::get_or(b"ses:len", 0) } /// The number of validators currently. @@ -40,12 +40,12 @@ pub fn validator_count() -> usize { /// The current era index. pub fn current_index() -> BlockNumber { - Storable::lookup_default(b"ses:ind") + storage::get_or(b"ses:ind", 0) } /// The block number at which the era length last changed. pub fn last_length_change() -> BlockNumber { - Storable::lookup_default(b"ses:llc") + storage::get_or(b"ses:llc", 0) } pub mod public { @@ -55,7 +55,7 @@ pub mod public { /// session. pub fn set_key(validator: &AccountID, key: &SessionKey) { // set new value for next session - key.store(&validator.to_keyed_vec(b"ses:nxt:")); + storage::put(&validator.to_keyed_vec(b"ses:nxt:"), key); } } @@ -64,7 +64,7 @@ pub mod privileged { /// Set a new era length. Won't kick in until the next era change (at current length). pub fn set_length(new: BlockNumber) { - new.store(b"ses:nln"); + storage::put(b"ses:nln", &new); } } @@ -102,21 +102,20 @@ impl StorageVec for ValidatorStorageVec { /// Move onto next session: register the new authority set. fn rotate_session() { // Increment current session index. - (current_index() + 1).store(b"ses:ind"); + storage::put(b"ses:ind", &(current_index() + 1)); // Enact era length change. - if let Some(next_len) = u64::lookup(b"ses:nln") { - next_len.store(b"ses:len"); - system::block_number().store(b"ses:llc"); - kill(b"ses:nln"); + if let Some(next_len) = storage::get::<u64>(b"ses:nln") { + storage::put(b"ses:len", &next_len); + storage::put(b"ses:llc", &system::block_number()); + storage::kill(b"ses:nln"); } // Update any changes in session keys. validators().iter().enumerate().for_each(|(i, v)| { let k = v.to_keyed_vec(b"ses:nxt:"); - if let Some(n) = Storable::lookup(&k) { + if let Some(n) = storage::take(&k) { consensus::internal::set_authority(i as u32, &n); - kill(&k); } }); } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index b0e8a9ddaf..fbe1149f0a 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -19,7 +19,7 @@ use runtime_std::prelude::*; use runtime_std::cell::RefCell; use codec::KeyedVec; -use support::{Storable, StorageVec}; +use support::{storage, StorageVec}; use primitives::{BlockNumber, AccountID}; use runtime::{system, session, governance}; @@ -31,12 +31,12 @@ pub type Bondage = u64; /// The length of the bonding duration in eras. pub fn bonding_duration() -> BlockNumber { - Storable::lookup_default(b"sta:loc") + storage::get_default(b"sta:loc") } /// The length of a staking era in sessions. pub fn validator_count() -> usize { - u32::lookup_default(b"sta:vac") as usize + storage::get_default::<u32>(b"sta:vac") as usize } /// The length of a staking era in blocks. @@ -46,27 +46,27 @@ pub fn era_length() -> BlockNumber { /// The length of a staking era in sessions. pub fn sessions_per_era() -> BlockNumber { - Storable::lookup_default(b"sta:spe") + storage::get_default(b"sta:spe") } /// The current era index. pub fn current_era() -> BlockNumber { - Storable::lookup_default(b"sta:era") + storage::get_default(b"sta:era") } /// The block number at which the era length last changed. pub fn last_era_length_change() -> BlockNumber { - Storable::lookup_default(b"sta:lec") + storage::get_default(b"sta:lec") } /// The balance of a given account. pub fn balance(who: &AccountID) -> Balance { - Storable::lookup_default(&who.to_keyed_vec(b"sta:bal:")) + storage::get_default(&who.to_keyed_vec(b"sta:bal:")) } /// The liquidity-state of a given account. pub fn bondage(who: &AccountID) -> Bondage { - Storable::lookup_default(&who.to_keyed_vec(b"sta:bon:")) + storage::get_default(&who.to_keyed_vec(b"sta:bon:")) } // Each identity's stake may be in one of three bondage states, given by an integer: @@ -81,14 +81,14 @@ pub mod public { /// Transfer some unlocked staking balance to another staker. pub fn transfer(transactor: &AccountID, dest: &AccountID, value: Balance) { let from_key = transactor.to_keyed_vec(b"sta:bal:"); - let from_balance = Balance::lookup_default(&from_key); + let from_balance = storage::get_default::<Balance>(&from_key); assert!(from_balance >= value); let to_key = dest.to_keyed_vec(b"sta:bal:"); - let to_balance: Balance = Storable::lookup_default(&to_key); + let to_balance: Balance = storage::get_default(&to_key); assert!(bondage(transactor) <= bondage(dest)); assert!(to_balance + value > to_balance); // no overflow - (from_balance - value).store(&from_key); - (to_balance + value).store(&to_key); + storage::put(&from_key, &(from_balance - value)); + storage::put(&to_key, &(to_balance + value)); } /// Declare the desire to stake for the transactor. @@ -100,7 +100,7 @@ pub mod public { assert!(intentions.iter().find(|t| *t == transactor).is_none(), "Cannot stake if already staked."); intentions.push(transactor.clone()); IntentionStorageVec::set_items(&intentions); - u64::max_value().store(&transactor.to_keyed_vec(b"sta:bon:")); + storage::put(&transactor.to_keyed_vec(b"sta:bon:"), &u64::max_value()); } /// Retract the desire to stake for the transactor. @@ -114,7 +114,7 @@ pub mod public { panic!("Cannot unstake if not already staked."); } IntentionStorageVec::set_items(&intentions); - (current_era() + bonding_duration()).store(&transactor.to_keyed_vec(b"sta:bon:")); + storage::put(&transactor.to_keyed_vec(b"sta:bon:"), &(current_era() + bonding_duration())); } } @@ -123,17 +123,17 @@ pub mod privileged { /// Set the number of sessions in an era. pub fn set_sessions_per_era(new: BlockNumber) { - new.store(b"sta:nse"); + storage::put(b"sta:nse", &new); } /// The length of the bonding duration in eras. pub fn set_bonding_duration(new: BlockNumber) { - new.store(b"sta:loc"); + storage::put(b"sta:loc", &new); } /// The length of a staking era in sessions. pub fn set_validator_count(new: usize) { - (new as u32).store(b"sta:vac"); + storage::put(b"sta:vac", &(new as u32)); } } @@ -164,13 +164,13 @@ fn new_era() { governance::internal::end_of_an_era(); // Increment current era. - (current_era() + 1).store(b"sta:era"); + storage::put(b"sta:era", &(current_era() + 1)); // Enact era length change. - let next_spe: u64 = Storable::lookup_default(b"sta:nse"); + let next_spe: u64 = storage::get_default(b"sta:nse"); if next_spe > 0 && next_spe != sessions_per_era() { - next_spe.store(b"sta:spe"); - system::block_number().store(b"sta:lec"); + storage::put(b"sta:spe", &next_spe); + storage::put(b"sta:lec", &system::block_number()); } // evaluate desired staking amounts and nominations and optimise to find the best @@ -196,7 +196,7 @@ mod tests { use super::internal::*; use super::public::*; use super::privileged::*; - + use runtime_std::{with_externalities, twox_128}; use codec::{KeyedVec, Joiner}; use support::{one, two, TestExternalities, with_env}; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 2327ffc3c4..b8610f0980 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -20,7 +20,7 @@ use runtime_std::prelude::*; use runtime_std::{mem, print}; use codec::KeyedVec; -use support::{Hashable, Storable, with_env}; +use support::{Hashable, storage, with_env}; use primitives::{Block, BlockNumber, Hash, UncheckedTransaction, TxOrder}; use runtime::{staking, session}; @@ -31,7 +31,7 @@ pub fn block_number() -> BlockNumber { /// Get the block hash of a given block (uses storage). pub fn block_hash(number: BlockNumber) -> Hash { - Storable::lookup_default(&number.to_keyed_vec(b"sys:old:")) + storage::get_default(&number.to_keyed_vec(b"sys:old:")) } pub mod privileged { @@ -39,7 +39,7 @@ pub mod privileged { /// Set the new code. pub fn set_code(new: &[u8]) { - new.store(b":code"); + storage::put_raw(b":code", new); } } @@ -77,7 +77,7 @@ pub mod internal { // store the header hash in storage. let header_hash_key = header.number.to_keyed_vec(b"sys:old:"); - header.blake2_256().store(&header_hash_key); + storage::put(&header_hash_key, &header.blake2_256()); // execute transactions block.transactions.iter().for_each(execute_transaction); @@ -102,11 +102,11 @@ pub mod internal { // check nonce let nonce_key = tx.signed.to_keyed_vec(b"sys:non:"); - let expected_nonce: TxOrder = Storable::lookup_default(&nonce_key); + let expected_nonce: TxOrder = storage::get_default(&nonce_key); assert!(tx.nonce == expected_nonce, "All transactions should have the correct nonce"); // increment nonce in storage - (expected_nonce + 1).store(&nonce_key); + storage::put(&nonce_key, &(expected_nonce + 1)); // decode parameters and dispatch tx.function.dispatch(&tx.signed, &tx.input_data); diff --git a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs index 0f471f4a98..116b6b6bb5 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs @@ -16,14 +16,14 @@ //! Timestamp manager: just handles the current timestamp. -use support::Storable; +use support::storage; /// Representation of a time. pub type Timestamp = u64; /// Get the current time. pub fn get() -> Timestamp { - Storable::lookup_default(b"tim:val") + storage::get_default(b"tim:val") } pub mod public { @@ -31,7 +31,7 @@ pub mod public { /// Set the current time. pub fn set(now: Timestamp) { - now.store(b"tim:val") + storage::put(b"tim:val", &now); } } diff --git a/substrate/wasm-runtime/polkadot/src/support/mod.rs b/substrate/wasm-runtime/polkadot/src/support/mod.rs index 854a8f9f01..6bc60880a0 100644 --- a/substrate/wasm-runtime/polkadot/src/support/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/support/mod.rs @@ -17,7 +17,7 @@ //! Support code for the runtime. mod environment; -mod storable; +pub mod storage; mod hashable; #[cfg(feature = "with-std")] mod statichex; @@ -25,8 +25,8 @@ mod statichex; #[cfg(feature = "with-std")] mod testing; -pub use self::environment::{Environment, with_env}; -pub use self::storable::{StorageVec, Storable, kill}; +pub use self::environment::with_env; +pub use self::storage::StorageVec; pub use self::hashable::Hashable; #[cfg(feature = "with-std")] pub use self::statichex::{StaticHexConversion, StaticHexInto}; diff --git a/substrate/wasm-runtime/polkadot/src/support/storable.rs b/substrate/wasm-runtime/polkadot/src/support/storage.rs similarity index 50% rename from substrate/wasm-runtime/polkadot/src/support/storable.rs rename to substrate/wasm-runtime/polkadot/src/support/storage.rs index dc1a6fde2d..e21f41bfd4 100644 --- a/substrate/wasm-runtime/polkadot/src/support/storable.rs +++ b/substrate/wasm-runtime/polkadot/src/support/storage.rs @@ -20,60 +20,95 @@ use runtime_std::prelude::*; use runtime_std::{self, twox_128}; use codec::{Slicable, KeyedVec}; -/// Trait for a value which may be stored in the storage DB. -pub trait Storable { - /// Lookup the value in storage and deserialise, giving a default value if not found. - fn lookup_default(key: &[u8]) -> Self where Self: Sized + Default { - Self::lookup(key).unwrap_or_else(Default::default) - } - - /// Lookup `Some` value in storage and deserialise; `None` if it's not there. - fn lookup(_key: &[u8]) -> Option<Self> where Self: Sized { - unimplemented!() - } - - /// Retrives and returns the serialised value of a key from storage, removing it immediately. - fn take(key: &[u8]) -> Option<Self> where Self: Sized { - if let Some(value) = Self::lookup(key) { - kill(key); - Some(value) - } else { - None - } - } - - /// Place the value in storage under `key`. - fn store(&self, key: &[u8]); -} - // TODO: consider using blake256 to avoid possible preimage attack. -/// Remove `key` from storage. +/// 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(&twox_128(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_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(&twox_128(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(&twox_128(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_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(&twox_128(key)[..], &mut x[..], 0) == 1 +} + +/// Ensure `key` has no explicit entry in storage. pub fn kill(key: &[u8]) { runtime_std::set_storage(&twox_128(key)[..], b""); } -impl<T: Sized + Slicable> Storable for T { - fn lookup(key: &[u8]) -> Option<Self> { - Slicable::set_as_slice(&|out, offset| - runtime_std::read_storage(&twox_128(key)[..], out, offset) >= out.len() - ) - } - fn store(&self, key: &[u8]) { - self.as_slice_then(|slice| runtime_std::set_storage(&twox_128(key)[..], slice)); - } +/// Get a Vec of bytes from storage. +pub fn get_raw(key: &[u8]) -> Vec<u8> { + runtime_std::storage(&twox_128(key)[..]) } -impl Storable for [u8] { - fn store(&self, key: &[u8]) { - runtime_std::set_storage(&twox_128(key)[..], self) - } +/// Put a raw byte slice into storage. +pub fn put_raw(key: &[u8], value: &[u8]) { + runtime_std::set_storage(&twox_128(key)[..], value) } /// A trait to conveniently store a vector of storable data. // TODO: add iterator support pub trait StorageVec { - type Item: Default + Sized + Storable; + type Item: Default + Sized + Slicable; const PREFIX: &'static [u8]; /// Get the current set of items. @@ -88,20 +123,20 @@ pub trait StorageVec { } fn set_item(index: u32, item: &Self::Item) { - item.store(&index.to_keyed_vec(Self::PREFIX)); + put(&index.to_keyed_vec(Self::PREFIX), item); } fn item(index: u32) -> Self::Item { - Storable::lookup_default(&index.to_keyed_vec(Self::PREFIX)) + get_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())); - count.store(&b"len".to_keyed_vec(Self::PREFIX)); + put(&b"len".to_keyed_vec(Self::PREFIX), &count); } fn count() -> u32 { - Storable::lookup_default(&b"len".to_keyed_vec(Self::PREFIX)) + get_default(&b"len".to_keyed_vec(Self::PREFIX)) } } @@ -118,14 +153,14 @@ mod tests { let mut t = TestExternalities { storage: HashMap::new(), }; with_externalities(&mut t, || { let x = 69u32; - x.store(b":test"); - let y = u32::lookup(b":test").unwrap(); + put(b":test", &x); + let y: u32 = get(b":test").unwrap(); assert_eq!(x, y); }); with_externalities(&mut t, || { let x = 69426942i64; - x.store(b":test"); - let y = i64::lookup(b":test").unwrap(); + put(b":test", &x); + let y: i64 = get(b":test").unwrap(); assert_eq!(x, y); }); } @@ -135,15 +170,15 @@ mod tests { let mut t = TestExternalities { storage: HashMap::new(), }; with_externalities(&mut t, || { let x = true; - x.store(b":test"); - let y = bool::lookup(b":test").unwrap(); + put(b":test", &x); + let y: bool = get(b":test").unwrap(); assert_eq!(x, y); }); with_externalities(&mut t, || { let x = false; - x.store(b":test"); - let y = bool::lookup(b":test").unwrap(); + put(b":test", &x); + let y: bool = get(b":test").unwrap(); assert_eq!(x, y); }); } @@ -155,7 +190,7 @@ mod tests { runtime_std::set_storage(&twox_128(b":test"), b"\x0b\0\0\0Hello world"); let x = b"Hello world".to_vec(); println!("Hex: {}", HexDisplay::from(&storage(&twox_128(b":test")))); - let y = <Vec<u8>>::lookup(b":test").unwrap(); + let y = get::<Vec<u8>>(b":test").unwrap(); assert_eq!(x, y); }); @@ -167,13 +202,13 @@ mod tests { let x = b"Hello world".to_vec(); with_externalities(&mut t, || { - x.store(b":test"); + put(b":test", &x); }); println!("Ext is {:?}", t); with_externalities(&mut t, || { println!("Hex: {}", HexDisplay::from(&storage(&twox_128(b":test")))); - let y = <Vec<u8>>::lookup(b":test").unwrap(); + let y: Vec<u8> = get(b":test").unwrap(); assert_eq!(x, y); }); } @@ -184,8 +219,8 @@ mod tests { let mut t = TestExternalities { storage: HashMap::new(), }; with_externalities(&mut t, || { let x = Proposal { function: InternalFunction::StakingSetSessionsPerEra, input_data: b"Hello world".to_vec() }; - x.store(b":test"); - let y = Proposal::lookup(b":test").unwrap(); + put(b":test", &x); + let y: Proposal = get(b":test").unwrap(); assert_eq!(x, y); }); } From 3491e1609e70fef42a2f2a99bdff3f1afb96f94d Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Sun, 28 Jan 2018 17:11:29 +0100 Subject: [PATCH 100/112] Fix exists bug. --- .../polkadot/src/support/storage.rs | 2 +- .../release/runtime_polkadot.compact.wasm | Bin 62629 -> 63399 bytes .../release/runtime_polkadot.wasm | Bin 62678 -> 63448 bytes 3 files changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/wasm-runtime/polkadot/src/support/storage.rs b/substrate/wasm-runtime/polkadot/src/support/storage.rs index e21f41bfd4..201556fec2 100644 --- a/substrate/wasm-runtime/polkadot/src/support/storage.rs +++ b/substrate/wasm-runtime/polkadot/src/support/storage.rs @@ -87,7 +87,7 @@ pub fn take_or_else<T: Slicable + Sized, F: FnOnce() -> T>(key: &[u8], default_v /// 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(&twox_128(key)[..], &mut x[..], 0) == 1 + runtime_std::read_storage(&twox_128(key)[..], &mut x[..], 0) >= 1 } /// Ensure `key` has no explicit entry in storage. diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm index 1f94e5511576c6db6c3f58819f74307aa2d7cf0c..c080bcdba20661b01da0ec6f1cde147712a3a132 100644 GIT binary patch literal 63399 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 TXPZ9Asb)59bm5H7W!QWLIQxDd literal 62629 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 E2dr6Re*gdg diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm index 4fa5a8ae0d5e9a9f09ccbe1329f4a5a79f3bfca7..9dc89f117b83f8009c223570b9ac157e89853b46 100644 GIT binary patch literal 63448 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 literal 62678 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 From 825cb6b9d4597db7d739e37001281af060ac46e0 Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Sun, 28 Jan 2018 20:00:06 +0100 Subject: [PATCH 101/112] Use consts rather than direct names. --- .../polkadot/src/runtime/governance.rs | 26 ++++--- .../polkadot/src/runtime/session.rs | 34 ++++++---- .../polkadot/src/runtime/staking.rs | 67 +++++++++++-------- .../polkadot/src/runtime/system.rs | 9 ++- .../polkadot/src/runtime/timestamp.rs | 8 ++- 5 files changed, 86 insertions(+), 58 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs index b811daf1c2..f638e56a5e 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs @@ -31,10 +31,18 @@ use support::storage; use primitives::{AccountID, Hash, BlockNumber, Proposal}; use runtime::{staking, system, session}; +/*macro_rules! db_name { + ( $( $name:ident )+ ) => concat!("gov:", $( stringify!($name) ),+ ) +}*/ + +const APPROVALS_REQUIRED: &[u8] = b"gov:apr"; +const CURRENT_PROPOSAL: &[u8] = b"gov:pro"; +const APPROVAL_OF: &[u8] = b"gov:app:"; + /// The proportion of validators required for a propsal to be approved measured as the number out /// of 1000. pub fn approval_ppm_required() -> u32 { - storage::get_or(b"gov:apr", 1000) + storage::get_or(APPROVALS_REQUIRED, 1000) } /// The number of concrete validator approvals required for a proposal to pass. @@ -49,10 +57,10 @@ pub mod public { /// Proposal is by the `transactor` and will automatically count as an approval. Transactor must /// be a current validator. It is illegal to propose when there is already a proposal in effect. pub fn propose(validator: &AccountID, proposal: &Proposal) { - if storage::exists(b"gov:pro") { + if storage::exists(CURRENT_PROPOSAL) { panic!("there may only be one proposal per era."); } - storage::put(b"gov:pro", proposal); + storage::put(CURRENT_PROPOSAL, proposal); approve(validator, staking::current_era()); } @@ -62,13 +70,13 @@ pub mod public { if era_index != staking::current_era() { panic!("approval vote applied on non-current era.") } - if !storage::exists(b"gov:pro") { + if !storage::exists(CURRENT_PROPOSAL) { panic!("there must be a proposal in order to approve."); } if session::validators().into_iter().position(|v| &v == validator).is_none() { panic!("transactor must be a validator to approve."); } - let key = validator.to_keyed_vec(b"gov:app:"); + let key = validator.to_keyed_vec(APPROVAL_OF); if storage::exists(&key) { panic!("transactor may not approve a proposal twice in one era."); } @@ -84,7 +92,7 @@ pub mod privileged { /// validator. `1000` would require the approval of all validators; `667` would require two-thirds /// (or there abouts) of validators. pub fn set_approval_ppm_required(ppm: u32) { - storage::put(b"gov:apr", &ppm); + storage::put(APPROVALS_REQUIRED, &ppm); } } @@ -94,10 +102,10 @@ pub mod internal { /// Current era is ending; we should finish up any proposals. pub fn end_of_an_era() { // tally up votes for the current proposal, if any. enact if there are sufficient approvals. - if let Some(proposal) = storage::take::<Proposal>(b"gov:pro") { + if let Some(proposal) = storage::take::<Proposal>(CURRENT_PROPOSAL) { let approvals_required = approvals_required(); let approved = session::validators().into_iter() - .filter_map(|v| storage::take::<bool>(&v.to_keyed_vec(b"gov:app:"))) + .filter_map(|v| storage::take::<bool>(&v.to_keyed_vec(APPROVAL_OF))) .take(approvals_required as usize) .count() as u32; if approved == approvals_required { @@ -122,7 +130,7 @@ mod tests { let three = [3u8; 32]; TestExternalities { storage: map![ - twox_128(b"gov:apr").to_vec() => vec![].join(&667u32), + twox_128(APPROVALS_REQUIRED).to_vec() => vec![].join(&667u32), twox_128(b"ses:len").to_vec() => vec![].join(&1u64), twox_128(b"ses:val:len").to_vec() => vec![].join(&3u32), twox_128(&0u32.to_keyed_vec(b"ses:val:")).to_vec() => one.to_vec(), diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs index 9322653d20..48cb6f42d4 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -30,7 +30,7 @@ pub fn validators() -> Vec<AccountID> { /// The number of blocks in each session. pub fn length() -> BlockNumber { - storage::get_or(b"ses:len", 0) + storage::get_or(SESSION_LENGTH, 0) } /// The number of validators currently. @@ -40,12 +40,12 @@ pub fn validator_count() -> usize { /// The current era index. pub fn current_index() -> BlockNumber { - storage::get_or(b"ses:ind", 0) + storage::get_or(CURRENT_INDEX, 0) } /// The block number at which the era length last changed. pub fn last_length_change() -> BlockNumber { - storage::get_or(b"ses:llc", 0) + storage::get_or(LAST_LENGTH_CHANGE, 0) } pub mod public { @@ -55,7 +55,7 @@ pub mod public { /// session. pub fn set_key(validator: &AccountID, key: &SessionKey) { // set new value for next session - storage::put(&validator.to_keyed_vec(b"ses:nxt:"), key); + storage::put(&validator.to_keyed_vec(NEXT_KEY_FOR), key); } } @@ -64,7 +64,7 @@ pub mod privileged { /// Set a new era length. Won't kick in until the next era change (at current length). pub fn set_length(new: BlockNumber) { - storage::put(b"ses:nln", &new); + storage::put(NEXT_SESSION_LENGTH, &new); } } @@ -93,6 +93,12 @@ pub mod internal { } } +const SESSION_LENGTH: &[u8] = b"ses:len"; +const CURRENT_INDEX: &[u8] = b"ses:ind"; +const LAST_LENGTH_CHANGE: &[u8] = b"ses:llc"; +const NEXT_KEY_FOR: &[u8] = b"ses:nxt:"; +const NEXT_SESSION_LENGTH: &[u8] = b"ses:nln"; + struct ValidatorStorageVec {} impl StorageVec for ValidatorStorageVec { type Item = AccountID; @@ -102,18 +108,18 @@ impl StorageVec for ValidatorStorageVec { /// Move onto next session: register the new authority set. fn rotate_session() { // Increment current session index. - storage::put(b"ses:ind", &(current_index() + 1)); + storage::put(CURRENT_INDEX, &(current_index() + 1)); // Enact era length change. - if let Some(next_len) = storage::get::<u64>(b"ses:nln") { - storage::put(b"ses:len", &next_len); - storage::put(b"ses:llc", &system::block_number()); - storage::kill(b"ses:nln"); + if let Some(next_len) = storage::get::<u64>(NEXT_SESSION_LENGTH) { + storage::put(SESSION_LENGTH, &next_len); + storage::put(LAST_LENGTH_CHANGE, &system::block_number()); + storage::kill(NEXT_SESSION_LENGTH); } // Update any changes in session keys. validators().iter().enumerate().for_each(|(i, v)| { - let k = v.to_keyed_vec(b"ses:nxt:"); + let k = v.to_keyed_vec(NEXT_KEY_FOR); if let Some(n) = storage::take(&k) { consensus::internal::set_authority(i as u32, &n); } @@ -134,11 +140,11 @@ mod tests { fn simple_setup() -> TestExternalities { TestExternalities { storage: map![ - twox_128(b"ses:len").to_vec() => vec![].join(&2u64), + twox_128(SESSION_LENGTH).to_vec() => vec![].join(&2u64), // the validators (10, 20, ...) twox_128(b"ses:val:len").to_vec() => vec![].join(&2u32), - twox_128(&0u32.to_keyed_vec(b"ses:val:")).to_vec() => vec![10; 32], - twox_128(&1u32.to_keyed_vec(b"ses:val:")).to_vec() => vec![20; 32], + twox_128(&0u32.to_keyed_vec(ValidatorStorageVec::PREFIX)).to_vec() => vec![10; 32], + twox_128(&1u32.to_keyed_vec(ValidatorStorageVec::PREFIX)).to_vec() => vec![20; 32], // initial session keys (11, 21, ...) twox_128(b"con:aut:len").to_vec() => vec![].join(&2u32), twox_128(&0u32.to_keyed_vec(b"con:aut:")).to_vec() => vec![11; 32], diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index fbe1149f0a..9ddd78b788 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -31,12 +31,12 @@ pub type Bondage = u64; /// The length of the bonding duration in eras. pub fn bonding_duration() -> BlockNumber { - storage::get_default(b"sta:loc") + storage::get_default(BONDING_DURATION) } /// The length of a staking era in sessions. pub fn validator_count() -> usize { - storage::get_default::<u32>(b"sta:vac") as usize + storage::get_default::<u32>(VALIDATOR_COUNT) as usize } /// The length of a staking era in blocks. @@ -46,27 +46,27 @@ pub fn era_length() -> BlockNumber { /// The length of a staking era in sessions. pub fn sessions_per_era() -> BlockNumber { - storage::get_default(b"sta:spe") + storage::get_default(SESSIONS_PER_ERA) } /// The current era index. pub fn current_era() -> BlockNumber { - storage::get_default(b"sta:era") + storage::get_default(CURRENT_ERA) } /// The block number at which the era length last changed. pub fn last_era_length_change() -> BlockNumber { - storage::get_default(b"sta:lec") + storage::get_default(LAST_ERA_LENGTH_CHANGE) } /// The balance of a given account. pub fn balance(who: &AccountID) -> Balance { - storage::get_default(&who.to_keyed_vec(b"sta:bal:")) + storage::get_default(&who.to_keyed_vec(BALANCE_OF)) } /// The liquidity-state of a given account. pub fn bondage(who: &AccountID) -> Bondage { - storage::get_default(&who.to_keyed_vec(b"sta:bon:")) + storage::get_default(&who.to_keyed_vec(BONDAGE_OF)) } // Each identity's stake may be in one of three bondage states, given by an integer: @@ -80,10 +80,10 @@ pub mod public { /// Transfer some unlocked staking balance to another staker. pub fn transfer(transactor: &AccountID, dest: &AccountID, value: Balance) { - let from_key = transactor.to_keyed_vec(b"sta:bal:"); + let from_key = transactor.to_keyed_vec(BALANCE_OF); let from_balance = storage::get_default::<Balance>(&from_key); assert!(from_balance >= value); - let to_key = dest.to_keyed_vec(b"sta:bal:"); + let to_key = dest.to_keyed_vec(BALANCE_OF); let to_balance: Balance = storage::get_default(&to_key); assert!(bondage(transactor) <= bondage(dest)); assert!(to_balance + value > to_balance); // no overflow @@ -100,7 +100,7 @@ pub mod public { assert!(intentions.iter().find(|t| *t == transactor).is_none(), "Cannot stake if already staked."); intentions.push(transactor.clone()); IntentionStorageVec::set_items(&intentions); - storage::put(&transactor.to_keyed_vec(b"sta:bon:"), &u64::max_value()); + storage::put(&transactor.to_keyed_vec(BONDAGE_OF), &u64::max_value()); } /// Retract the desire to stake for the transactor. @@ -114,7 +114,7 @@ pub mod public { panic!("Cannot unstake if not already staked."); } IntentionStorageVec::set_items(&intentions); - storage::put(&transactor.to_keyed_vec(b"sta:bon:"), &(current_era() + bonding_duration())); + storage::put(&transactor.to_keyed_vec(BONDAGE_OF), &(current_era() + bonding_duration())); } } @@ -123,17 +123,17 @@ pub mod privileged { /// Set the number of sessions in an era. pub fn set_sessions_per_era(new: BlockNumber) { - storage::put(b"sta:nse", &new); + storage::put(NEXT_SESSIONS_PER_ERA, &new); } /// The length of the bonding duration in eras. pub fn set_bonding_duration(new: BlockNumber) { - storage::put(b"sta:loc", &new); + storage::put(BONDING_DURATION, &new); } /// The length of a staking era in sessions. pub fn set_validator_count(new: usize) { - storage::put(b"sta:vac", &(new as u32)); + storage::put(VALIDATOR_COUNT, &(new as u32)); } } @@ -155,6 +155,15 @@ impl StorageVec for IntentionStorageVec { const PREFIX: &'static[u8] = b"sta:wil:"; } +const BONDING_DURATION: &[u8] = b"sta:loc"; +const VALIDATOR_COUNT: &[u8] = b"sta:vac"; +const SESSIONS_PER_ERA: &[u8] = b"sta:spe"; +const NEXT_SESSIONS_PER_ERA: &[u8] = b"sta:nse"; +const CURRENT_ERA: &[u8] = b"sta:era"; +const LAST_ERA_LENGTH_CHANGE: &[u8] = b"sta:lec"; +const BALANCE_OF: &[u8] = b"sta:bal:"; +const BONDAGE_OF: &[u8] = b"sta:bon:"; + /// The era has changed - enact new staking set. /// /// NOTE: This always happens immediately before a session change to ensure that new validators @@ -164,13 +173,13 @@ fn new_era() { governance::internal::end_of_an_era(); // Increment current era. - storage::put(b"sta:era", &(current_era() + 1)); + storage::put(CURRENT_ERA, &(current_era() + 1)); // Enact era length change. - let next_spe: u64 = storage::get_default(b"sta:nse"); + let next_spe: u64 = storage::get_default(NEXT_SESSIONS_PER_ERA); if next_spe > 0 && next_spe != sessions_per_era() { - storage::put(b"sta:spe", &next_spe); - storage::put(b"sta:lec", &system::block_number()); + storage::put(SESSIONS_PER_ERA, &next_spe); + storage::put(LAST_ERA_LENGTH_CHANGE, &system::block_number()); } // evaluate desired staking amounts and nominations and optimise to find the best @@ -215,13 +224,13 @@ mod tests { twox_128(b"ses:val:len").to_vec() => vec![].join(&2u32), twox_128(&0u32.to_keyed_vec(b"ses:val:")).to_vec() => vec![10; 32], twox_128(&1u32.to_keyed_vec(b"ses:val:")).to_vec() => vec![20; 32], - twox_128(b"sta:spe").to_vec() => vec![].join(&2u64), - twox_128(b"sta:vac").to_vec() => vec![].join(&2u32), - twox_128(b"sta:loc").to_vec() => vec![].join(&3u64), - twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![].join(&10u64), - twox_128(&two.to_keyed_vec(b"sta:bal:")).to_vec() => vec![].join(&20u64), - twox_128(&three.to_keyed_vec(b"sta:bal:")).to_vec() => vec![].join(&30u64), - twox_128(&four.to_keyed_vec(b"sta:bal:")).to_vec() => vec![].join(&40u64) + twox_128(SESSIONS_PER_ERA).to_vec() => vec![].join(&2u64), + twox_128(VALIDATOR_COUNT).to_vec() => vec![].join(&2u32), + twox_128(BONDING_DURATION).to_vec() => vec![].join(&3u64), + twox_128(&one.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].join(&10u64), + twox_128(&two.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].join(&20u64), + twox_128(&three.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].join(&30u64), + twox_128(&four.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].join(&40u64) ], }; with_externalities(&mut t, || { @@ -281,7 +290,7 @@ mod tests { fn staking_eras_work() { let mut t = TestExternalities { storage: map![ twox_128(b"ses:len").to_vec() => vec![].join(&1u64), - twox_128(b"sta:spe").to_vec() => vec![].join(&2u64) + twox_128(SESSIONS_PER_ERA).to_vec() => vec![].join(&2u64) ], }; with_externalities(&mut t, || { assert_eq!(era_length(), 2u64); @@ -347,7 +356,7 @@ mod tests { let two = two(); let mut t = TestExternalities { storage: map![ - twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![].join(&42u64) + twox_128(&one.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].join(&42u64) ], }; with_externalities(&mut t, || { @@ -362,7 +371,7 @@ mod tests { let two = two(); let mut t = TestExternalities { storage: map![ - twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![].join(&111u64) + twox_128(&one.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].join(&111u64) ], }; with_externalities(&mut t, || { @@ -379,7 +388,7 @@ mod tests { let two = two(); let mut t = TestExternalities { storage: map![ - twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![].join(&111u64) + twox_128(&one.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].join(&111u64) ], }; with_externalities(&mut t, || { diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index b8610f0980..35a425f53f 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -31,7 +31,7 @@ pub fn block_number() -> BlockNumber { /// Get the block hash of a given block (uses storage). pub fn block_hash(number: BlockNumber) -> Hash { - storage::get_default(&number.to_keyed_vec(b"sys:old:")) + storage::get_default(&number.to_keyed_vec(BLOCK_HASH_AT)) } pub mod privileged { @@ -39,7 +39,7 @@ pub mod privileged { /// Set the new code. pub fn set_code(new: &[u8]) { - storage::put_raw(b":code", new); + storage::put_raw(CODE, new); } } @@ -76,7 +76,7 @@ pub mod internal { // so will wait until a little later. // store the header hash in storage. - let header_hash_key = header.number.to_keyed_vec(b"sys:old:"); + let header_hash_key = header.number.to_keyed_vec(BLOCK_HASH_AT); storage::put(&header_hash_key, &header.blake2_256()); // execute transactions @@ -119,6 +119,9 @@ fn final_checks(_block: &Block) { }); } +const BLOCK_HASH_AT: &[u8] = b"sys:old:"; +const CODE: &[u8] = b"sys:cod"; + #[cfg(test)] mod tests { use super::*; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs index 116b6b6bb5..e6ae82a97d 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs @@ -23,7 +23,7 @@ pub type Timestamp = u64; /// Get the current time. pub fn get() -> Timestamp { - storage::get_default(b"tim:val") + storage::get_default(CURRENT_TIMESTAMP) } pub mod public { @@ -31,10 +31,12 @@ pub mod public { /// Set the current time. pub fn set(now: Timestamp) { - storage::put(b"tim:val", &now); + storage::put(CURRENT_TIMESTAMP, &now); } } +const CURRENT_TIMESTAMP: &[u8] = b"tim:val"; + #[cfg(test)] mod tests { use super::*; @@ -48,7 +50,7 @@ mod tests { #[test] fn timestamp_works() { let mut t = TestExternalities { storage: map![ - twox_128(b"tim:val").to_vec() => vec![].join(&42u64) + twox_128(CURRENT_TIMESTAMP).to_vec() => vec![].join(&42u64) ], }; with_externalities(&mut t, || { From fc1214f251b3b240d44c2df6887add44f48f57da Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Sun, 28 Jan 2018 20:17:14 +0100 Subject: [PATCH 102/112] Minor cleanup. --- .../polkadot/src/runtime/governance.rs | 12 ++++-------- .../release/runtime_polkadot.compact.wasm | Bin 63399 -> 63401 bytes .../release/runtime_polkadot.wasm | Bin 63448 -> 63450 bytes 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs index f638e56a5e..1be0b8b03c 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs @@ -31,14 +31,6 @@ use support::storage; use primitives::{AccountID, Hash, BlockNumber, Proposal}; use runtime::{staking, system, session}; -/*macro_rules! db_name { - ( $( $name:ident )+ ) => concat!("gov:", $( stringify!($name) ),+ ) -}*/ - -const APPROVALS_REQUIRED: &[u8] = b"gov:apr"; -const CURRENT_PROPOSAL: &[u8] = b"gov:pro"; -const APPROVAL_OF: &[u8] = b"gov:app:"; - /// The proportion of validators required for a propsal to be approved measured as the number out /// of 1000. pub fn approval_ppm_required() -> u32 { @@ -115,6 +107,10 @@ pub mod internal { } } +const APPROVALS_REQUIRED: &[u8] = b"gov:apr"; +const CURRENT_PROPOSAL: &[u8] = b"gov:pro"; +const APPROVAL_OF: &[u8] = b"gov:app:"; + #[cfg(test)] mod tests { use super::*; diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm index c080bcdba20661b01da0ec6f1cde147712a3a132..faffaa1605b839e2373e04522082b564ed251617 100644 GIT binary patch delta 1190 zcmYjPZA_b06u#%a1uAbDg`~3|qib0dDWf2Wuud}GB@9UvEl%g0A0wrMVpo{p$3WKp zKr<aKxU;yCG=@xc=om8Zevplg`op-mEFqDZnizw|7)cndI%AV9(Q^wW`*GgqeeUzz zbI(2Jo=qs9CzO#rdIm@K^Y9UN;gxDI>J7QNJe^L*x!wT44R{6y`J*+$$-e^rn_1jc zqS<`dNm!jFKFhyq$9PMT6#i{VNCW=y^pd3CdkfP3-&<|KZ<~d(`>+m%aq#&cU|8(l zyCD~<(dP^DAq%#(c|~#i9%;h?|4j)w9d+XU1CIk=HseCaj}pG@tcN-rIq*8aD~Sg` z4yf{=bAeBdl+xS(BB%UQZ>Q+%?Kk1<;4;;DV(2ds4Ij%A?e0zvGvY?&xpZ0mRr6f# zexfFIA54nI9Y%m8KGzU}a`8>WGXSNSXtHvnOVsSl(<v@vIX3Qc>&L9d2bikGa9~&1 z9A70_4rVN2sw1E9K@w9~*z^;WibPWZfD55{lFFNE-lsrJ<UV;yo^z(9*fe5Gr<z!W zcp7GK^xcQW-ggERjGUN<ljy~RV&Uk|I;a-ngBv<=6~D`ZT6}L*gRSEFXrmEoMZp(K z3S1O-&POGjzVM&^{;iHeEycQ=g$|Q;G~88e%44c(ti!2G^|E`nE}fMf{pfNlJc3J? zAJUac(KP!kMDf+xPFh@;eF?^~>dJW-7mHUO11hCxu9f=VGgnKdiMeZZr$ez8px(v4 zcF>Ek;IH4-k=u3+%y3K;Egm<7^}T&<o;L$Q57U;-YK~;RJ$|O$UL*e3+L(5CjRgHZ zrVUxhcDUE$>uzV-utha9BV(HwW7GMJ*$Epd6bhz|lNvKHwoS4;#x@hYK#?uE7PF|^ z@bBgAJYvPlTU)|oR@FRDIb0-Wa{1_gHP?())yrc;-65(qM&1Z{-S>FA*1d63D@iS* zmHmVTgiiruCPJnqt!hqR;GpM?wjk3|WMyP2VPVD^HZWF9mKq9O+B;&SnrO9@SVrBk zu1=6TMr!#z>dtjFMrseK@;;fpvNx-l<D@cDYcuLb`e|O5lQtEAX^~CXv9cXv_{mBM zJ<97V6)=W(R;pkg-3d33*zx5=8K1V}hyPUYMLQn<WuvlLbz^ywo>0OJ)0myyLS|R8 zf=3*<FX_PP<e_GNue?3=@uZW6Ni66OF)f-QK^pV;8VQ7G%#%)PKG{NV_0gt_lF=x- MgYBa0&-(2D0kjre>;M1& delta 1265 zcmYjQZA@Eb6n@X!TPR#QE@YjBGPuR)_*&Vhd{_l{=c@8YiDohQ5h(4=TDZ2@7PiHW zlB^mw$%c8WLL{cqZTP_q^W6`!vB7>hXH59PbQ)c5jDJWrTm0h^HF|FO$bOtW@AE#- zIqx~=wx4HAGa1vw%NCj#A-x1fF7~)V5{fL=LO~EH1)x@om3;!o>0@s0q+bL5r;6V) zP3O^+6VYwv=ZmjZavlg$nB*0QzRVfE4K7o|_|d@q0=UFeLlVF;J2xDLI==nzO91t( zW2Br)4Lo_oDwrCiI+i--vW%8Xj}TEwvzx~f_W5;UmWi~Bh;lLFqbS~HzT>|@J?|JP z0cc=diCIYTe-p2oAkDi^d}zG0maKMX*R#hQxr*~S__2U)Pr!&m6jDP4MJEH*wiYVL zHf5zj!ER5uGDi0-zGu~FzGrVqZkTA31L(NS&$y2YkYWXGKj4dc+qObzWtsh&@Vi|x z^PZ>A8zz?Ty=8dsct?RIW!C%bPX=V4^9Zs_YGD%xhG@#*UgL$<&T|sh`nCHtitA+W z`Tj!q^i&@hY~24RujzT$4D)R2oxQyK?YB(4^wb>zTKU@P?*+CpwoIp;?2KFE*Vs)n zG_#Xa3e@uNro0j~^O7%CO)$>?zA$aT<i-Ci57o-0%6-!BEX9e(68+USD-lI(>Z{A` zMpO4L&ltUaaOFj4W2;wcgx!W{TQ~@3*}y^&FIN^`hgsHi^#aUt{pypzW)_QC{o(;= zVS|gUX!~sO2F~;5((`~{ed)TKNAKF%Z{M^*k~?mI9ZvF{`st!)%pQLvpc3V-U9{`P zgj5hhCJ-wTy%;78q9n^id%B2_$C2oWRfw-(<Y5pcUB-T1>oApxRcv2&2TR-&6Qkv# zeGbdip}twpkLUGrljWi%b~NS*N5URVM{h5BT@QHsx4iSHN~qT3%|65u#20`N8zNDb z%f<Y7=nc=XPb120wCdXk*+mkB$attmOEZR$^Ja~n@U|A&rux*DI_41Vqp0qFK;6Hk zrcv!e)tF~9*I3Vb<#|+fD<Q3$>JB_~Zpq6I5r8PVgMIwR6GFN|tj0arq(hNmH5&GX z{i-V(!%-N`G{Pur$~3_oQ!_5A?_}?1>S2Oi&+I8%suWAKP@g{%RU0FN@lYh3%hD@Z zVYUf9?b(Mh&6jOFs8@*<UB0Lqj>|z`EGWl<ks&Q0_o*^&DHL!K{Da~C<37*fkcRtD z%3{93VuScQ7~ddj)JK%m2GLYMo6E*J@smZg0H&mzSU`;#YezQi!~)1PHB6MVn?&;y WWp;yv!U3XO+DHl?iF0kOJ@0>C$!;M4 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm index 9dc89f117b83f8009c223570b9ac157e89853b46..4fcafd35025853a4542797c75f0560bf042b6f06 100644 GIT binary patch delta 1174 zcmYk4Urd`-7{<?g`jvJ2%J_(Gwq<r@GlCQf!y=_f#)lb$L?MHjsYDr;A~m&4L3B~q zCNhn#o5UBhE%pL8jEk!acy>VslkQ5kxJcrk6tl=kcC%!oommWtM14=8WEUsTdCu=S z|K4+wDZ?Kr!|(wUgChrd_z0Wmbc1FxZ&Gp<Md93J2H<8q3uk!sQ(`aw9{4Sb_{R{- z;n70UCynB#ysLKH*!rjh#jPnBK<mES(kgBFnfxQ|1;FoHgnR#C1)_N2h2J46j=s2g z6S#527vw`$?0j{fXzxBCV;J}UCdKobM@;oJ0l#BGWAD6_o4s{VgI9Xq<}1>8@#lal zH@Xq{T9XHw4|j0dVB!5`a%amw1QOge^q06EK4uhOxOzEEihnE4XHIp#a*oT%A5<-G zgt!>otpTL*<N6S|#NYMp043;XvT@BRdKz*SgHv<iV57@4YSSKPs-D1jW7v{hHAV;1 zika%jBP}AhjL+=70VTrGln>y<%H}v-c%iw&00~k1+)265FD*N^3>RdUI=3pxj7;LS zk9LVqkG^NXiO=WwNFloS2ZiyIKNWC`TgR^}B8AtC;K56$btn@nr}t>!5e?toHo!$u zdLbs|>coF0D8q{Q!(6Mug-dm^T=uDNWC?$qYJ)1YO&2SrD#6C-=OKo%>0TN%UVa(I z(0BPe7!&zFJPj~{Ei-LY@ULd7DKtMbOSd?aXaTC$y(<p-0#<xz)<fxMXTbu;M9a++ z=CG-Mpv(JCAn0ZK9gDg_y8c6crr%#P{<pfAzOrV5ejn3^tQ0%k@AdU{Gd*fmElgu< z8)Ixdk1;#x9%=?^OdlhfFf&#oT`ptWNnWCsBfXxmsx|o7-C7>8Vb|TA;Zd7vnWHsI z2xiyvQGa!<Nt<et+lKl=bk+oABb0SLkbQkUn<QF6)JY=;N%Kitfw3*5Oi$a?4FiEU zyn|gqrY}>JQKX248LQvS*ba(RQByM6;Q~4njXpsxOLwo+b3{jpmOVfl)@g$1A)@j= z*}1Ydt1BmoGNRR4x|KT3>o{GY0x&(Y4NooALIQtXDxz<=vQ!SESemMYIqXcic*KsM zrJQ`+jwco?z>YJETMgS)7rv6FAC$JhI98{3Qnn*q&La+trX9GLezV!%FE3AJ94Vx? sBp39Dm>$cTAieU~nhAvHmE(m}dy0kL9iT}UrK6YV3wDby@73k}4;V9682|tP delta 1241 zcmYjQZETZO6u#&7?I^taco#R)wX=Iy6Pf!cu))?9r@oAhEKwvHV#FCJZA0g3tLru( zVq4=dFc&PIMj@F=WuS=;GrTit*k;EMbP$aDp*W1uF5wRe+QKg)BzoR$UHEbG+~+>e zIrrRibAQho7P5x;D<&R|u>A}o7x!%eMJhBEt&=2)a{yjsD#9^1%eQV3JNdW3A6AJ6 zhS36^s3vSOit8m;ZQ_>K&*8Lq;o#RxhJXF@TsL0ty}uSF#gzdCU><J_2BA)L9C{g` z9zzieR~p23hl?abgHnfAjyg;+i}ECswIn_`8a1buiBV-r4U^Rp!VM%Y;K%R&0resj zDFtZ2_oCyF5RTYu21ttG_dnIou^+QH<(9LLTbC-Pmf*LwyetY4jcKfgOIn8Y+RK}{ zq?T*H)N9o3q$8_$kLNet)|-!SE?v6JSfdsAh$?2Aj!2L|m-7alSlU{=4xFgA2c%nO z%_!pSU+5-ucKoV)OFCn~hg3YZ^QI2fT`oy=C@pw-#{f_0yhA_1-*sN0TE%<2ITh~h zzE49Pn>qjlIODk|UfuVh5mI>VgUw?2*gFQ%KK!QyPGSG(Ckc%w=J{wf&Nc-^7Oxqh z884mDpjJFQ)1g4K*#6aR1B{6JZ$@>vdhtIK)Z(V`GEPnWb*W8n!Z!7#-rJ8;FF`9> zrfVdJOk(Hs9yo`i(|+1C&b$ue=$W|y<D&HYrvVqzCD@(b0WJ7>x`k{v({t4S+1Xt{ zuYC8iTEOp^@v%8442kFGzziqEuFT28PNT~c^7@!|$1IyOC5%-v#^QuF!VU@p1=EHq zWOK5Ru~s4(!YabO6a^GaOIDzK?-@gdT!nAv*5kzAax`X<%@b6nmh^l%53QHWowmrP z@R6`97z(;5oxJ<W>v+Wb#;P|(szPcV?L0?VO86o$R!+#Yd5gTJzvoTYpgX{{1+r#} z8QZ|3jH$G+lVvM~wB*g{J<;w{#PaI1tLky9Y>tuI@QAv7RZWt*n^gTi`CNTG%av24 zW{MbV$*b#W(X}eiTV(*IWvuw~Kii~arEI4;l`98BgTB6?JLvH_`oeS-Y|3tg7<#ge zFoB<B9X#_m{*bNXaT}go+{kBbm|iUB85?fPH9{PNxhJHFD!CTha%Q}cE8CN)k}G$+ z`+UKE)$b1b)v!M_5b&x8d@4<+$LnD9k!bGyZr7on0L^_!mDlJj{1(0c$O`fGxtW$& zApxHU7jxk*da6*sODTzJD&Pz2<0dv*O$CSrd_kt2%aeeIY2z!TC+KC`<VsTTaKHHM HZd<|s$~$NM From 6451b612cc1aca4f987507be8788661ed63d8f66 Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Sun, 28 Jan 2018 20:30:44 +0100 Subject: [PATCH 103/112] Less constant-bloat. --- substrate/executor/src/native_executor.rs | 14 ++++++-------- .../polkadot/src/support/storage.rs | 4 +++- .../release/runtime_polkadot.compact.wasm | Bin 63401 -> 64258 bytes .../release/runtime_polkadot.wasm | Bin 63450 -> 64307 bytes 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/substrate/executor/src/native_executor.rs b/substrate/executor/src/native_executor.rs index 3018157001..0db4d683db 100644 --- a/substrate/executor/src/native_executor.rs +++ b/substrate/executor/src/native_executor.rs @@ -46,6 +46,8 @@ mod tests { use native_runtime::runtime::staking::balance; use primitives::twox_128; + const bloaty_code: &[u8] = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm"); + const compact_code: &[u8] = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm"); fn tx() -> Vec<u8> { "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000".convert() } #[test] @@ -55,8 +57,7 @@ mod tests { twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0] ], }; - let foreign_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm"); - let r = NativeExecutor.call(&mut t, &foreign_code[..], "execute_transaction", &CallData(tx())); + let r = NativeExecutor.call(&mut t, bloaty_code, "execute_transaction", &CallData(tx())); assert!(r.is_err()); } @@ -67,8 +68,7 @@ mod tests { twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0] ], }; - let native_equivalent_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm"); - let r = NativeExecutor.call(&mut t, &native_equivalent_code[..], "execute_transaction", &CallData(tx())); + let r = NativeExecutor.call(&mut t, compact_code, "execute_transaction", &CallData(tx())); assert!(r.is_err()); } @@ -81,8 +81,7 @@ mod tests { twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] ], }; - let native_equivalent_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm"); - let r = NativeExecutor.call(&mut t, &native_equivalent_code[..], "execute_transaction", &CallData(tx())); + let r = NativeExecutor.call(&mut t, compact_code, "execute_transaction", &CallData(tx())); assert!(r.is_ok()); runtime_std::with_externalities(&mut t, || { @@ -100,8 +99,7 @@ mod tests { twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] ], }; - let foreign_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm"); - let r = NativeExecutor.call(&mut t, &foreign_code[..], "execute_transaction", &CallData(tx())); + let r = NativeExecutor.call(&mut t, bloaty_code, "execute_transaction", &CallData(tx())); assert!(r.is_ok()); runtime_std::with_externalities(&mut t, || { diff --git a/substrate/wasm-runtime/polkadot/src/support/storage.rs b/substrate/wasm-runtime/polkadot/src/support/storage.rs index 201556fec2..7dcbcaa5fd 100644 --- a/substrate/wasm-runtime/polkadot/src/support/storage.rs +++ b/substrate/wasm-runtime/polkadot/src/support/storage.rs @@ -123,7 +123,9 @@ pub trait StorageVec { } fn set_item(index: u32, item: &Self::Item) { - put(&index.to_keyed_vec(Self::PREFIX), item); + if index < Self::count() { + put(&index.to_keyed_vec(Self::PREFIX), item); + } } fn item(index: u32) -> Self::Item { diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm index faffaa1605b839e2373e04522082b564ed251617..84d8006b5c7b0d48ff65e134274f8965f965347c 100644 GIT binary patch literal 64258 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 delta 25461 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 Gul_F^1`#O$ diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm index 4fcafd35025853a4542797c75f0560bf042b6f06..2141ab632f4a0d606c7fa27b6c39c9ad53f91ec8 100644 GIT binary patch literal 64307 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 WJ;%RliuVnxKbzu~MaZi`)cOY;Eip*| delta 25564 zcmeHwf1F%ZmFIh}s=KPY`bTwDb$6vZKklpUPO7StP9RAKItY1<K_bMkj5v(5DiNbe z(fL6V@fY$M&0v-dB>I>ky5Pi-&%mrA?KZkuH!IEfD=LF=hy6@Y*NL<2$n3gf1_Cw? z>VCiH-uLQtCqM#zX8mIa)92lD?>qP0bI&>VoO|!9nS4I+gP$i3{C?50Z@JF#Z?UdR z__z2L9(^Dz+yCPB2D{<H3zF${@FBaWC*9JVY)vMUj+1V&ZKtK#X>*+R_N>zsJY+Av zEZ4Yo)7I;Ee89@f!`2;EAqC9V?Kf?*I*Hn~X}8tYxOL;$*!JtK?&Q07ZrWrOTQ|Lb z)AjG&z3CnA1oj5&lE8I3i))&)w&huw=GV{fnOB<A>#iDZzV%4rg5XWg4*UGcN1Tgn z=c(f4uM+QQ2#fn%6qh#ykGEg%E>}sFEIY+gLOHczr>GJvW^2m!k~QUI^TE~Gt?9Cr z@$OOCg+WW#h`l^`L)R|+{m)%$INzhvWhd!2C>w92Yo$clvGCe*(BWe#C1fp?QZ|Y; z)hIMOy6?4nCLij47QFQZ_s!WuQ0=)BVDc+H6^F(DIrsf`Pw@76_u31B7v~My3nt6+ zS0-&0yuI`}yAm|_Ew(F@tNM=E_T0%+{reO4K(MELuRSnXs<b)j0dV|O13125@Nb-h z{Xxg#Y5T>XdC7(N`}!sO>{G$_@q8-C46U@E3cR83&hO_Nc6K4a6SisspTvZZL3Qaa z^ziAWqonqCOV^@MUiKwB7yNh`EB^a=YgzHh^DeCy`p-vUa`X8cZ68!si)zk7kg8cF zvx}_E-!wS|D36E9g9N=3)(xf3VJE3Ny(boXPZhJTQ=Mfe?K%XOn+M(+c9Z~X4Z&*b z^}2MKF1=BMD+xxdH)*gz<&~rSPH)PpWm|wdX4NoHs<UEUUg}zf$?Ei$2}T!Kv4#~_ zsZIs3OxI@tRLx6zRyLtoQXb~nOI*?Gwm4u1Ls;8tseIPSpxC19^(b|E9W}QVz|Ym( zHo$z%Z3igSToUZ8xg7vqH8%&)U2_uv#hObQ%&9@AI=!Bn+X&EGb5j6wYi=4~Ud?R+ zm|t_70T$HUjI!N)f<j5wC>QqJh^JwBYOZ-h2H6r-x8Z3-s!gl*2$8J?OWsn!%>MM6 zwGf=DsXXUnHHbn4=^Ce_z!57-f`W~8%Tm2-me9TFouxVlEY0A8{1X{+;;6!zCQjO< zYZc2n*ZIq4FcQ1w<}pKHzn>H4V8Sq6`8Tv$nG6`1rF(v;e9G3!M+WOc{w7LBe&6Av z7X4%O$H(~?$(bYkUWlPyp01X&M(3l+IjCor$~Q|FZ4T4+8g_HiysukYBf+_7B-j>} z1ka+AU|5tAY`Qtm^0i*oH9${442fFcs8&7ZHZ6sAUCL_EF=ON)MmabT_A8FMKIjc% zp)YBamZxS6S!NT+nhR5usa6H=x>~8g*@eM&2A_NDwa%$x@c5sO`Cs1XEcKnp0Ub)* zP#U5G8uC)Z&chDi(dw`>fd@QJaCJCAB!;n9;IK8GV0pE*N8qq^n<?LJ;68yP)}03K zPk^MC!b{_c+6dgykay4)=QC8X_9jZpINBj^O5=1%p=w;J4%*-Z$SFJcr$b%7X_y7v z>(o4(u8C7Uv;_QNF44(H_7;aVvwNCXTl*Z9^%^&@3ExoJ+7ipc<YNfK4u@36083de zXB`T_(nJz<g%`e!dHW=DJ1Rx#hrE6D$2<AR$tGnjr2Qc(t2%(j@Mnyk2zVCS^x4Xw z7i1`?aQsQn&L+I%Iu0-RgSQR%dN>^%j->!BjB3c+Q)lxwKGH?LnsIa}zV|ZYSZoGz z;^imvgzc;W!<DxyU*>_643XOR2pqOQZOVUU;C%u|tUovKemhhtXp+cOcUZz;E6yQ1 zlqd9;%U+~Y&Oxa<0Ww5F%h5j@Wxc2Rph_9Cp|zjzRj@VQCz`I=n#GNt?ouw!k3WMU zF)cRZ{E{!d^j4{*6OPN#6AO2}&qb&J>|qD~NY`>|j830D^L|{Ym|fcV8JM5J^K6!F z@9C7PN>q@;>mmQN&lvxE9k?Rhs><0f!`rNFg+W<djLtML3|EFdb6{4P<6LbmCK$Hp zrcgRxgB1iL*02VvFd)jTOda85Sj$4q*lQHj7w5yOGOI$(*vr@0rfz7Afk2}Sr-6ZV z$Z$JURprJ?IS62zTd0r93@ZDeyA*UVWvU|!m%|~uon};Bo`opM=ez4#WeyL+53Oyr z;jgf4aU$-)vQ5AFX}~n#p8+-j-UrwW_~(EW-Ti<qs^GQ>$u2jWfPB59SaXZDk_CE2 zIvMR|iOtragjs-!<;Tzn<f}l7N77=+%4?T{*wdOA96-e}uMh=FmdedQfl5wQLlo`t z@>R}ekf2_GpM>fND}nNbMlwd$SczRHOB$P3Ibs}CDiCQ<iHHbM-~%bl3>5fCDmz4x z#&}|tczleIG#XVy#R<m`6llcB0>jLvPL(9~I;$Mc#0kwtQZ<Gh2nr;Gs*w;|fkuof zX{4cMoZT|H@Z&uY1rl+pz<@%GC@Gu(7iB1PC<7~EGFNAa4a-{c^ch9yAbCyDnutKQ zhq?4(7<fvVN;cu!n^z?m2T+mBJIAWoi&d4Y3YwIi%V`k7Z?3OKUc5ywfqI>o<(uKf z%)(zH<JuDKxHFvPSe!Nd4{wDYg)3it#h<c~L!@B-LG!y7yc`cz5mjjWB=a(>!W3<v zZR(3c*}1aSZgDc6gAOt9D`BP?*tDcQIqx_2jh+)+wrLPNtg4Bd9<GT6uVi{N<gH+O zGvqC2dNbsm&-7-<J5L+;GHu&SwP_D&%U+@ldok^L$QxwzI^<PrZW};_u`5&%M$fq{ zGlUgq<#t@!(u9D|ZOy2qqv|$y8Kl?A=%|Y>cBxvnM^LS*fWV(i;HcVre<?fcAV?Zg zc^wZ0%ip~M<Dga11cn)$sXQHl)&@8wF4gQBehDsE9^sloEWA_r2nSV<iS%*`UnMB- z0UZ<0R1y#c!t>#Spdm}O%hDb}=@Jzat2hecs{v12G}GBkOG5^pEVaIs?(^J-;)eq` z%dt$n%vfH{Q2ZzW;8>CzOJc@Yl4e@URv4~OY?7kA_L(_c^<zPdXd3M$wBFY+Gf9jl zaTcTTMGJmQ!<iA1o!w{{=AVV4aX2un*Pv)Gp=W-SNX#;tso%1q&CoNrG##uA`LvlV zf+@yd3`%H5Tr_kdEMX8r8Tx?VmOI!pC#G}oKX7laS?Q2=A*8qH0kb;DJWKD)G}E|e zS%4+_!c*!@P8#^6_S1MuoXJ%qkd!pcxN7aWm)%dXV(Y9WrMFqJ@0bRk*d+AI;X~3O zLKx!r_HoM+i|>K0=h;KS{%vc2?^F>2%rel0+$6pOsOsd>LO@Dv9;+>$k?7X(236Mt zrqtLqfdK@Mk6o;(UmQ_qY$pjT=$sWfCRKGd-y&|GY@RbA%@>xmp$b-_(z2^CtpzWw zbKgh~@BY~gITR$IEn$C?%SkAQE-WT>IcU5=&5}d6TBiFOwN$s4x}x`A>6J5h$F`+f zG;5*`vC|ZZrt54ZP0?g8tdn}%iy`l?f|N1dXfF@8i{voOHZY&TqdTZ8zxn7|ALK<< z&Seg`it2PuLLkY4ayseboal58GZJNUDwjpLLN1UXHS8``J+;+cM9jtT9rLwwap&nM zFZ`>j-h!RpC7jen4~~{^DM^fi{Ak(zAmCrwno!l?xf}cZ3U;`>hMU|4Fjc+4BQ%@m zR#m?{m;gUvh@J<<So*_|93gfASf)QS1NBZ|W7!WC-Nfo9cj-bPq|+aGD2YmIrEXO) zIE{jt6`=?wOX4cRa9x5F_y^=2b5vJYYXbfr)g8xxLa!=@7*b&7QpT9lLSU|%Q&|#b zVL)L#a}>@`%wT{4g&x%#VlefW?ixtYpl{f<P_JwePm~>)%Ga3+zPM|yFUwz)FfnOF zqt0mfI=e*2`Pk^$3OyHQW^PQGm_h0!q|~Kl6H7xvvJnb2E;Ujmjsm#c1fR$`4XNV; zNJVsBiuQTtBt@#!X1cCX1gpn`6Jv|Dz6bVuJALtd^n$Nona3fJwD=m(t0ay)uzZ*$ zjyxDnqlYoBC!*%i=o&OG%8m;VV#3S<IOW7}xPtQGExW^75}trum=<%P6WNLyi4ceq zB^5=9P#C9Cz)&p6&=>_vwjz@#oyiMRnnow)2mL23%)2y`2@*C95l~o_K+coHK?^iw z<R%57{h|E5`KDed!m?Ef?32RiD`*zwk03|YDQ9sQD3Kxla*7QCj~X2!Fs7L;@HP+} z>Wo(+qJz@BL#mnN3@Vy@sS+%DUtedJ>IcKv^H#a{+>pH#O%VqN8@DadKG{FaI4N8V zWeJEp^I50>$6<D^bOtJ6P#@>LsyAEvrT_9+tu$~M7X*<7W}u+@p%WEfL~hWS$xfi* zgyLA4%zio{gH`>NL|Q~0*-9>)JQ0QHL{;mPOflJ{?rW_JrxW&;@Fj1jY{64E>@n<_ zDDYFnA|6M9N(HtZa-y|!hH4FJ<&CS>9Qde^$Q0;;NRO%r%EZs1YDIfLy=pLe#kkKw zIJ1z7PV~f?#aN-z!F_hap=oR}qEe~9O!b7n(oFlzhA{Lv*F<6H-7&6-0@p>uwe~f_ zG<JRqQ7@g**t_a4v%iDjOiaVrm<neH<3Gc!gqtbkj7}1xVR9`Sb)qCPDG>^s(cDd| z&}Gn-(znRO)>j_mZWuRU9q@$+aUg;d-TF!p?Z)Y)q${@a=#?bCoavRs&?HGP!JW7? zcrZI)G2-D47-(J=b|^UT5Ti;OdJ7EazouO^Vv$bLEM#y-AOBF%uc|)Jr)pJI&-&g{ z6$e~Uc`WPedP}_zjyBw8LWE=#A~blm+l7CN;jgP=wAo~7F`{jTNM^mO;*s_PF;>D3 zr4AF3H+6U%tU#1{miQt@g4M-jLZvz3iyRW&xtx$`!6K9hYw?y=yfAi<bsVIM^|g}} z^xooPu%zW;S!%JDeM?PCL`qn^Brae<%MnjQsuw#rSO(N$?BH-Yz^Uy4+gYP}FnI44 z*Y%XEC=<j*IR%GhBZm6b%?sh%p@iD!R3eWs7&(GDb@zkLpy_52Hhv{EcB-)PD{=cK z3WH>@5;JCqDe@~mr9U5$i>cR}Zne^a$kL-FtEA?Jt;mX5vLe4SPt6aj!?0|=S}+3z zRu-sIh$4}xz`dpaYU*^|aTvc*iZNyU2IHxaPvbXwPiG2#qZ-_O%RGsnLjQ0svOTIz z+sHQZ1yDsJ+Xz*ct+7mrD2#g$(Q*`__8R{XiwebyfCxtsS)6eXosg8qbw@Oc@qjXN z17$Ixp2(7ATRV$w?cTZ}Gs+ciXT-Gd0cC2AHo`csL}9>jUWq!LS8Q)%Cq2jLAP05t zVsy68=H6xshK_)vE4W~MQ4`LFaB2g85NsY-!{WqD_}i)GMdO@ro{CVMm^>H*r`6)% ztK(h1xF%R!4|s_T5#bLV8VylSj8FyV1K-UpIv1|Xb(LbEs8pZok{cJ!8nuXisb6v> z^6V~Yu`|YHMOE0zT@uUc_I1|J{NTRiXbe$VEUiO2_v(Wl`nNM5*UdQC%7JI_k5HF) zeTKZB;mQP(Oz$79n(ubw;Ta$hIeVu7D}c`fGM4)V;2gjg02wm=5|GE){|q=6@I}CR zfWHDna_IdUkjdR|02SakHc?!_TLDXe9|7zG{3u{Q;2!%AYwiFZ{s;(0ySD)%-Sj>N zSXNzb4(^W^sBC8PvTa?|rHTfFv90ROYED?vmJ@vD_RW=Yh+}k{;~DH~(AQxY6A&yM zGAq^KCu4&q)vjWxdewm_`^H@l^o21{#X+B^rieqSItU{44Ia(J%wu7#A}KksfFXSE zquj4x^8ebkL~fr%tQd{xB3oVh#?4~hqH(K|hf`M7n5=lfNMVIL6Zx31aNq6K3M*$W z#YAlJQW^xOc+ZSM0}{3Rtr#<Hkl69X(Ls8(`Ttwh|9h*#g#4~qRa{3zMSfSTsxGVF z39EvGT0$?d7^dfOaX6H~{jqt;_KbH5_lU8v&FjQgCfgT1TEP#NpO0(Btt)<xzrR|+ zE5<jje7D^Z9A7zRAD&!0{5iSF{LHErCplHd)m~?0idUPzKJpnmIlU;maB|B<|J!zs z4+L+yc#<G<$xoaE<=`JL`AZFYC;w{A&lAq)-N~=MzTI|C_5|J=^TFS(eXBh*`MS$~ z&z@JsjyYm(+dELkmJ;qvDV(nY6kR(z7(Dof>zs)y-YHD>U0$;7d~n&i7o4NSd>Fhw z@<#Hy@QP8QYFAv<J(wL*nYFFBQjMMcA`Xce)n?BNzJEoJf2c=<Fr|TwO(tHk#^ncY z`YQ{saPvQ@+68J^dCH*62A&uYBGVciSSY2iQQ9;L;c>hLkBU3Zs(o!ArY6a$Ij$LK zK*zkA+^!k$rhyLbxbn$NOd^vvu20$aVDN!At>p-(-n7ZVMe;=(-kL~G^`iM7U46B4 ztUCGR)oX0~WYF{GQs)7nF^UH?I4<CD@DF#K7yQM(br9dbzhkAnFsR%y9zCD9<JRc; z;GGZP+1u~7Q%7Q26Wq9e4{Dy@?>0r+6HI@4%N#AjMiF5`HOh#1-+WQ<!9Ts)xy$9P z$GI6CfMC&4cD5&z1<)m4!OqSN)*M*vclBVGXbMY}jk~Da(?ThM+k(VJm~mW=7knKf zZGew33_G)ugoJdks{srz6NMN}8Tbfu&FQ3(36M~Xw0;fv=(W?|LiAaGX>!BIClmIH z$;2OD?Lc;KxqB)8-gfsD`1@b)9>(9MgT!1Yf43Z5*oJXicpn{kEASD(y$6S`%J<Ne zflI=aX~|Q(K1@BWs0O3I4N^vhAXI~C5GrM;xfLpB(EG_JpeZLmInZ;kpPwFBo-^ze z&@VUUhLICk-jQJGrv{Ucx!Hl>?VlQjm3`(@+wr&K-+e-!w<glr<w4<|yG$v8(wuw$ z0;R9r%XZ5@{cV4n<HT;cW^X7Zz`e6Z*~o}(*FtoH)6N8XwX>rtvC>KNzC==gz2H3P zHlQiKWRTnKa=o@eCHJ^OfDVpV)*zJx(iGmEO=j-5Z5x*c%%%Rs4Z*L!{kj22)A62$ zPC4F5%>K0Km7{S|DmmFD!FAs`uk&d*HY>B=wv#?L97*PhfneRCYY9GksNDUjf9-Vn ziRjkuMCyhTu4^Rql~~97sl{O2@eX361ZOhqk>T5AYjdfY;W>7Zob@H#l64TCEm)5e zl)QID-^I#}%I1bHBjxIhmyvI!bU6pBh|W+tQHYLCQVPS4j!g1wegyP!?}|q!eDo$7 zB}HtCP6adyy>&-fqeh{_f=Zd>3tK!D5WpqPMi4m+Gr(p+PBn$qf+EX)lxXT^WINhe z5h@dntDM70veF<_(s5RR0u@|>j|j6Bh_uXP<!}<LG=K=$XjSQ`brvFTQ<<oYH;bwz zEOHPN4ctIVt5$=|s5bM|qLWC}3ZIY|dT5G>cSmFkr&EMjv^0iDom-TS%;igseHwlY ztTzR3`0OHohLAb3X>Ra`vVBQn)7ayJAX_8(;p-05ZSizz@iICOQ?Ry%L)Qq1EE0jn zgz0ol633~ni`KU$0lo$GZlF#nWRQ{aw#StfbC`{nF%2EM+%7IXJnPG%bb%k1I#5~` z7G`KKwie>rn^Wy(ppo_>Q<;Ghy$i24o>6-vy~9~hsJ?N<qmrMlc(b*)t{+;V#gOXy zXS8>g#>~`SKb+}2b-yjrojkj*?@DUp5$$b?rm#Djy26>X_bjw%q5+p~p}vtgR9y(O zj4m2GmqBQ6GO~@ltc>8kAu<w;!U!5?S_{WMPOS~^hqn2=`6<>?jP6UyV8_vvYCElc z7G8>`m?-HkG+y0Gx(oNULMxu8%Q`47HtJL(aOpC-bgD5>{qPQ{ygm(Qbua;?r%!KG zM#+tC$5i@+73wWj`gl~LO5<xU@xK@fZ6Nf>m&+qm**BxAt8gm1lq*aazkBvGR9DKE zbXrCQTj6HRo_byJ{snX{u5t@8$*-hyP_>{I^!g$XagmL1&7lf)M;cT(efr?U&&mvh zC8&|CN|8_12q;Q)lA|$Dlo@WDwlUqHn!TGh;2x1)>2snrY3zjN*0nYv$Z3Ki;$(CR ztKVpHRpM~cOS;&;oB1DJPGTYTk_;knnI9W&_%@6YpIh+x0{+S78L8s?Je9kllwy<t zLsPk02_K4Dq=17)uD#vszz;s$yP`FXC@K#-@6KiwPv}cI22WTLld4DMdfgt>gTu0O zB*{%%af;bxs=)0b!5>a;aPfg!Mm2dYIBRWEJ*)68LJ97z7NjA!TANr*@h-6HT!)Lg z3A_WUhm&rKJ+M;}z?M@g*m`tsaMMFMUwUOtN@6)T(~`qW2sx5&5B6fiM@^@MjE*?^ zpd5f+)^Mvxdl7M?xXUGYIElJ@g?s2Wcsz#3b<nA6D$a4Nre@Hjn?^hBGfGkT5Uvuf zrjFh^>eDP2MN<d*?ZNjx*Xf&p3nDkFRf<+63C2LA+0@}N)aWP#V~j(Uq-P8JqBN$l z5Ws79M2eb>^s%wNf~dT9F3`-D$XT~Vezbk&nnAmQv#a}|Ce>{EEJPM27D#PB?zABP zurO6^*x6H^Ci_T9>W9gf)GvjP2PGYOnt6&&4s+51VX#yvT!)rRb_O2Bwq^K+en^T% zgt(m0&FMxEj*&0*K$~tTB`saVgSaOnRS1(q1>sAOD3wGDH>`<?R<Gv_($Gq)LfA?| zSIicbi8XP`daeqlCVh3(DM=q>1kEWm5kIv|Yi~rFH6TrsXHASWYru4Cpgunbs|d1< z#leAjX`dS$)ZCUD4U$jG__-{{IG207G{?NR7<=SVp&T|S)Eo4}$3+cP*q|k9pfbZa zddc%%N-Aup=HPY%sUxb)dk;6(8^fR{8ktGvJ$%*~1+#g6{8`se@1okQ<N#{D0`DME ziu4s<{-RX3!XKd&MFOJXTp-_!w_t<#Td3g$ZW`p7=xMaU^ze#3ZtwTp?;=ak9}z%< zJzPo^hoT8EJv0<zZ<q2OcN54Bi6eu{;QOqu8+@JP;d5)%rM)lQF+Dhou#0uAh|raD zMQa;Aj=<{B4x6FkVO|a)BOAqu??HSt$ODD?e>fTu|DX5p%>s3S?gfusUfQ)2I60y7 z$D#@6@0XgqOV+oxz^Sf*N_yq>=&;GV8=Bw5Wuc9s9lTxH+T#5m<e#!GG;v*MhwsL^ zK-a{97qBv1fM-~Q=@7dPlp_0HAs=dTIuX($9{L)E;HBJd$H(!Lm*Tw}xCSvNyat)9 z07ZU)iA725g>T?UD#vgRe}y(`Q0UgwfaDH}GzhDq^FUCQr9*sG)y?xR-2IdeNsHk- z1JXLPK+sn78=7G-1{%5vsyQN7gH4WBGZ^D2r(Z@-DO$}v2`-2^+In`WhOk5!0VXo% zmtof2zX(T0k78(1ta0|GBi&Fpv7r;w))-m=8*x<-fq@3}r+dU&fx4BDW+(&kISfF! z+NSzw-%VI<F_~t$CEv1`k~Y>^JE$F9203vgYq8^CXYti^Ym%R3z$x96aB+m{+FWPx zp*HT?XdEgbD(;j~<7cTqd=9r0w1I_fjIwBaXhQHyu!Xi^-hz>(Ij361B^if8AHteK zsCDd3LM5C*8jr>=-`}70N^m^s);uN!?_@E4xWjJG=l8REPEp351x}et{G|(tLn?_P z4meZZ+zrORp)s!4u^LY>M35Y|uxz6%L}Zu<20WTUT=&76m_Wz`Yh`P%AD_zzS;Q{q zJyghmAytx(dQ!nv4_)A+AL@k`evyxeXV44UC3$ZqH*BE`C==rx2tQ$!dai=KYDxBt z`Zs$IyV;A#)igh+0z7GB2BQ_Dn<)f`Yu1TEyqrc4wm}d`&J50F$-!rt4|C~3`O5-V zTVFBoh`<r+s|G$IVI|ta)^RsHk}deDSce-*W|^VYK@D|@RTI9{ad(GUq<JPW1SG$T z7dbt(4%-NNeZuOB2sK*!Xy>x5MxmLQzRYU)?V!XTvv;CkMnXi^BAOAXVAc#_UfgrE z*r@MO8q4Gy9CStBCCY&LZYH+)m=qpvEKbDaPw@E$n`Y*#zhBJN7c1!xYZ^pS@1{=u z%tTWW(U(l$xQiuQadc}~d`&KLIpj(V@|AG#8i8p#O$N-1%g!mgwV|akqgrJNY-M1c zQ<-4xe^~6dQH?VU$n}mWh(q}$oyNKSi%hF=aQ|z8tL=}-qPE)JBXGpJ&A^WtxYxjc zW8m!u{#yh08F+_*clzdGzkvq~{J4RiFfcIiE(8DAz&|nYZa|Jx2G}WfCu>lXr?L&m znk0t9L?x`q_6{W&AK)!`c3ewvTY?Wx_WH}UIr8tcUFwt#P$XOQ402t!iN+t6F)2-$ znWzl+)&w6Hl`%z4n5U?W=nYv>y^I-a;vysTnD(iG9Ks49lVKzN9*x45_q2^MQ0rkR zO~Hi^FDi%y%Aia59f>2f$5gQUVHex+fAaABw<2YOXW~!Y(33FS!JEj|jMwA!99D)@ z_SvOwLj~{@dSla*?3MnX(I7;*oNg{?`_f(On*^oFBLIr1o}5ATlwIddZp;bQy`;)G ziyV?_@bfQyYOP^d5>4$nARb-fY=B)9V(g+%88qO-m|!-YXbc|zat|DIrsg5`p)+sU zT55T4wB?qPgoUj+goOy*@Kpn(g*%E^;tD1^*WYb+(l`n#<Ko_m+l?r!E<3#{<VSG@ z6>`bROke=6krB=!k|H3V!YZXPhm;D!Y5I2@bH$f1Ej_GwoE$E#GC8`eUnrpvjuv9X zSD`XmKwLb;cE4OaqyVLVN|W8Hrm}N^RcaDO%pCEI$M69mrof46V$jE5@uBb9XLGe- zrau30Uv~xzVaphrxwuuj7IAbp!-Y(6?csUdDQ`D)sMSKckJBi~2M0T?sM~kA4_Y^I zxO9=$P-8u2D$VfB9s+zj<q@Au43Co;wEd@|4;KZI$OSFgk2qj6ke172Y1JapJd1+P z$R3HvfI+LsK<0(=?}P{tEm0s=i7^y~0Lh6a(N!X8g%ENKU65(=Ru3u*ycyQytU>6+ zJ4>>Ikuf_M?Y?Re|3Y_({utJR+~G!O65NJ<2CWnV7R((_3s61L2rmLHNTD~-m93Gq z5WvNv#xP3|KM#jXO{T;BvT?XyG4Kc>zft_EAV#c544g9XQ3L<dz^@tjbpyX);5QBY zmVrkN{I-GLG4Q(vK4#!w0phrA#CqHyzK7q7!VPf|1I~A~bJCe~#W{+-gAgZ+J=AO} zhJ&^<&VZ1lovfgEq`pgbLB|@d#Db8;&TL}pCUg#A6CuSj6&@l=RBV=jhZ`{QxN8RQ zo%g<s0(R)M8GZ!?M0~pD2nvO;@KqFWQGjWU1X2=MJpyF<8jUTgHq_{_38RoWUJm45 zI%az5kZHOhSb1cLzXXanja@*vQg1K!Gx$S7*$a92f*_Cn#tg#@z_4zZp2aS{r2+Sz zeA*T=8Z91mj`b&c6509DPJUNB)O%^RWj$e}hcyeUD&p7P*TCt|()<dKtOlF^%Uplr zZ2G1Cu-~5SO4T#U)fpcQ!ObJmh7!zCy})IN`>^Wy$f$L7tCd|mQ=-_+KyX-Bj!-px z=thW!W`vK>i!*427WF-@;XfWqzgpGs8FMpXuM0Ug*i!FRt!*;GXw)B8y?TVv6i5&! zp*eiY9$FQA%54Hy+qWCIPau9Z%E0|e?>>%0D}&?&CN5_8&fa9G-zE&{tg8yr09Mje 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 J^DqD7{{_dzC~p7& From 4dca28441d96896ac7867991abbd4e83e6e2070d Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Sun, 28 Jan 2018 20:32:59 +0100 Subject: [PATCH 104/112] Bulid script fails fast. --- substrate/wasm-runtime/build.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/substrate/wasm-runtime/build.sh b/substrate/wasm-runtime/build.sh index 2c78bc67c7..83f46d5a04 100755 --- a/substrate/wasm-runtime/build.sh +++ b/substrate/wasm-runtime/build.sh @@ -1,4 +1,5 @@ #!/bin/sh +set -e cargo +nightly build --target=wasm32-unknown-unknown --release dirs=`find * -maxdepth 0 -type d | grep -v pwasm- | grep -v std` From 5b179842ecfac8de6a7f7f8af176c11870b73086 Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Sun, 28 Jan 2018 20:34:18 +0100 Subject: [PATCH 105/112] Remove old comment --- substrate/wasm-runtime/std/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/substrate/wasm-runtime/std/src/lib.rs b/substrate/wasm-runtime/std/src/lib.rs index 82e34f3297..f19de6836d 100644 --- a/substrate/wasm-runtime/std/src/lib.rs +++ b/substrate/wasm-runtime/std/src/lib.rs @@ -162,8 +162,6 @@ macro_rules! impl_stubs { }; let output = super::$name(&input[..]); - // things break if we try to take the address of an unallocated vec, so we - // shortcircuit the empty output case. output.as_ptr() as u64 + ((output.len() as u64) << 32) } )* From 769bd9d10110addb8b76ed15f7c6ce0e26b74c2c Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Sun, 28 Jan 2018 20:39:18 +0100 Subject: [PATCH 106/112] Avoid using the controversial `Vec::from_raw_parts`. --- substrate/executor/src/native_executor.rs | 12 ++++++------ substrate/wasm-runtime/std/src/lib.rs | 6 +++--- .../release/runtime_polkadot.compact.wasm | Bin 64258 -> 64236 bytes .../release/runtime_polkadot.wasm | Bin 64307 -> 64285 bytes .../release/runtime_test.compact.wasm | Bin 13280 -> 13189 bytes .../release/runtime_test.wasm | Bin 13405 -> 13314 bytes 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/substrate/executor/src/native_executor.rs b/substrate/executor/src/native_executor.rs index 0db4d683db..b8c90f2d9a 100644 --- a/substrate/executor/src/native_executor.rs +++ b/substrate/executor/src/native_executor.rs @@ -46,8 +46,8 @@ mod tests { use native_runtime::runtime::staking::balance; use primitives::twox_128; - const bloaty_code: &[u8] = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm"); - const compact_code: &[u8] = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm"); + const BLOATY_CODE: &[u8] = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm"); + const COMPACT_CODE: &[u8] = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm"); fn tx() -> Vec<u8> { "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000".convert() } #[test] @@ -57,7 +57,7 @@ mod tests { twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0] ], }; - let r = NativeExecutor.call(&mut t, bloaty_code, "execute_transaction", &CallData(tx())); + let r = NativeExecutor.call(&mut t, BLOATY_CODE, "execute_transaction", &CallData(tx())); assert!(r.is_err()); } @@ -68,7 +68,7 @@ mod tests { twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![68u8, 0, 0, 0, 0, 0, 0, 0] ], }; - let r = NativeExecutor.call(&mut t, compact_code, "execute_transaction", &CallData(tx())); + let r = NativeExecutor.call(&mut t, COMPACT_CODE, "execute_transaction", &CallData(tx())); assert!(r.is_err()); } @@ -81,7 +81,7 @@ mod tests { twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] ], }; - let r = NativeExecutor.call(&mut t, compact_code, "execute_transaction", &CallData(tx())); + let r = NativeExecutor.call(&mut t, COMPACT_CODE, "execute_transaction", &CallData(tx())); assert!(r.is_ok()); runtime_std::with_externalities(&mut t, || { @@ -99,7 +99,7 @@ mod tests { twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] ], }; - let r = NativeExecutor.call(&mut t, bloaty_code, "execute_transaction", &CallData(tx())); + let r = NativeExecutor.call(&mut t, BLOATY_CODE, "execute_transaction", &CallData(tx())); assert!(r.is_ok()); runtime_std::with_externalities(&mut t, || { diff --git a/substrate/wasm-runtime/std/src/lib.rs b/substrate/wasm-runtime/std/src/lib.rs index f19de6836d..6969f0cf1c 100644 --- a/substrate/wasm-runtime/std/src/lib.rs +++ b/substrate/wasm-runtime/std/src/lib.rs @@ -154,14 +154,14 @@ macro_rules! impl_stubs { #[no_mangle] pub fn $name(input_data: *mut u8, input_len: usize) -> u64 { let input = if input_len == 0 { - $crate::vec::Vec::new() + &[0u8; 0] } else { unsafe { - $crate::vec::Vec::from_raw_parts(input_data, input_len, input_len) + $crate::slice::from_raw_parts(input_data, input_len) } }; - let output = super::$name(&input[..]); + let output = super::$name(input); output.as_ptr() as u64 + ((output.len() as u64) << 32) } )* diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm index 84d8006b5c7b0d48ff65e134274f8965f965347c..cd507221413e44b6db333d0616a95c4c1667c504 100644 GIT binary patch delta 8825 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 KfUo}K`TqkpXTjG1 delta 8811 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 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm index 2141ab632f4a0d606c7fa27b6c39c9ad53f91ec8..b893a62a1bb975c3e9cfdaf0554b2f8f04dfef7d 100644 GIT binary patch delta 8872 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 delta 8772 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 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm index 6005dbbca5a96f2ab601b89eb12eead782c3a7c6..63e7666aadfbfdef2c4286d3397788e339381d7b 100644 GIT binary patch delta 2632 zcmcJRNo-R`7=UNyJ;%?PI2p1!h9<ww(&sFW1H^;?jR!%A3R1aL94b%=gb)K^Nm^Q| zs?*ACk&2Mp37k-6sp_EzBvW%Km5M9*kV93aDhH%eDF+U8lYBsGdV&7)Mvhadhg|T% z-}{&OXa41ly)^mZWML<x9~4K}5M!mVx@c!L{<g0niXZ!8T3h_u-%K0wO)@6uge)*w zP>W6^IM*g4a<NU`pt90leCj-P?7S@tpEW;iS+J9A7y=NGZaT@vkOj4_WhcF(4z?T< zWnYpdP=`+25s%b2Ed%UHUGevpAE~(MH%9c)#<E&y8*r8#(Mh<>s%LGto9^=@I|TKz zj2x5m>R$UlY&odzb_{Dg>G*_Ig6jRyu*SEc?Q}_1Lgntf1q=crgki2&B8*r@8JMS8 zX6on8{Vk6%Vh9Kj>EN+l<dW(QchRfrmGFK#uX5oKEfv2CZ>2P=9<EP!%m<T90Fx}q z8ZbNpP|B*K8+zHppnA6cK<NKn%8lySh8}vq*!se8N*}1Vy8duWVSOw@_^*^%8Ty_i zlDN#4;!G4PWwR8}Ad%ReE8X20TaqLra)C$-Y+*$R*e)XxDnWALmp^Dd0V*81NMu0x zSxWka9cBB2=qa(rHrV>STEa*Uq5(a+z#d{w#HXX#5e%(^GQG84NCe}+Zh>#_AbgaK z_)u?YJwv_Jkpz~_249oT!X|qucZi&$I<3>{GW6=v`T}-kzO)!ymEaON6SY=n7{SaV zl!JvwBcQR1Y%<aoBlQ^cX^fD#!GJ-+V9;Qz!8U{K8krF?WW=Pw4ufHXodzQYy9{<4 z>@j%BU{seFA0aIWqD0a%l#Ze%MuvA_X^l#xqxcvjiK;4-#`%get#dt{eu5pknz$Zl zj1l81(m+-OCk?DB-~yIHAM7e%SH0%oF_LT_SU{6rB<$*#IRSnHcGhxPDoSsGl^J4V zdvyc#Ordt4?jbcjwB!=;nrM4Xd@h~B`meQB&!JQGkXd`Ho=c~2|FyPi?Vb9IGP>%W zN}P$}+g-afs;?BoS1LpForUjIt45Nv8!2qCL1Tn;8FYglafWZUz{?UR9Y+`Ekc6U^ zo>8Vn^Q5&xYw-&7R5+ZXI-D3F$u^+@hZA1bq4oW$<KdUU;bblYJ)HPE<a)Ddv6NPB zS~Z(YCcM$KywSX?UfZmSe{Q}<Pb@Po3Y3s$Ldd91$T}p!Yo3P|QQNB}X0)%O+~!&H zR&C8TT;qD$g2kK9PK}>9e`#Xi)VbM#bLUUSFU=6Ss2be_ol~Q3dr#ixzSraN_)#JY zHV+kWG2VA1?<1rgDUi4e9$-Ob+>3ke__)ZSk3QTjhme40EBiQHK+i^$=8)(>a!7%! zMR=t8V>eDcsjEe}jS<idqi6j*1o)`aJB-vx*V4P`=Wg|6B@Dg=tra9L_X5-*YWtM^ z{EkY*K2>*nwxpJw+IHWqY?lkvDl;>CX{9oS0O#ZH%uc}6^vQ|00e_$r^!9G71h@mP zHq4-IuAbM$;QT3ggUDPxr-*#LYH|nIV!cYaZ9|oM-Z(xnIW-Nt_rS#TNpNuy=e8Dc z3FjgPmrqYj!_3*K6I0WZI#6Ey*1NvH#5s${3H}@4V#%uvAtfX>oZ#;_=T1uJsz36v z8tjX8Ty5Y2P^Sxa-Kv%|uP*krca+d}7;S*I3rO8G-Tlw|HgByo@Mai)a~5V#SF@ec z$z_9F2tOfu8$d?AHS<9}rUqkUqeMPLhYDI-(Xei1!%C31R!2=|HL+6CTqCcmRx_{O z?SC;|Zsg(uhSu|yLk7Jq?xVIEx1$!fQT@~(Zp}6Epm$oV<_sL4#e?S6v;HG=u6QJ# zq_j}HHgJgINdJ;JKo`}<!J7>K#eF|`j>3aZ9;!5$$pYN!zmrwz^ct5B>&DTNy1wn; Ezgw8o%>V!Z delta 2828 zcmbuBO>9(E6oBu&@4fly?X<W5!+`CXvCtU`?Lg^JT994@X@mq_X`+y}bSNE4i|rt~ zamJ)5#)J&s>Z*$_y1)dI!EvFOz$|J)qJc^5f`ultU_q2c7bIdris!!PbZXLtv9sv+ z&d)vf+;h&meV0dzquG6o{+8=y-HfFT^`1GS@uztek^9t&Xl?ErcP*{VR?CRY2$^Lv zuL_=^FVi4{ve+QMqB7l-Tk))T%&aN%U(~MDJv3vi2fW~w;Y5rLAoHrGZXaD#$Ldar zB`e0Fs6(ech^OlNx=uFZ&i!6@pNbo9$A~`KxTNkibb79M#U{e#ta{OKtNIa-vExu7 zmyiQ;LEUZqi(RQwx0`x2o;H2X(pBnXe~-ow{ylVAE&CT+t{cF>EBqKHV~7AEZD5AX z*5HwU*>t4t8AkL20U|w^b{M&=+5^pWPQ4yDLKjpf;HQP$*MZ%X&Z=KGCz=*~F(!aX z7Gsqd9swxLs*_vV*%P07vH7TfeV3&wb!y9Y`Y2cb(h#MO)%(qVv@Hg7T7>Xr%B&Ro zND@iH%#`9>$Q5HI>j&y1lB&;IT2d}aVvNXpL>k}{Mv#Fk%t+9XAh~eMpS7NWAw04` zq*u6EzjO;TWFGMma7iq&2`<3;YY8KH5S8fB46bhG3A%MOGiW(M_0EP~$OPlyJ_Mfx z-*kg{Gw4Bsr46Pwc)&dq#EpPz6+xBM(FIo01b4MQm>_G-hbZ?DnWp;Gqv~yFr&L{r zzSMUHGuIryNX~_D7*@|8#Igh_2MZG?pwUNK9ch~*ZFjIkqnC6z=yVWuu*<=22VD;K z*hrCXM~pex>!8QMJ_o%H`W)<caKOPU4h{kVijR;G1d%5R=}&|hSP{~*7YpyGL?UEp zRdiLA!r=><S{Jr;`U&>xQsa7H5k?$WkpN>=@Fc)23AljuqYw5Ru;)y-1Jj7H!(izV z)se9015O6ognhTV*?{h>3sP2?^@rF^yO;QUxZHYh%>-R*TZkRDWRch{cG)f7c=J*^ zy*~0kySMS?rR=F$)4d9(Q2(ua8*g4}L*3g@^U{p5)S6c>dM;$F^X3`)%@cs=BlQ|F z(&$J52U|3HNwb3%`$aJDCJ<iKKmu!oqf7iDQ%|y?MdwLtMM|py3|ogYEJ`zs5n`+r z4fZvwx5X=3$HPAYN7(3QVLieo7-0r_f-Rg?d~RKxU<=Hdpna39xuXmjwFlU=2l$R! zX;r4azjD{M-leIu!9|`DQcDOqXcAI`B=|3c`-`Y;M?o-0djjPK+j@P?nl4-uwzYYK z*N%@3pPrnGcb++)>^wg?(lIqnWYOU5r-#PJ<0CM5;zDw4a-z5Q;>4w?p$p;2pnA|& ze>h|En$pTi+rwU%HM#XpM@Pp=BJ(Eq=W!>zWl7c|q!9^7ObN4nX!3FOAToZ4$VH2b zd34mrx#=OqYdb7i9Mb4sg;EBI4rCrFkmWE>EuK;LBiG_Y&bZ5AZebYo#eHVo+#kh9 zU6nzku2s1zH{3j2%CUeuY}0Gd3zrjtbRo-|EvcU(xBIVn%lq6}-DloguH<xbYPFJi zFXzJ_CgU(RF%tg(h%Bfdx3|BXuHYUBYr{0^G8Nnvfypy4NaTD4r-*EY`nIj}c(G#L zGN(DO8jg>SO~C#G5T6)<Fb3h=)FOu9Ttwi~+4uxZkB^-mn;6xBv+8R5=4gR)*3m)m zONEPNJfZ#-kT@^|zb!cTyrB=RfASgUt=Oa1*NB{}<RXd&UA`}kQgO4D>t<I#=RtG^ zbWS66V{xX`t2?&tPWyN*3|~w_@@%OlW4Z*hJ}$uRR6L3d*=rVjd;l{T2oU)M9S9og z(NMFR0e(+C-{JSoS8-RVz*!aC+4k;I6&GoA*Hbr-^x5$qp|%vHsT`!5H|j!_5}Hm9 zO(mycD2aK^S9718FIM><RaPzRe2Zps&v(Ws&F8v0k5iga>F7~fRQIBD48J_j>^e{3 e@h0xq`|8n)BL6*l>40vqKO0!Lgo~=T>)79G8TeoT diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm index 45e9c3bf2327d92d207a100b1838c1f97ef1fb4e..c1b257f3a313526e610ecdd3e0fb6fef413f1b6e 100644 GIT binary patch delta 2627 zcmcJRO>9#~5XX1-Jtwv|PL_N+CM07wq%S0~6Ch4Vpkyg2sR|{heyD0yLIR1&2aq7O zDy^+5sw#ny+XYTkvQ$;-h04gBdT4#H)JUzWsLBDgAmzXTsVcQp4&j12`?ikLTQ2zE z-_Cz`XLe`iJ^R7*r_<RRjDDTF$=+ZrA5xF)WsN1zHAK#?=+tU1=B=ewnHt$CQ$l8$ z%&HT<a3Iwn!*aDj-lVeFnES~0%xh<Cocp-;S>1{qXM^AapL7y&HipcqYjp?cUA0p8 zo+x<YtQR$0v>)+M#p`42Nk#5#{jXHqsx*_hMo$*hXk*N~;T3I!%Vl-B@lMSekF(?8 zmj&dQysi#5J!KmKH4q%sxDdR;iUIWuEyRUjgF4aNM%UF`bD=F`0Rx|CMOU9&0uUQ$ z19O!Prp7~~b&t?%5C{<I#iKjOb@gqim0ndpg+}Rh71$Z1`CP}&y_7Diw_6e@o!r%c z<KJ7l*!_UI+;YrFtWd4~XxT&8a$oE^Md>~DPwSsfKBU7E!XHp(CFv)UNa8SCigOXn zhRsHR28hHGc%Ut5OA=>9t`KQ~EvzsB+hHV3B}gv(@)xZWpn}U)B7MToMr5V1BWyH) zD<$U91{)Z<Knp#25mmUN9qfMQ4STdVJB+TiQ>H`fjYKdG>^69g^ucG#VGrt-)*0$j zdlHxy8$31o7B)FTxtGWk)z_L<PoPWp4}^!4-&l-ox!^iE7qPb9FpM`3Qw|m$jey25 zX*X7fvGy2rYYdU7LCm1npwD2h!9Iii8p$EjZ_K#CfWe@_0fQlfVS|GPhYVgaIIL5Q zLr4gM$diN&CL*YGlEDE?t&v0`g2PVITauCq?4JnJn&WDE1OqyoxF2XIBW9^c0NFIW z31B4yH?R?0gH;8rs#_d9Mw}f53uxT+gjF3gC%|vO%32N^iO}0%CHvXf5nVvtQ>Y%* zHKeA7mRu)p5pB1K&!tkB|LvCQIaDeD$?ccwxl{_{Z?{z2uhd_Z(JjwZ@3{y*-Q|}? z>5*diNF|8?<S?n%h?7QRg$!CWhDfVH8|W5i_+*PJ1n7idACh3i(ml$wX+~NVS_OQO zY6+WDl$sMA#92E|U~|GN+O>XvYJd18usNB-KsP7rXO7#O78}uG`<C8hve#`*%Wci? z)o;61Zl>c$dU}I#k)?#x5<(8!gzP{Pe2w$qDym)DVn#iQc7r>cvC4b);U33Tvlg$N zotZejaB(VjW^O4qw=fyKxJcxxy5jV*l&${mZs^I_-1AN}8hw|@tj&X2+>I|hlJOAI zh!jW+gC|(A`K-Fr-L8J#Gxjo(cRgIBaj`z;Z7(4{cTvH^;XH1sMk|HH1tg6W$g-=4 z9-gNE`I?;}@<~P6*B$hQ8!+H<B@Y4)^_9nwIuYe7->T$J>9BbW(}A-^ByM*dR3OR` z3zhtCDdLwS8{TrfA2#EqedTm5E?wMASJub*#D_~$Ff%_n^#S0ominrz>xH6^d%@8Y zi>RgiyrL5p&cORbrv02EGJbW{iLq6`&U0JQ&#Nb<&d$uk!9y@LKM4+Q;@s9IZc*di z4X<W6Z-kjeSh%#LT}>=pnx90=b(-g#MWY1&3~;gTCWw$c5_^H*PdDe@5q)L-k&o1O z-JMNWtGEEvblz@QrL1Pu<L<_$JkE{d9N^q}q^_cFjGaBZW5p_73ln&RrRmb0@l05c z02iW?5FG}P5qHmZwa|0o(0!aM;zT`aJ2qn#1H8V}fQz#;r>8b^ny%&*rF3T0)1DWj zg=#L&qgUN@X=K3lzJ_YaZ&TTCwR$}os!!MOfO}9(=OUb1!ZT*n<>;F<m0OF(Db411 z?{P{~>aD(GbX8^gZZZ4=_tM@u3iq0Muvle!3oz9Gd#l*&RxT6Lm7{r8yZ^O+0Y2#2 AdjJ3c delta 2719 zcmbuBPiWLf6vt=g_h)xA+0B^0YmCYJZDaf;vAY{Jn`pFV#9*L`_R>=N2a_0+tR`Zz zr4?;=DWM1jNtx7>loUL8P*~YROAmGnfqEz<hZLlx5U2;CQc~){9vb@Q_j7ks=%F-w z*w4&+GjHa-@B96BKb-t|GXE)~8-*L}RmO6L`pulz$XM4A1=H@-)<Pm!ORMuWvQsVy znP;-7PKKQDLW6YVT7$enWv;1kCA1MV^CtS<uidD7Xr@>{gdil{bczili|Tsa0lKUn z)V(cMtrSb54HxZ4JXNXs1e*^OChEVZ;!ePK;u`H-RYQ%5;I)uwBU~=3tBv<+9`O`A z0abDpIV^9fLrs6OYZ28K?bo;z{g~w<Y6EA8OVI{(a(f$HSJT^<+in}cAS7Bb)Pf-Z zku&g?%(GzLr<;fBo?+A|5Fj#$S9g)?>UMK0y{W!!9-_BYct@136gqb7rF2of-jYVs zshtft{;{Q-JqfF;EysNmTaBonTDs_?!Y4aND1EH{X#I8fa<e{`5WY^Cm1Q4DB8kgP zDbC026f@Z%&@hoy+0d4?B}p+N9}sDPEewZ&?K0vR5+oN@@;hy3U<fW(hzyA;HYfwa zjG04W0=C35nqULgSkEw05K)aQ+QIH+K_{T2nU3WL)h8QzBNL26;3$0Lyb=KOt`kIu zr5&br1R*f*1oSPniJ(d9=mINcLZC(`Cdg*@QObiv=BUnkLj3^Ulq%*7WWO|+xhefM zaz2KFm-Bb9EDq&h;l&AP43Ktz*5S{(eC*LUNa8*cK9W9qeC+kH&&PfbS<>rIQ$G59 z^!qsA<DicLABTJ#_VJRBBS3)S5YmDmiX<(g=@<j6ll1pt;eC@x#|&*smQ7h~u9&H9 zu4mID=+mXf{lGdI@t2A;80ASY4Q6SA8`vPOLCpa*XIc)tMv5H+3s}mFgqjcgH_$HB z-Rfn-T3H*imdgfX?5?LJj*nHO2YcSJH%o{LTXKzf65F1{TNf{jAyLx*sovJb%X(e2 zNxiUNsQ;$k*2T+iNxdzJmt%}&H$8gE^D*OJo;*W8c>)jvq+TOM8vR+bj~0!Cq}4~8 z_aGSfCJ@zVfi%_#TbD#*rtV}zPyLa$imWyR7@iG#Sd@AgBcxb6I<SY)uism)7Z1M# zwy@F5T;0MZ7%l_d!4~!^j@!!}Y=JrNcyE$T?<hkiy#_YD2EMPZ>{6zFe-$DfU(>Oi z!9|f0QcDOqViK|qN$@9vN7vBWjT6Cq>nWT!c;4Ha_Uywwu4gS8y!OJ>=-9>C@x;05 zOk(=t+4$@nk!vdHCh3A2aT~kxCb!;*$K!7iSu}aHh@0`nN%9sUjYvS^DR_a0>T~zf z;bn`9C0wH~cQ;5#$n&jQ9CElag0lrAE+9)tfviM$s!ny@7@H4NBHY6WxD2B&26!}y zL!I6kq)xh$-kkt<OE+7=;2nAouEOm^AZ=vjoK-d4_0{0DQ01Ka<#U!om6FV5X3Hfh zhBzO+oEe9ynX}{X0g)@}Xm|Guxhft6S3Bm=wot|GPPlju&Jej&#VI0RrFz^1T~o#G z#@-y~k<syqsTnwQ7{+JLf{S}NH}w>Ea4tIG-O2G8n7c4FHZ?P$<Kz|Jv!i!~a~6*i z{1?H+Iwqt)D@YWY;BP+X!P7cN{gKZ&Z}%iozq?NKW;GW{^yz|qYLv>EuU6l5H#DuF z^9(uxojIgdP0L^0vukfI%xhuvoeX3qOIc6pBp1V6K)|nQ5*hRM+zRtyb)swd2$4^4 z0YOJSI<}Qh%td&8sn>LR<K@yWMYvt6YF>Tz;_f$BBV6P#f^M)SWY|065n4-en<{Z@ zc%v8ZxiWK^k=e`~jAZbtOEo;~rGT}5Zptes{u*5<T#lzGEf(^L6BHZ$ujFx*XsG8V n!#{_=^h{HDyq!n&xw_wy$ba@*u34+f^3A%6_&@QBeJ}qF`nl9_ From baa1d76323aedc817fc5bd5a514f0d2aa3e791b8 Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Sun, 28 Jan 2018 20:40:33 +0100 Subject: [PATCH 107/112] Name more consistently with std. --- .../polkadot/src/runtime/staking.rs | 20 +++++++++--------- .../polkadot/src/runtime/system.rs | 4 ++-- .../polkadot/src/runtime/timestamp.rs | 2 +- .../polkadot/src/support/storage.rs | 6 +++--- .../release/runtime_polkadot.compact.wasm | Bin 64236 -> 64085 bytes .../release/runtime_polkadot.wasm | Bin 64285 -> 64134 bytes 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index 9ddd78b788..02644fc940 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -31,12 +31,12 @@ pub type Bondage = u64; /// The length of the bonding duration in eras. pub fn bonding_duration() -> BlockNumber { - storage::get_default(BONDING_DURATION) + storage::get_or_default(BONDING_DURATION) } /// The length of a staking era in sessions. pub fn validator_count() -> usize { - storage::get_default::<u32>(VALIDATOR_COUNT) as usize + storage::get_or_default::<u32>(VALIDATOR_COUNT) as usize } /// The length of a staking era in blocks. @@ -46,27 +46,27 @@ pub fn era_length() -> BlockNumber { /// The length of a staking era in sessions. pub fn sessions_per_era() -> BlockNumber { - storage::get_default(SESSIONS_PER_ERA) + storage::get_or_default(SESSIONS_PER_ERA) } /// The current era index. pub fn current_era() -> BlockNumber { - storage::get_default(CURRENT_ERA) + storage::get_or_default(CURRENT_ERA) } /// The block number at which the era length last changed. pub fn last_era_length_change() -> BlockNumber { - storage::get_default(LAST_ERA_LENGTH_CHANGE) + storage::get_or_default(LAST_ERA_LENGTH_CHANGE) } /// The balance of a given account. pub fn balance(who: &AccountID) -> Balance { - storage::get_default(&who.to_keyed_vec(BALANCE_OF)) + storage::get_or_default(&who.to_keyed_vec(BALANCE_OF)) } /// The liquidity-state of a given account. pub fn bondage(who: &AccountID) -> Bondage { - storage::get_default(&who.to_keyed_vec(BONDAGE_OF)) + storage::get_or_default(&who.to_keyed_vec(BONDAGE_OF)) } // Each identity's stake may be in one of three bondage states, given by an integer: @@ -81,10 +81,10 @@ pub mod public { /// Transfer some unlocked staking balance to another staker. pub fn transfer(transactor: &AccountID, dest: &AccountID, value: Balance) { let from_key = transactor.to_keyed_vec(BALANCE_OF); - let from_balance = storage::get_default::<Balance>(&from_key); + let from_balance = storage::get_or_default::<Balance>(&from_key); assert!(from_balance >= value); let to_key = dest.to_keyed_vec(BALANCE_OF); - let to_balance: Balance = storage::get_default(&to_key); + let to_balance: Balance = storage::get_or_default(&to_key); assert!(bondage(transactor) <= bondage(dest)); assert!(to_balance + value > to_balance); // no overflow storage::put(&from_key, &(from_balance - value)); @@ -176,7 +176,7 @@ fn new_era() { storage::put(CURRENT_ERA, &(current_era() + 1)); // Enact era length change. - let next_spe: u64 = storage::get_default(NEXT_SESSIONS_PER_ERA); + let next_spe: u64 = storage::get_or_default(NEXT_SESSIONS_PER_ERA); if next_spe > 0 && next_spe != sessions_per_era() { storage::put(SESSIONS_PER_ERA, &next_spe); storage::put(LAST_ERA_LENGTH_CHANGE, &system::block_number()); diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 35a425f53f..2dcd41c503 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -31,7 +31,7 @@ pub fn block_number() -> BlockNumber { /// Get the block hash of a given block (uses storage). pub fn block_hash(number: BlockNumber) -> Hash { - storage::get_default(&number.to_keyed_vec(BLOCK_HASH_AT)) + storage::get_or_default(&number.to_keyed_vec(BLOCK_HASH_AT)) } pub mod privileged { @@ -102,7 +102,7 @@ pub mod internal { // check nonce let nonce_key = tx.signed.to_keyed_vec(b"sys:non:"); - let expected_nonce: TxOrder = storage::get_default(&nonce_key); + let expected_nonce: TxOrder = storage::get_or_default(&nonce_key); assert!(tx.nonce == expected_nonce, "All transactions should have the correct nonce"); // increment nonce in storage diff --git a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs index e6ae82a97d..01df210c5f 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs @@ -23,7 +23,7 @@ pub type Timestamp = u64; /// Get the current time. pub fn get() -> Timestamp { - storage::get_default(CURRENT_TIMESTAMP) + storage::get_or_default(CURRENT_TIMESTAMP) } pub mod public { diff --git a/substrate/wasm-runtime/polkadot/src/support/storage.rs b/substrate/wasm-runtime/polkadot/src/support/storage.rs index 7dcbcaa5fd..8c9afa6279 100644 --- a/substrate/wasm-runtime/polkadot/src/support/storage.rs +++ b/substrate/wasm-runtime/polkadot/src/support/storage.rs @@ -31,7 +31,7 @@ pub fn get<T: Slicable + Sized>(key: &[u8]) -> Option<T> { /// Return the value of the item in storage under `key`, or the type's default if there is no /// explicit entry. -pub fn get_default<T: Slicable + Sized + Default>(key: &[u8]) -> T { +pub fn get_or_default<T: Slicable + Sized + Default>(key: &[u8]) -> T { get(key).unwrap_or_else(Default::default) } @@ -129,7 +129,7 @@ pub trait StorageVec { } fn item(index: u32) -> Self::Item { - get_default(&index.to_keyed_vec(Self::PREFIX)) + get_or_default(&index.to_keyed_vec(Self::PREFIX)) } fn set_count(count: u32) { @@ -138,7 +138,7 @@ pub trait StorageVec { } fn count() -> u32 { - get_default(&b"len".to_keyed_vec(Self::PREFIX)) + get_or_default(&b"len".to_keyed_vec(Self::PREFIX)) } } diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm index cd507221413e44b6db333d0616a95c4c1667c504..c6ba80a0162be66bf0ebda010e8e4796f9a1da21 100644 GIT binary patch delta 14431 zcmb_j3y>T~d7hbl+}=L!Mz@dKyOXS*J;~nF%a$#j#K{KD85=9IVq;!OzyZg|hSkXe z%Q&Vm9@z*ui10%r&_U#2Dx@$KyK=CGQV|u17=pmYm{%e5iXf^)DIhUmmoF(7$@l%; zGqZaq%OwKB+tYt{|NZy>{(I(r`E2U@&!lE=u`@5(n9k+GciHC^a>cyU=Q#cSt`k0F zuURyZ-Fe;A)UNBTTKa~Yw{N!w!(Z5I`d_|eXt7rxR_iXxf8xujjbYPyo4vOEQRn`w zG#A^>0k8do)J2)_!T#&*3&Wzj)Gmjs+?~1etb%_?xy!?Ut4?6RtL?_`hihu6Jgjm} zC+%gFt!zKnYNVQur5yLd@QK=DEdE7pzdh8xWAL}OeKNdx=)L%z8@k6n*`6L=;h@uA z{7!o)T)pIe`<(ExB`fW7+RrUnpSG8Vs~dlBH^ZkItL$bwJ9@;nN7|1ryC-EY3t!c| z-(J@Kb+gaOEdyC6Gw$+s&&uzm&KYITc9*01o~?R81tHO6_}^=GWA)DSKY-uo&i|Y} z5I%eXA>P^#%I_P(+=Xj^dBcU**^7Wg6;<BF!Bt+R-E-TYzUZzz2wwHl%hP*C{hn~` z%WC1imu>^g!XLf#`{dkbU-oDkC%g6K<+QVBH2n4DuM2;E#ZT-F?W0?E*cXtjoO0cB zJKD7AM{P7dJ&H5Ee(Qgx?D6ort?y`m>8e*}uLrBw`ZIP5zq3xuZ@L1&qXtKS6Z2<G z%M5^{8F~r88n7lo7~cBYOLCLwTjS1b=w1Ex_Nv$2owL`5|M<q=@SyHne%`+Cx_646 z6t5p<8#dqkb3IfE)%IVJ5B)ckWyZ1_uSnUKws*E_wtZ>1cgJ{{JfIp`1-D@y!*A|b z4_!)4{TF_JJ4L;^apw*8qV^Lz$I|xl_T1ZVaL~N*mRIGRN4)kUx8GsgtJ@dd@haOM z3$K0eu;Z?1|7|d1+vWDfciv`W`RDG!@^JBc4h*hvSF6HhrMgPFPO)B4i~OT@%e^4{ z+IyA+B<1L^D2we|l(U~!7Nw&s%%_yns$W`7v9AocY1$LZW%ZnH?mbs}(WIQ26t%~( z3c`j$s{YGLmV!z-1^>7vAcKvmX#JW1e-7aAJ$s+B$J*Dvcad$c2zR~jA#!%f`>#!b z8Snbw7wiEZ;K32u^td#KL;FK(!`t?4f!VFSd%e9poZGi2e*T9K-5EdMc=v;NcJJ}} zDTQZ5Alke)-?JAZU%kg0i{xV!EUQqkltsI?-JybuM)v?pyCY%$y_<sSuyXyQP&C^= zYEd!KOSLpChU`fTB-KhFG6(P&G7ar@{XGlj03OfLm^<gZW+CchmLTdtt(O5FBU-pB z*SV;D&VB6^%=bG7u5rMX<p<Bl?`sZj#qTE$j^p>ZKyovLZ=5-|59hY@$^CV1Ih>kV zb8UIJ;0r9>8h6tD&^dZXYS);`7_G}l9|HnV88abLrAXh#v`T%(c2a?ThqKw;96mSm zV0h=T?L%67v%~{6%Zf5(i6;EtW7jx`yzosEQ{l%y`senM@OK|wnSR`JmxZf8HVI>S z+sAg{_r%Bc%k$1u4xam8|N4OGrO-Qd=+o%!zn}A*zxjIbddJ50zU5Q=zPqF0;9$;X zWtS}f<fsR@XBU(MPS~!m9H>phepor{9XOWv?e$Wa3SgQ>VABS`58owoRH|^uw(TH7 zeIj)_+*cF1KL_b@{d!_sZ9QcBJ(mNa<3A1kkzq`s9y<OhXr;g-h=xh8;kc{9*B)y+ z%dPN>U*A9YAAjc5f>eCC*`6JZ3MdQj+cg+C{=Zw>WRIDk)hPR^Z6#aTP3tX<MgA|X zR%1{(+Zs5QqXzw@+e#@_@sB`_>zF%fZGiFUzT0ZlI{OHjIo&VAc<QY&OD5OQaidNS zogf$WDx7`<_?0b_`RLDPWvjd@k2z*Hg0Nd%)w)2~u&QzqNL9vwYlAbJ1(L(C7SgNo z(XfC>vI^>5Fp{mR5r|l3vm2blX_Ar=EWMqi00b-poumN7bfKG+!)cI`0TPf=P`wd; zEDjn)H4yi)vZPW`SGLcP$GxgxfCH*%o>HpRIT75!4*3{)Jw{tyh!Jct+z5cZrXnW1 z(Ann@R6%;D7zmmt27(rffoGp{qW$J?7j&Ls&JkW0Vip%;&XyK3l&W`J2#dL+0d6a1 zk_N#2&F9r|>hpQqN<kX!*I)t2^u{dZ4FRdq@4ilb#!>q_`#7ho`+X7|A}#JmZ)4PP z(YYY%bm@0ftGYiMXaz5;zK9W`^P-#mT_Eg;JSqa6PQg1>lR7_7H3<TeZq*DHD0rem zTIWT`iHgz;M95ug+O6P;ondh?)~*T{mb%R=m=y)j$0Dr9va2o-8WcP+;uqFhV1$Av z+(_)R`|Lb=ppBcc8Va6?&8OlM1oE@79cd7b(9>;DJo}!sDyWPRPElpeQ%Uu73TzK% zQfue5&@(tR>@R`Ic9DJSX|mmX<(;Efn-MP@Z>j-M{b+9ufa-UVFb8)wlY-9E>t|J8 zSpK_OVEZSmNKL80$KxI~_{q4}rNUQ;3MYzNQ<1)&UQJ(E9)WP6!`UV(_<~-{C>*Mo znCX!do2Owfu3!OV!riqC{X=UQ6)e%KM4b{X3S@WjlUaE1NR8^TD60!)cvhwWRg&Np z`&A8qvPcYN4A2m0OIHYG@SDq^z_|UYQV$v?1Z7d3oElW+Eu~(hMR_bnVRaNiax%Rk zbvW&(y#Z%)_dhI7Bi{OH<{Gwt%4&Ix??=-uuNrUx{wt?8BNhQ`hRu#fj>$+CnP0ip z=xtgSG1S?~srnYslT)>=r5sYF3XHw(x~jsgtjrV)(oCyiRUYw%F%Alw&XM#hIKa^F zp0BEyO3IrM&sE+)K@F(9Uz}o$8{UAm2zBFNOI0TNHsI{$yfSy)QnHJwLP4+gNI{;P z5`kA!x$yE?FR1yq;JhUi86=R~b4pH9LvNsn9hst}z2PD<Kl7*&HU=&$5vFsND8@CC zbO&xChhfG(JVpi}-nDMvIplI(Y0PniR&#pd?ZrIpKpL?hkCGy8%`xCke31zrB{K%M z6bCF)KZ9ILXGz+%^#_=!m97!TtSGWAGGo{v(siBb0V_Ql*U|5Fy3RT6)ZJKxGqI-j zBmst`z>1-=K`M6T#W=R~bw?Ch9DHHoxbkX|*|Qqkp4cYs;J8ynont|EeMnGL%~Ux# zsZO94Qk_6Kr0O{ZpW>JqWto9IT1J!_l(uQwW0rY16+NWIRx}z*l?88EPXcpHMqG~h z8*wS(ZcRo4%CBn(9HrK1=0+oAm|<<4;nJS9ZbY*r_l2~mU0O4`Mu53$Mv%?xfVN%u zMzxT<*Q8WbJDsw{2si@NbOu_XyGDST>d288wP2<`A4!F;Tv89+n-&KOHbeC;wrIY5 zx}b$0GHY=QrcUFn_^Vo~9Cw=0gi11D89ZV<K}8da@dPz6?vRO#;U}YcYG^}>5d>z1 zpGUIEWLW)dcH9BI{^Ka@5<~q8dQr5h_!qajQz8bebyx#u8|!ezKZ#yqsy{|ADhYre zSv0GiS7Q|n6~C1h7O+sPNa?6+APpIwRMVgG3TpUM9!d{*G8U`wzn1Yj8UYH<2!lo{ zy++07O$MnUa=0{>#DhBmT{sqTg)*ppHJms7J-e`#Eu|7n#@SlxQ#r<xe(Xp-LM{(L z@{_p@shJcbKxfcUCR$Yd^*UJ42jOwh&v|wfDhd)Rf=1qd*|rjHHvP>|Q@^<l8|M9k z@Pc^;kv?XF(9)*$R{vLsVG>31j3WK;^oSye9m2UP;>dbD!%8%SHy-37_g>dpZCM^w z9Z4`!s7J{JzsIXP!Ddy}r8<R86T>p_WF161Vd3IUmBog*!o%jw0P!ohF@jEAV*`-4 zH!>j_hJ^q?RhA7^)vGh6)Xj#(MQ_V|H6a!NT9#g+2?k-np{HP&C*m;3<Y_g59Tb)I zV(gTo)f`GOe3ohd?i$^~Bw+*)WI1TUk@9{dI+<YsBCxQvlYH4oPt?TN(1|%~3MA;+ znyRWW4D>*M>J!#FjI9SZ&55ewhnTJ~Hs=D`cOJnR!Zg8|bW6k~ZbW6?;xoelybRR@ z;T)wqKu9Jz$Vi~6{xoz(!Zw5Pq10u#@xXnKDwNX2j0EaKDQ}n>$hd98W@x+tffxl_ zd80?`m}e^RPjqp-$4TZG#nSM|+~C7tH%0BS;2F!RAkW74(B076R3ZiCW`QJO&%-Hb z@2Bi>=Qek915PSeV#<O=E_elZTK9u-iwG!x@!UCIwHmf@XSuOd-NVZdx;Sx#m}_gV zi6_`BFpgUY1lS3w9%RN$>W?*rl`()eq>!G$vN_#f)}oDbA^oM#8zu}mkU@#R0IEh! z#ME@^!hfbv;T5w>yAvqV0|Z*2bv{yRf;DZhf))sr2^NA{%4!T>4IiL6K0F!R?(g&5 zO(cKL#y)7Dw#5aR$W)y)b(o1qcF+j`pL$K7ja*IPgwr-Qur^uyq#d{JHvRpkJs|Cb z^%2t^gsOvMq5y6&kpVzs*1dMagf5yo6S!I=O^i;<C{ru~<ywo==(k9*!d-vLS6fPQ zQ-uNKc=aT#M7co~mmH29w3dVx<^c2W%Ix_UV^GB27$58;iqc#>|B7rd-bLpWSUZqx zCw2{n!Y6hjF$En0h=vAm+0m^-If;C-9|9yek!+J-KRwcVgcSLFgtN8~r*Ku*=BgfF zOo`V-sT8Nv0)XpTzyp@$P3IZAlqqHld_w~dQD99_Rs&u|Tu&u&J(wy=%%sJuzyqOP zfCi(iC{oRX0hS7<ntT&NEgN^F>bEx8&of81#_iupyUD(*hy6|VUTG(+_nG$nrkytJ z2Tc1x)Bcrd_nG!XroCI*V8Xh`0PZ#IeWu-S+R(HIO#5Nee#Eo~(UKp+2yK|;9Rjm* zGbrpNW<j7SD>lyQG?Ef5+LI2v5|RY^OdcHuG-+>0JxxPmYGMJ!h1!bwJ7+g)^pyFg zC61>|_m!v5i26v*@-T|H5BHge4~_c}a2|PR+%E<MAoGh5K;U@>Jn6Gwl`sMrVu_wp zLG)0#@h7p7cg;uCX?M=x0M&>67>7wW)IdiJTbR|zjiW3?N~iEZ$HKYOXu&2pW}SdB zZ25Sn!H|hZ)YUm`%$r=`V1_ol0q!?%2KC-#8}>$p67LPC(y{kGyHVGBE40BgX77mS z+Jlqr+L>chp4My%?C@9EeH|Ttjr_0h<_OejfMmx=gJXaMFub;k0T4mOM{2AA0gxb@ z#}z>Y0RTc^z8o)+Tz6yC&kKn>5(0b2F<*$q^Eu4eEi9vQ1qp9Ej)@uin6K_Q=F=S% z$}y3-$0W)zaorIE<e13jV}P9UL<c}l86d@vr^q>RD`x;kuyRA8iySP`J*@zUvaw1* ztl$V$iY$2qX2+@G>vaBxq#Im??u#N7r;xfAT7EFNh2hjM?rfwUo-E$ckh-BXfVu$_ zf-9L;xM|*1RFIAGpOQchsZAkA9`I@~-#XHCZLriloeD&TT&6bWv8hLU(MFw4v@7U^ zWl@s7JQ9YH(?GK#%hIAonnRE=E4)vVzFyEkr^Bpz4G++YRbdoXMeC9MDSD<Ta3Nqr zp7PJZfCy^zCUn4Jz-k*`P@pP6eFA+P13s3VxcK4j)LNvQb>yXz>7$1niO#(W=Z<Tp zIv4~b-k_>qhBB-U@2CdA3$F}@)xa>)q-p`Nl!*+C=JH(0!le`5u!60=jg<r5AUm}v zJb;b!d?eW^%;PV7WEnwAm?*xh%Tq-&Vul7Ho(`>o6?JIUGhJFG9L4CgZBzll4}xie zHTsh6UP-p-o4j6?lA@Et0v?cyKam7$E0KgMzY_bC`8AvYS-qAEbA3{XqY@V+gNR<E zEXXPN)j<>~;D_EADp>#-WH@*^Fz;GUA-6|>W|+mUtiiDCa28q(rs-!OgpR@)0xUV> zY!-0_8kxhEz%I9by@H?#%Zf@`u`L8-+8T7;{=5m)U&yLJBJ~jgOjutu?Uzh@)U;nV z?LV3JQPY0Kv|lytKb!VzraflbubcK8rhUw`k7rpZS`*ec4d4mWek%(O^L7Vpz=sgp z$mE3|)cY7Nzakh?IZPXKj&{JnA||k4lFZ{{oDs4PWay1Dy+Dd%xWMH4gH!0fqA7xk z?+i2Gu#|8$EuwvtKGSUyb2mD9FjqSJ(Lu?fM-HG<jXEDe2j9W42B#>jfRWTc2q<o@ z2`%Ass3;#dnK`Jz3+S$7Jg%$GoQd-&%9RUWe~+!zR}6vGC6w7KGpb2FN;`K~L2Vb* zo$feaLZZxIwqwp~PHN6*PS<%Z97`X_e;)S&@rfdDNdbwM#OrokB+ow`Uh<o|@yzFw z6oQoovLEClsGvs9l2X*338}yAB$YKqMAuo9L;WK;!|p~kJc;P<_iP<O$U+I|Y*s^R z1h4_Zf_JOoyC$t`N|w8_(8cMB5B-YN2HMr3TM-nR6+J?)I<zWMDgpVQ^iCszg#Ym= z<H&uMyze+{W8~^mpPVp0^}E%GK42^vD!z{Q)~4WePU!`FlK+rC2z`Pv62=5>4_lAy z!(1bD)T-EvgJcTTiZNKyVb-caqC&V!&{CVUZ=a;5Lp&zKPw4%<$?c*tAr4jD8K@KD zT!aH-eVv>;8%mC@5Dn0b>!Kt`NLfe;1etIuW|W^}B4&7H7=&A9afLSB+UL>9L&nni z0y=aP(m8?-orQG1hz`F(ihQ9~i7x?aJjbC<af52PG=RWakZWn5iTL@Xla20p?8HC< zX$;UB@(f`eUW^nOT8s@v9Q?gWp#L;m%g%vx&$#tG;ho*q_*4x3k*@|Nqy640|A6OS z%xnVJPI**y@x2puoL>ath)5$NAwiZMl8m5`WAq3qo<@Wk#DrCc@FLR{Bfl=`$*W!( z@ENRtUwEX&%L55sVPt$d)YR4yUe6Q4iaxq&(|5;izZ@~+F=k`No~(WiTlO=zAmNKX zsqqTTKcKuU@~O8TZ|I=1ULWV61s)$q^yn*~nx3OF$aZn*o&sLEJgEDRc<v>-qf<oY z@8EA1IbMOcbF>L_i#OQWhbj+5w|a!*7O$w;ikk*nPoM7f>&ETov!lDXNCx_OE|IS? zC`atTOlO{JEGNO$3Fh-%3a7;Cle;{8YsZ5SEfTR*^0r4n$io)Jms<JwQj1<<!Cl^9 za?|Apbk}kp7rp6BK6jACapq<|cf+S5IFV*5L0CJOY!}_-;W8weCD8%tn<zJ(7}CGw zy_NWXq<;xg@pG*Nr6?yZ_>lbk|D*$Jh-DFrAUK2S8{0)~#k+kd9jXH@83<qykNPyx zL3K>y)utYaU$@fq^r@n$Jk!%C5)Y@T|EyL;qzMxU>f$V}i8~kba+I|dUpORM(ZN@$ zNe5d|xOOg|#@_I)sICH0-Am0k3D0MVPSWc-E^|<?R#~=I;f3FXuppO_Fs<h^oR&cr z9=%fNN4Tc4n|BH5DV^<Vr-uGABnpysNL>e(;NZ}oi*?nlYOla6w>-?wf+LYCd%?Sb zKlp0_?V9$=cNp|h{8XJVFir|h&02FO!a5#R<AV1^;h)a-b-$Y6{Vmpatd8)S5<osk zVWQ6}6i!S^0kH3^-bM+bc)`P+0?`4DhozAPKH{~sh3X&If}$TixU#@!*}MjmuMmzR z{K~@^UU2Hqs`LE90287=2GJib>>H8`XMU}qr$t{cMBgFcD~14<5NZ9PgZmOZ?`_EE z`k$1ggy57kfMUzXZ42o^BiD(d{N~<aW|{tG$WNJ@8F6;wG<;kPV=zt}fd?OB1CPc# z-gJ&Jr+gf)OvA+#Pb_o!cQYNI{afLc-}vcLTn^+FzOC?^___zbZe<v+4wm>2f<pYU zNx0>)D_?ZZBadD6VsqM!$Co-I*et6Sa}&SW^6;2!)PBPgBY5>R449>|pr$c=I(phO z-`at{`UunCUW32=xaiwoX6M=Otj6!?ckiuZy`?w61yU#W$G-b+TxW5V(VAx!GQ4!x zthaps%G4-kE%E1^7Ji?^hZXV{H{gc=02Z$N;5h$A>bc{8g5Rs3s^Ry>r~U}PpM7fA zAlBzK4LppXk~JHDcv%Buiy^2%KiEB=;SuVO|L`wKXd3^>hKSISPC~=+A6+^$sj`Ue zS-*N!sa&iS)ChR%;I9QH!~H*cm{epb)%o&#?T;^t_@HI3`2dO&S%jbd@tqn0<U|CO zjxqlyiv#|J)u|QOz?MI@I=%v{2a`t)onFazPy(Gx=HfAe&aQ-g#S;uvE%x#SA8Yf; zkeQ|MO&iTl;g(*^)9=7Lvr?>VdL{pmz#R>L_mgXQgbK`Gj$m~h;l`gnYoFJ?_Fvjm zo<%=f2~E1>XY0#BZuj=x6SrPBHDUROyh0CqQ`>K{P_mlN)b$q1KHYiiO>ef4Y!zhD zO}E{GMMpgRoy;Oj{|~LhC;xFkPq>y0d?saC8G)Yg3X7)R`WM&lx_SHgH*eqlj;UML zth#x(<?m?}oCy%Uw^67o;CKmUzX|P9wEOX2R#rdI2zNYvN%};iuryS^sfHIkTU@<o zw9s?ou3IOrd)v*HKRsHgKY(Q`G5txj_`h|PZCO>ld^CLE<oV8%qv5wtR@=XM_J7j< E2Ry$4Bme*a delta 14603 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 IufLJ{e-+g{#Q*>R diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm index b893a62a1bb975c3e9cfdaf0554b2f8f04dfef7d..94c946efbf7601256477a9e9e6762c7d3516cc5c 100644 GIT binary patch delta 14528 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 delta 14682 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 Uk3p{)bmK?%jJEE3<z(jn0Ganl3jhEB From a4e7f17a19691405f1e430e163c8e80fe394b319 Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Sun, 28 Jan 2018 20:57:50 +0100 Subject: [PATCH 108/112] Keep naming consistent. --- .../polkadot/src/support/storage.rs | 2 +- .../release/runtime_polkadot.compact.wasm | Bin 64085 -> 64054 bytes .../release/runtime_polkadot.wasm | Bin 64134 -> 64103 bytes .../release/runtime_test.compact.wasm | Bin 13189 -> 13189 bytes .../release/runtime_test.wasm | Bin 13314 -> 13314 bytes 5 files changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/wasm-runtime/polkadot/src/support/storage.rs b/substrate/wasm-runtime/polkadot/src/support/storage.rs index 8c9afa6279..3ff8b1c75d 100644 --- a/substrate/wasm-runtime/polkadot/src/support/storage.rs +++ b/substrate/wasm-runtime/polkadot/src/support/storage.rs @@ -68,7 +68,7 @@ pub fn take<T: Slicable + Sized>(key: &[u8]) -> Option<T> { /// Remove `key` from storage, returning its value, or, if there was no explicit entry in storage, /// the default for its type. -pub fn take_default<T: Slicable + Sized + Default>(key: &[u8]) -> T { +pub fn take_or_default<T: Slicable + Sized + Default>(key: &[u8]) -> T { take(key).unwrap_or_else(Default::default) } diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm index c6ba80a0162be66bf0ebda010e8e4796f9a1da21..c65945f6213a7648c8f2af485fad014d2f5c2d0f 100644 GIT binary patch delta 9565 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 AzyJUM delta 9551 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 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm index 94c946efbf7601256477a9e9e6762c7d3516cc5c..250789a6eb36864dc8e784b2a20cd7dffa687a88 100644 GIT binary patch delta 9586 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 delta 9495 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 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm index 63e7666aadfbfdef2c4286d3397788e339381d7b..b7de494d797ad705fdd131f73372496980b4f089 100644 GIT binary patch delta 158 zcmZooZ%yBj&%!i8dU7F43yAv8(g&nAx3g+8f#^-_ZbFO~Hvg2&U}fAgIZ0j>q^48; z7l>+Ahy*Elps<t?#C@Q!X|kpACy<b?%1lPa37e0r7V(;Ik>ZvJ;ALPCWME(@0Mf!h r`V<ob11FGXaJ(SJEts5GkeHlVQmK$%mRgjSlV8r@_(5uNfw3q6Pf9T) delta 158 zcmZooZ%yBj&%$&-YH}e<3yAv8(g&nAx3g+8f#^-_ZbFO?Hvg2&U}ZcoIZ0j>q^48; z7l>+Ahy*Elps<t?#C@Q!X|kpACy<b?%1lPa1)Gnn7V(-Nkm8m|;ALPCWME)u0Mf!h r`V<ob11FGXaC{)eEts5GkeHlVQmK$%mRgjSlV8r@*dRT*z*rOjBQG+< diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm index c1b257f3a313526e610ecdd3e0fb6fef413f1b6e..450a7e7066596a0fbabb0702c9dad058cd5ead9c 100644 GIT binary patch delta 175 zcmZq5Xv)~|hJ|T@^yGIeEg-6dwGT*bW?|E00@3;$ZbFO~HkV0durh9$d|zG_q=rr5 z7l>j~j07o(Rb0vl;>Id&n!HW<6G&*4%1lPa37cKiig<mtNO4O9@G>w6GB7X{0BK<$ zeTs>JffGnGI9`zA7EDeoNKDQwsZ_`>OD#&v$uDPc{2;|GoRgW9n3I#AtY4H^9$%K4 ItXEVF0MgJkQUCw| delta 175 zcmZq5Xv)~|hK1>X)Z}+8Eg-6dwGT*bW?|E00@3;$ZbFO?HkV0dureN)d|zG_q=rr5 z7l>j~j07o(Rb0vl;>Id&n!HW<6G&*4%1lPa1)E*eig<kvNO4Of@G>w6GB7YS0BK<$ zeTs>JffGnGI6jc#7EDeoNKDQwsZ_`>OD#&v$uDPcY>?&_&dE$l%*n}5)-Osdk1tD2 I)+;Io0K!!^@&Et; From c245b38eaaeba5f5ebbfb306dec2906cd91a63c6 Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Sun, 28 Jan 2018 21:47:49 +0100 Subject: [PATCH 109/112] Move constants to top of files (even though they're private) --- .../polkadot/src/runtime/governance.rs | 8 ++--- .../polkadot/src/runtime/session.rs | 24 +++++++-------- .../polkadot/src/runtime/staking.rs | 30 +++++++++---------- .../polkadot/src/runtime/system.rs | 6 ++-- .../polkadot/src/runtime/timestamp.rs | 4 +-- 5 files changed, 36 insertions(+), 36 deletions(-) diff --git a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs index 1be0b8b03c..4f7f6d8688 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs @@ -31,6 +31,10 @@ use support::storage; use primitives::{AccountID, Hash, BlockNumber, Proposal}; use runtime::{staking, system, session}; +const APPROVALS_REQUIRED: &[u8] = b"gov:apr"; +const CURRENT_PROPOSAL: &[u8] = b"gov:pro"; +const APPROVAL_OF: &[u8] = b"gov:app:"; + /// The proportion of validators required for a propsal to be approved measured as the number out /// of 1000. pub fn approval_ppm_required() -> u32 { @@ -107,10 +111,6 @@ pub mod internal { } } -const APPROVALS_REQUIRED: &[u8] = b"gov:apr"; -const CURRENT_PROPOSAL: &[u8] = b"gov:pro"; -const APPROVAL_OF: &[u8] = b"gov:app:"; - #[cfg(test)] mod tests { use super::*; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs index 48cb6f42d4..0402816fdc 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -23,6 +23,18 @@ use support::{storage, StorageVec}; use primitives::{AccountID, SessionKey, BlockNumber}; use runtime::{system, staking, consensus}; +const SESSION_LENGTH: &[u8] = b"ses:len"; +const CURRENT_INDEX: &[u8] = b"ses:ind"; +const LAST_LENGTH_CHANGE: &[u8] = b"ses:llc"; +const NEXT_KEY_FOR: &[u8] = b"ses:nxt:"; +const NEXT_SESSION_LENGTH: &[u8] = b"ses:nln"; + +struct ValidatorStorageVec {} +impl StorageVec for ValidatorStorageVec { + type Item = AccountID; + const PREFIX: &'static[u8] = b"ses:val:"; +} + /// Get the current set of authorities. These are the session keys. pub fn validators() -> Vec<AccountID> { ValidatorStorageVec::items() @@ -93,18 +105,6 @@ pub mod internal { } } -const SESSION_LENGTH: &[u8] = b"ses:len"; -const CURRENT_INDEX: &[u8] = b"ses:ind"; -const LAST_LENGTH_CHANGE: &[u8] = b"ses:llc"; -const NEXT_KEY_FOR: &[u8] = b"ses:nxt:"; -const NEXT_SESSION_LENGTH: &[u8] = b"ses:nln"; - -struct ValidatorStorageVec {} -impl StorageVec for ValidatorStorageVec { - type Item = AccountID; - const PREFIX: &'static[u8] = b"ses:val:"; -} - /// Move onto next session: register the new authority set. fn rotate_session() { // Increment current session index. diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index 02644fc940..d9bb971647 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -29,6 +29,21 @@ pub type Balance = u64; /// The amount of bonding period left in an account. Measured in eras. pub type Bondage = u64; +struct IntentionStorageVec {} +impl StorageVec for IntentionStorageVec { + type Item = AccountID; + const PREFIX: &'static[u8] = b"sta:wil:"; +} + +const BONDING_DURATION: &[u8] = b"sta:loc"; +const VALIDATOR_COUNT: &[u8] = b"sta:vac"; +const SESSIONS_PER_ERA: &[u8] = b"sta:spe"; +const NEXT_SESSIONS_PER_ERA: &[u8] = b"sta:nse"; +const CURRENT_ERA: &[u8] = b"sta:era"; +const LAST_ERA_LENGTH_CHANGE: &[u8] = b"sta:lec"; +const BALANCE_OF: &[u8] = b"sta:bal:"; +const BONDAGE_OF: &[u8] = b"sta:bon:"; + /// The length of the bonding duration in eras. pub fn bonding_duration() -> BlockNumber { storage::get_or_default(BONDING_DURATION) @@ -149,21 +164,6 @@ pub mod internal { } } -struct IntentionStorageVec {} -impl StorageVec for IntentionStorageVec { - type Item = AccountID; - const PREFIX: &'static[u8] = b"sta:wil:"; -} - -const BONDING_DURATION: &[u8] = b"sta:loc"; -const VALIDATOR_COUNT: &[u8] = b"sta:vac"; -const SESSIONS_PER_ERA: &[u8] = b"sta:spe"; -const NEXT_SESSIONS_PER_ERA: &[u8] = b"sta:nse"; -const CURRENT_ERA: &[u8] = b"sta:era"; -const LAST_ERA_LENGTH_CHANGE: &[u8] = b"sta:lec"; -const BALANCE_OF: &[u8] = b"sta:bal:"; -const BONDAGE_OF: &[u8] = b"sta:bon:"; - /// The era has changed - enact new staking set. /// /// NOTE: This always happens immediately before a session change to ensure that new validators diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 2dcd41c503..a6bf24718e 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -24,6 +24,9 @@ use support::{Hashable, storage, with_env}; use primitives::{Block, BlockNumber, Hash, UncheckedTransaction, TxOrder}; use runtime::{staking, session}; +const BLOCK_HASH_AT: &[u8] = b"sys:old:"; +const CODE: &[u8] = b"sys:cod"; + /// The current block number being processed. Set by `execute_block`. pub fn block_number() -> BlockNumber { with_env(|e| e.block_number) @@ -119,9 +122,6 @@ fn final_checks(_block: &Block) { }); } -const BLOCK_HASH_AT: &[u8] = b"sys:old:"; -const CODE: &[u8] = b"sys:cod"; - #[cfg(test)] mod tests { use super::*; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs index 01df210c5f..f0a798d112 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs @@ -18,6 +18,8 @@ use support::storage; +const CURRENT_TIMESTAMP: &[u8] = b"tim:val"; + /// Representation of a time. pub type Timestamp = u64; @@ -35,8 +37,6 @@ pub mod public { } } -const CURRENT_TIMESTAMP: &[u8] = b"tim:val"; - #[cfg(test)] mod tests { use super::*; From 1e0b1338414d5ce50dd3bc90b03ffb8b2164a60f Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Mon, 29 Jan 2018 00:22:15 +0100 Subject: [PATCH 110/112] Fix verify logic. --- substrate/wasm-runtime/std/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/wasm-runtime/std/src/lib.rs b/substrate/wasm-runtime/std/src/lib.rs index 6969f0cf1c..9b7d385e69 100644 --- a/substrate/wasm-runtime/std/src/lib.rs +++ b/substrate/wasm-runtime/std/src/lib.rs @@ -111,7 +111,7 @@ pub fn twox_128(data: &[u8]) -> [u8; 16] { /// Verify a ed25519 signature. pub fn ed25519_verify(sig: &[u8], msg: &[u8], pubkey: &[u8]) -> bool { - sig.len() != 64 || pubkey.len() != 32 || unsafe { + sig.len() == 64 && pubkey.len() == 32 && unsafe { ext_ed25519_verify(msg.as_ptr(), msg.len() as u32, sig.as_ptr(), pubkey.as_ptr()) } == 0 } From c8c0879f3dfedb37ff5b364ca9b96d2b6b708517 Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Mon, 29 Jan 2018 17:19:56 +0100 Subject: [PATCH 111/112] Correct implementation of `memcmp` --- substrate/Cargo.lock | 8 +------- substrate/executor/Cargo.toml | 2 +- substrate/executor/src/error.rs | 6 ++++++ substrate/executor/src/lib.rs | 2 +- substrate/executor/src/wasm_executor.rs | 12 ++++++++---- substrate/wasm-runtime/pwasm-libc/src/lib.rs | 2 +- .../release/runtime_polkadot.compact.wasm | Bin 64054 -> 64085 bytes .../release/runtime_polkadot.wasm | Bin 64103 -> 64134 bytes .../release/runtime_test.compact.wasm | Bin 13189 -> 13189 bytes .../release/runtime_test.wasm | Bin 13314 -> 13314 bytes 10 files changed, 18 insertions(+), 14 deletions(-) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 6d5f20ecdf..c741c845a5 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -498,11 +498,6 @@ dependencies = [ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "memcmp" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "memorydb" version = "0.1.1" @@ -731,7 +726,7 @@ dependencies = [ "assert_matches 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memcmp 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "native-runtime 0.1.0", "parity-wasm 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)", "polkadot-primitives 0.1.0", @@ -1339,7 +1334,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2" "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" -"checksum memcmp 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9a1b44fee357b6a05a9e22554ded6c1bbe57844b58190295257ac0ad4c5944e1" "checksum memorydb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "013b7e4c5e10c764936ebc6bd3662d8e3c92292d267bf6a42ef3f5cad9c793ee" "checksum mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e2e00e17be181010a91dbfefb01660b17311059dc8c7f48b9017677721e732bd" "checksum mio 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0e8411968194c7b139e9105bc4ae7db0bae232af087147e72f0616ebf5fdb9cb" diff --git a/substrate/executor/Cargo.toml b/substrate/executor/Cargo.toml index 498482c03f..5329eb7023 100644 --- a/substrate/executor/Cargo.toml +++ b/substrate/executor/Cargo.toml @@ -15,7 +15,7 @@ byteorder = "1.1" rustc-hex = "1.0.0" native-runtime = { path = "../native-runtime", version = "0.1" } runtime-std = { path = "../native-runtime/std", version = "0.1" } -memcmp = { version = "0.0.6" } +libc = { version = "0.2.33" } [dev-dependencies] assert_matches = "1.1" diff --git a/substrate/executor/src/error.rs b/substrate/executor/src/error.rs index c1f9c2c711..973fa58d38 100644 --- a/substrate/executor/src/error.rs +++ b/substrate/executor/src/error.rs @@ -59,5 +59,11 @@ error_chain! { description("runtime failure"), display("Runtime error"), } + + /// Runtime failed. + InvalidMemoryReference { + description("invalid memory reference"), + display("Invalid memory reference"), + } } } diff --git a/substrate/executor/src/lib.rs b/substrate/executor/src/lib.rs index cfb0506352..9935f8aec8 100644 --- a/substrate/executor/src/lib.rs +++ b/substrate/executor/src/lib.rs @@ -36,7 +36,7 @@ extern crate byteorder; extern crate rustc_hex; extern crate native_runtime; extern crate runtime_std; -extern crate memcmp; +extern crate libc; #[macro_use] extern crate error_chain; diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index c184abab89..a4b1b453c2 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -16,10 +16,11 @@ //! Rust implementation of Polkadot contracts. +use libc::{memcmp, c_void}; use std::sync::Arc; use std::collections::HashMap; use parity_wasm::{deserialize_buffer, ModuleInstanceInterface, ProgramInstance}; -use parity_wasm::interpreter::{ItemIndex}; +use parity_wasm::interpreter::{ItemIndex, DummyUserError}; use parity_wasm::RuntimeValue::{I32, I64}; use primitives::contract::CallData; use state_machine::{Externalities, CodeExecutor}; @@ -96,10 +97,13 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, ext_memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 => { if let (Ok(sl1), Ok(sl2)) = (this.memory.get(s1, n as usize), this.memory.get(s2, n as usize)) { - use memcmp::Memcmp; - (&sl1).memcmp(&sl2) as i32 + unsafe { + memcmp(sl1.as_ptr() as *const u8 as *const c_void, + sl2.as_ptr() as *const u8 as *const c_void, + n as usize) as i32 + } } else { - 0 + return Err(DummyUserError.into()); } }, ext_memcpy(dest: *mut u8, src: *const u8, count: usize) -> *mut u8 => { diff --git a/substrate/wasm-runtime/pwasm-libc/src/lib.rs b/substrate/wasm-runtime/pwasm-libc/src/lib.rs index 0c2fd43fc6..f4e5eb7a57 100644 --- a/substrate/wasm-runtime/pwasm-libc/src/lib.rs +++ b/substrate/wasm-runtime/pwasm-libc/src/lib.rs @@ -22,7 +22,7 @@ pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut ext_memcpy(dest, src, n) } -/// memcpy extern +/// memcmp extern #[no_mangle] pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 { ext_memcmp(s1, s2, n) diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm index c65945f6213a7648c8f2af485fad014d2f5c2d0f..db7dab9917d324f143aea0837c0fdf2ee30504bc 100644 GIT binary patch delta 9546 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 delta 9532 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 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm index 250789a6eb36864dc8e784b2a20cd7dffa687a88..a0dc5a2754ab33efa1b1deea73317bc369fdc975 100644 GIT binary patch delta 9484 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 delta 9554 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 VBHLRhXZdQ{u)V)@#oP0>{{mWUVU+*? diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm index b7de494d797ad705fdd131f73372496980b4f089..63e7666aadfbfdef2c4286d3397788e339381d7b 100644 GIT binary patch delta 158 zcmZooZ%yBj&%$&-YH}e<3yAv8(g&nAx3g+8f#^-_ZbFO?Hvg2&U}ZcoIZ0j>q^48; z7l>+Ahy*Elps<t?#C@Q!X|kpACy<b?%1lPa1)Gnn7V(-Nkm8m|;ALPCWME)u0Mf!h r`V<ob11FGXaC{)eEts5GkeHlVQmK$%mRgjSlV8r@*dRT*z*rOjBQG+< delta 158 zcmZooZ%yBj&%!i8dU7F43yAv8(g&nAx3g+8f#^-_ZbFO~Hvg2&U}fAgIZ0j>q^48; z7l>+Ahy*Elps<t?#C@Q!X|kpACy<b?%1lPa37e0r7V(;Ik>ZvJ;ALPCWME(@0Mf!h r`V<ob11FGXaJ(SJEts5GkeHlVQmK$%mRgjSlV8r@_(5uNfw3q6Pf9T) diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm index 450a7e7066596a0fbabb0702c9dad058cd5ead9c..c1b257f3a313526e610ecdd3e0fb6fef413f1b6e 100644 GIT binary patch delta 175 zcmZq5Xv)~|hK1>X)Z}+8Eg-6dwGT*bW?|E00@3;$ZbFO?HkV0dureN)d|zG_q=rr5 z7l>j~j07o(Rb0vl;>Id&n!HW<6G&*4%1lPa1)E*eig<kvNO4Of@G>w6GB7YS0BK<$ zeTs>JffGnGI6jc#7EDeoNKDQwsZ_`>OD#&v$uDPcY>?&_&dE$l%*n}5)-Osdk1tD2 I)+;Io0K!!^@&Et; delta 175 zcmZq5Xv)~|hJ|T@^yGIeEg-6dwGT*bW?|E00@3;$ZbFO~HkV0durh9$d|zG_q=rr5 z7l>j~j07o(Rb0vl;>Id&n!HW<6G&*4%1lPa37cKiig<mtNO4O9@G>w6GB7X{0BK<$ zeTs>JffGnGI9`zA7EDeoNKDQwsZ_`>OD#&v$uDPc{2;|GoRgW9n3I#AtY4H^9$%K4 ItXEVF0MgJkQUCw| From a9403a3ed41ee54f40581afad30ef2ac41e75ded Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Mon, 29 Jan 2018 21:29:03 +0100 Subject: [PATCH 112/112] Make memcmp safe. --- substrate/executor/src/wasm_executor.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index a4b1b453c2..439defd449 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -16,8 +16,8 @@ //! Rust implementation of Polkadot contracts. -use libc::{memcmp, c_void}; use std::sync::Arc; +use std::cmp::Ordering; use std::collections::HashMap; use parity_wasm::{deserialize_buffer, ModuleInstanceInterface, ProgramInstance}; use parity_wasm::interpreter::{ItemIndex, DummyUserError}; @@ -97,11 +97,11 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, ext_memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 => { if let (Ok(sl1), Ok(sl2)) = (this.memory.get(s1, n as usize), this.memory.get(s2, n as usize)) { - unsafe { - memcmp(sl1.as_ptr() as *const u8 as *const c_void, - sl2.as_ptr() as *const u8 as *const c_void, - n as usize) as i32 - } + match sl1.cmp(&sl2) { + Ordering::Greater => 1, + Ordering::Less => -1, + Ordering::Equal => 0, + } } else { return Err(DummyUserError.into()); }