diff --git a/substrate/core/executor/wasm/src/lib.rs b/substrate/core/executor/wasm/src/lib.rs index 842749dd5bbf460f6b2766cf5c90558d2ea3e74c..193ff5c9c0d3cbe9d39122f28126c6b052de55a5 100644 --- a/substrate/core/executor/wasm/src/lib.rs +++ b/substrate/core/executor/wasm/src/lib.rs @@ -1,7 +1,6 @@ #![no_std] #![cfg_attr(feature = "strict", deny(warnings))] -#![feature(alloc)] extern crate alloc; use alloc::vec::Vec; use alloc::slice; diff --git a/substrate/core/finality-grandpa/primitives/src/lib.rs b/substrate/core/finality-grandpa/primitives/src/lib.rs index 7016a708bd62b8c0f1bc05726d193dd2dc986d1e..869b5e68fd6af5f744d4f9ed34ca77af7545f822 100644 --- a/substrate/core/finality-grandpa/primitives/src/lib.rs +++ b/substrate/core/finality-grandpa/primitives/src/lib.rs @@ -17,7 +17,6 @@ //! Primitives for GRANDPA integration, suitable for WASM compilation. #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(not(feature = "std"), feature(alloc))] #[cfg(not(feature = "std"))] extern crate alloc; diff --git a/substrate/core/primitives/src/lib.rs b/substrate/core/primitives/src/lib.rs index 97f5480743cef5f397cb13da3b823e54a1fea5f2..c9008171df94376893596b39790d15db3d8bffe4 100644 --- a/substrate/core/primitives/src/lib.rs +++ b/substrate/core/primitives/src/lib.rs @@ -19,7 +19,6 @@ #![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(not(feature = "std"), feature(alloc))] /// Initialize a key-value collection from array. /// diff --git a/substrate/core/sr-io/src/lib.rs b/substrate/core/sr-io/src/lib.rs index 5101d3b2c124b0d23ce02ed2f3e83f5eb1ec63cc..47af4de98ba642133a0069ceccf0e97a90114daa 100644 --- a/substrate/core/sr-io/src/lib.rs +++ b/substrate/core/sr-io/src/lib.rs @@ -22,7 +22,6 @@ #![cfg_attr(not(feature = "std"), feature(lang_items))] #![cfg_attr(not(feature = "std"), feature(alloc_error_handler))] #![cfg_attr(not(feature = "std"), feature(core_intrinsics))] -#![cfg_attr(not(feature = "std"), feature(alloc))] #![cfg_attr(feature = "std", doc = "Substrate runtime standard library as compiled when linked with Rust's standard library.")] #![cfg_attr(not(feature = "std"), doc = "Substrate's runtime standard library as compiled without Rust's standard library.")] diff --git a/substrate/core/sr-sandbox/src/lib.rs b/substrate/core/sr-sandbox/src/lib.rs index e8bdd5727ea8795ea16efeae71426aecc014e73f..1e8b2b3f1df5e63f76012f7e642f8dd04422aabf 100755 --- a/substrate/core/sr-sandbox/src/lib.rs +++ b/substrate/core/sr-sandbox/src/lib.rs @@ -37,7 +37,6 @@ #![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(core_intrinsics))] -#![cfg_attr(not(feature = "std"), feature(alloc))] use rstd::prelude::*; diff --git a/substrate/core/sr-std/src/lib.rs b/substrate/core/sr-std/src/lib.rs index 45857b33eda784a3107bc162a3c12c1b610d0342..b9874bcc2018d5e680fdf51025ffaa77165700ac 100644 --- a/substrate/core/sr-std/src/lib.rs +++ b/substrate/core/sr-std/src/lib.rs @@ -19,7 +19,6 @@ #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(core_intrinsics))] -#![cfg_attr(not(feature = "std"), feature(alloc))] #![cfg_attr(feature = "std", doc = "Substrate runtime standard library as compiled when linked with Rust's standard library.")] #![cfg_attr(not(feature = "std"), doc = "Substrate's runtime standard library as compiled without Rust's standard library.")] diff --git a/substrate/core/trie/src/lib.rs b/substrate/core/trie/src/lib.rs index da6630e46d47a530cc482b3c08419716808a59b8..1322038d7847cbec83d36349014ba5e0717282e3 100644 --- a/substrate/core/trie/src/lib.rs +++ b/substrate/core/trie/src/lib.rs @@ -17,7 +17,6 @@ //! Utility functions to interact with Substrate's Base-16 Modified Merkle Patricia tree ("trie"). #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(not(feature = "std"), feature(alloc))] mod error; mod node_header; diff --git a/substrate/node-template/runtime/src/lib.rs b/substrate/node-template/runtime/src/lib.rs index f7325923c7641f3b6180eb1a5090a242728d27fd..81adf200d05f405eedbfa3dd1d9d7b29e5a25abc 100644 --- a/substrate/node-template/runtime/src/lib.rs +++ b/substrate/node-template/runtime/src/lib.rs @@ -1,7 +1,6 @@ //! The Substrate Node Template runtime. This can be compiled with `#[no_std]`, ready for Wasm. #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(not(feature = "std"), feature(alloc))] // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. #![recursion_limit="256"] diff --git a/substrate/node/primitives/src/lib.rs b/substrate/node/primitives/src/lib.rs index 0d8906c47df817f4c6c62c2a3b6d54365b47bb77..4dde59296f4980c6ec4a0b3bf6734609de6405bf 100644 --- a/substrate/node/primitives/src/lib.rs +++ b/substrate/node/primitives/src/lib.rs @@ -19,7 +19,6 @@ #![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(not(feature = "std"), feature(alloc))] use runtime_primitives::{ generic, traits::{Verify, BlakeTwo256}, OpaqueExtrinsic, AnySignature diff --git a/substrate/node/runtime/src/lib.rs b/substrate/node/runtime/src/lib.rs index 748b5c63928c4ff0be6e81343cf9cf568cb0ff5b..d0d603bb10d33f216169389e9b150f38abc1db24 100644 --- a/substrate/node/runtime/src/lib.rs +++ b/substrate/node/runtime/src/lib.rs @@ -58,8 +58,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("node"), impl_name: create_runtime_str!("substrate-node"), authoring_version: 10, - spec_version: 71, - impl_version: 71, + spec_version: 72, + impl_version: 72, apis: RUNTIME_API_VERSIONS, }; diff --git a/substrate/srml/executive/src/lib.rs b/substrate/srml/executive/src/lib.rs index 6ca10bed2d5c73b7cb4f4344d64faaf1d3ae8cfb..f6dcae4a4c9293df00afea416cc6c260fccde3ae 100644 --- a/substrate/srml/executive/src/lib.rs +++ b/substrate/srml/executive/src/lib.rs @@ -443,7 +443,7 @@ mod tests { header: Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!("4c10fddf15e63c91ff2aa13ab3a9b7f6b19938d533829489e72ba40278a08fac").into(), + state_root: hex!("ac2840371d51ff2e036c8fc05af7313b7a030f735c38b2f03b94cbe87bfbb7c9").into(), extrinsics_root: hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(), digest: Digest { logs: vec![], }, }, diff --git a/substrate/srml/support/src/lib.rs b/substrate/srml/support/src/lib.rs index 78edc361d5e67ffea6952f3a6d4f30041ba0566c..b0fe28c63c5b9fdc2b6ad7a2c4c121cfd06f72d2 100644 --- a/substrate/srml/support/src/lib.rs +++ b/substrate/srml/support/src/lib.rs @@ -17,7 +17,6 @@ //! Support code for the runtime. #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(not(feature = "std"), feature(alloc))] #[macro_use] extern crate bitmask; diff --git a/substrate/srml/system/src/lib.rs b/substrate/srml/system/src/lib.rs index e3d77438f9c27f94ceb213a2ad309956f8043797..0d3264c5ab04e990eb2127600eae3bacd1df7277 100644 --- a/substrate/srml/system/src/lib.rs +++ b/substrate/srml/system/src/lib.rs @@ -302,8 +302,9 @@ decl_storage! { pub BlockHash get(block_hash) build(|_| vec![(T::BlockNumber::zero(), hash69())]): map T::BlockNumber => T::Hash; /// Extrinsics data for the current block (maps an extrinsic's index to its data). ExtrinsicData get(extrinsic_data): map u32 => Vec<u8>; - /// Random seed of the current block. - RandomSeed get(random_seed) build(|_| T::Hash::default()): T::Hash; + /// Series of block headers from the last 81 blocks that acts as random seed material. This is arranged as a + /// ring buffer with the `i8` prefix being the index into the `Vec` of the oldest hash. + RandomMaterial get(random_material): (i8, Vec<T::Hash>); /// The current block number being processed. Set by `execute_block`. Number get(block_number) build(|_| T::BlockNumber::sa(1u64)): T::BlockNumber; /// Hash of the previous block. @@ -395,13 +396,17 @@ impl<T: Trait> Module<T> { <ParentHash<T>>::put(parent_hash); <BlockHash<T>>::insert(*number - One::one(), parent_hash); <ExtrinsicsRoot<T>>::put(txs_root); - <RandomSeed<T>>::put(Self::calculate_random()); + <RandomMaterial<T>>::mutate(|&mut(ref mut index, ref mut values)| if values.len() < 81 { + values.push(parent_hash.clone()) + } else { + values[*index as usize] = parent_hash.clone(); + *index = (*index + 1) % 81; + }); <Events<T>>::kill(); } /// Remove temporary "environment" entries in storage. pub fn finalize() -> T::Header { - <RandomSeed<T>>::kill(); <ExtrinsicCount<T>>::kill(); <AllExtrinsicsLen<T>>::kill(); @@ -432,26 +437,13 @@ impl<T: Trait> Module<T> { <Digest<T>>::put(l); } - /// Calculate the current block's random seed. - fn calculate_random() -> T::Hash { - assert!(Self::block_number() > Zero::zero(), "Block number may never be zero"); - (0..81) - .scan( - Self::block_number() - One::one(), - |c, _| { if *c > Zero::zero() { *c -= One::one() }; Some(*c) - }) - .map(Self::block_hash) - .triplet_mix() - } - /// Get the basic externalities for this module, useful for tests. #[cfg(any(feature = "std", test))] pub fn externalities() -> TestExternalities<Blake2Hasher> { TestExternalities::new(map![ twox_128(&<BlockHash<T>>::key_for(T::BlockNumber::zero())).to_vec() => [69u8; 32].encode(), twox_128(<Number<T>>::key()).to_vec() => T::BlockNumber::one().encode(), - twox_128(<ParentHash<T>>::key()).to_vec() => [69u8; 32].encode(), - twox_128(<RandomSeed<T>>::key()).to_vec() => T::Hash::default().encode() + twox_128(<ParentHash<T>>::key()).to_vec() => [69u8; 32].encode() ]) } @@ -475,11 +467,54 @@ impl<T: Trait> Module<T> { <ParentHash<T>>::put(n); } - /// Set the random seed to something in particular. Can be used as an alternative to - /// `initialize` for tests that don't need to bother with the other environment entries. - #[cfg(any(feature = "std", test))] - pub fn set_random_seed(seed: T::Hash) { - <RandomSeed<T>>::put(seed); + /// Get the basic random seed. + /// + /// In general you won't want to use this, but rather `Self::random` which allows you to give a subject for the + /// random result and whose value will be independently low-influence random from any other such seeds. + pub fn random_seed() -> T::Hash { + Self::random(&[][..]) + } + + /// Get a low-influence "random" value. + /// + /// Being a deterministic block chain, real randomness is difficult to come by. This gives you something that + /// approximates it. `subject` is a context identifier and allows you to get a different result to other callers + /// of this function; use it like `random(&b"my context"[..])`. + /// + /// This is initially implemented through a low-influence "triplet mix" convolution of previous block hash values. + /// In the future it will be generated from a secure "VRF". + /// + /// ### Security Notes + /// This randomness uses a low-influence function, drawing upon the block hashes from the previous 81 blocks. Its + /// result for any given subject will be known in advance by the block producer of this block (and, indeed, anyone + /// who knows the block's `parent_hash`). However, it is mostly impossible for the producer of this block *alone* + /// to influence the value of this hash. A sizable minority of dishonest and coordinating block producers would be + /// required in order to affect this value. If that is an insufficient security guarantee then two things can be + /// used to improve this randomness: + /// - Name, in advance, the block number whose random value will be used; ensure your module retains a buffer of + /// previous random values for its subject and then index into these in order to obviate the ability of your user + /// to look up the parent hash and choose when to transact based upon it. + /// - Require your user to first commit to an additional value by first posting its hash. Require them to reveal + /// the value to determine the final result, hashing it with the output of this random function. This reduces the + /// ability of a cabal of block producers from conspiring against individuals. + /// + /// WARNING: Hashing the result of this function will remove any low-infleunce properties it has and mean that + /// all bits of the resulting value are entirely manipulatable by the author of the parent block, who can determine + /// the value of `parent_hash`. + pub fn random(subject: &[u8]) -> T::Hash { + let (index, hash_series) = <RandomMaterial<T>>::get(); + if hash_series.len() > 0 { + // Always the case after block 1 is initialised. + hash_series.iter() + .cycle() + .skip(index as usize) + .take(81) + .enumerate() + .map(|(i, h)| (i as i8, subject, h).using_encoded(T::Hashing::hash)) + .triplet_mix() + } else { + T::Hash::default() + } } /// Increment a particular account's nonce by 1.