diff --git a/substrate/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm b/substrate/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm index f650ddc85fdf2189758363aea9ea27aa5036c17d..f3742d5492f5c14d9d8155c055fb32a3ffa07f81 100644 Binary files a/substrate/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm and b/substrate/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm differ diff --git a/substrate/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm b/substrate/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm index 8f03da6b6570ec0ca879f8082487b83209f40dc5..14ef56c39bca928910ffe8963eca70b19625a177 100755 Binary files a/substrate/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm and b/substrate/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm differ diff --git a/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm b/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm index b7adff2d53861c2623460a07124cb71dcb968588..580bc98f7a85a6fc3556286a46a8fbb06dc2e5f1 100644 Binary files a/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm and b/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm differ diff --git a/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm b/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm index d4e3dd6dd34f3ad9e8727982a3e7c7743d4652e2..e7fb35798f8b7863a1454a8d038e7a6303690c57 100755 Binary files a/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm and b/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm differ diff --git a/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm b/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm index 1d065a3690093b9c40e71c730dc4f17bcf9eb059..b1e3d685a3d2301ff3d3d56acae3b80b852b2011 100644 Binary files a/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm and b/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm differ diff --git a/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm b/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm index 9ba001aada9be42e8982d5ae00ff6fef7a51b74c..e8aafb9f39186a4980c94e5c24f14419f3471f82 100755 Binary files a/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm and b/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm differ diff --git a/substrate/substrate/runtime/staking/src/lib.rs b/substrate/substrate/runtime/staking/src/lib.rs index 8722c6be9b1cd96c1fffb350836decf83129587d..227b220e741d225ac8273ff8b8f1b55d7834f534 100644 --- a/substrate/substrate/runtime/staking/src/lib.rs +++ b/substrate/substrate/runtime/staking/src/lib.rs @@ -39,7 +39,6 @@ extern crate substrate_runtime_system as system; use rstd::prelude::*; use rstd::cmp; use rstd::cell::RefCell; -use rstd::marker::PhantomData; use rstd::collections::btree_map::{BTreeMap, Entry}; use codec::Slicable; use runtime_support::{StorageValue, StorageMap, Parameter}; @@ -170,8 +169,8 @@ impl<T: Trait> Module<T> { /// Create a smart-contract account. pub fn create(aux: &T::PublicAux, code: &[u8], value: T::Balance) { // commit anything that made it this far to storage - if let Some(commit) = Self::effect_create(aux.ref_into(), code, value, DirectExt) { - Self::commit_state(commit); + if let Some(commit) = Self::effect_create(aux.ref_into(), code, value, DirectAccountDb) { + <AccountDb<T>>::merge(&DirectAccountDb, commit); } } @@ -181,8 +180,8 @@ impl<T: Trait> Module<T> { /// TODO: probably want to state gas-limit and gas-price. fn transfer(aux: &T::PublicAux, dest: T::AccountId, value: T::Balance) { // commit anything that made it this far to storage - if let Some(commit) = Self::effect_transfer(aux.ref_into(), &dest, value, DirectExt) { - Self::commit_state(commit); + if let Some(commit) = Self::effect_transfer(aux.ref_into(), &dest, value, DirectAccountDb) { + <AccountDb<T>>::merge(&DirectAccountDb, commit); } } @@ -378,25 +377,20 @@ impl<T: Trait> ChangeEntry<T> { type State<T> = BTreeMap<<T as system::Trait>::AccountId, ChangeEntry<T>>; -trait Externalities<T: Trait> { +trait AccountDb<T: Trait> { fn get_storage(&self, account: &T::AccountId, location: &[u8]) -> Option<Vec<u8>>; fn get_code(&self, account: &T::AccountId) -> Vec<u8>; fn get_balance(&self, account: &T::AccountId) -> T::Balance; -} -struct Ext<T: Trait, F1, F3, F5> where - F1 : Fn(&T::AccountId, &[u8]) -> Option<Vec<u8>>, - F3 : Fn(&T::AccountId) -> Vec<u8>, - F5 : Fn(&T::AccountId) -> T::Balance -{ - do_get_storage: F1, - do_get_code: F3, - do_get_balance: F5, - _unused: PhantomData<T>, + fn set_storage(&self, account: &T::AccountId, location: Vec<u8>, value: Option<Vec<u8>>); + fn set_code(&self, account: &T::AccountId, code: Vec<u8>); + fn set_balance(&self, account: &T::AccountId, balance: T::Balance); + + fn merge(&self, state: State<T>); } -struct DirectExt; -impl<T: Trait> Externalities<T> for DirectExt { +struct DirectAccountDb; +impl<T: Trait> AccountDb<T> for DirectAccountDb { fn get_storage(&self, account: &T::AccountId, location: &[u8]) -> Option<Vec<u8>> { <StorageOf<T>>::get(&(account.clone(), location.to_vec())) } @@ -406,26 +400,20 @@ impl<T: Trait> Externalities<T> for DirectExt { fn get_balance(&self, account: &T::AccountId) -> T::Balance { <FreeBalance<T>>::get(account) } -} - -impl<T: Trait, F1, F3, F5> Externalities<T> for Ext<T, F1, F3, F5> where - F1 : Fn(&T::AccountId, &[u8]) -> Option<Vec<u8>>, - F3 : Fn(&T::AccountId) -> Vec<u8>, - F5 : Fn(&T::AccountId) -> T::Balance -{ - fn get_storage(&self, account: &T::AccountId, location: &[u8]) -> Option<Vec<u8>> { - (self.do_get_storage)(account, location) + fn set_storage(&self, account: &T::AccountId, location: Vec<u8>, value: Option<Vec<u8>>) { + if let Some(value) = value { + <StorageOf<T>>::insert(&(account.clone(), location), &value); + } else { + <StorageOf<T>>::remove(&(account.clone(), location)); + } } - fn get_code(&self, account: &T::AccountId) -> Vec<u8> { - (self.do_get_code)(account) + fn set_code(&self, account: &T::AccountId, code: Vec<u8>) { + <CodeOf<T>>::insert(account, &code); } - fn get_balance(&self, account: &T::AccountId) -> T::Balance { - (self.do_get_balance)(account) + fn set_balance(&self, account: &T::AccountId, balance: T::Balance) { + <FreeBalance<T>>::insert(account, balance); } -} - -impl<T: Trait> Module<T> { - fn commit_state(s: State<T>) { + fn merge(&self, s: State<T>) { for (address, changed) in s.into_iter() { if let Some(balance) = changed.balance { <FreeBalance<T>>::insert(&address, balance); @@ -442,9 +430,63 @@ impl<T: Trait> Module<T> { } } } +} - fn merge_state(commit_state: State<T>, local: &mut State<T>) { - for (address, changed) in commit_state.into_iter() { +struct OverlayAccountDb<'a, T: Trait + 'a> { + local: RefCell<State<T>>, + underlying: &'a AccountDb<T>, +} +impl<'a, T: Trait> OverlayAccountDb<'a, T> { + fn new(underlying: &'a AccountDb<T>) -> OverlayAccountDb<'a, T> { + OverlayAccountDb { + local: RefCell::new(State::new()), + underlying, + } + } + + fn into_state(self) -> State<T> { + self.local.into_inner() + } +} +impl<'a, T: Trait> AccountDb<T> for OverlayAccountDb<'a, T> { + fn get_storage(&self, account: &T::AccountId, location: &[u8]) -> Option<Vec<u8>> { + self.local.borrow().get(account) + .and_then(|a| a.storage.get(location)) + .cloned() + .unwrap_or_else(|| self.underlying.get_storage(account, location)) + } + fn get_code(&self, account: &T::AccountId) -> Vec<u8> { + self.local.borrow().get(account) + .and_then(|a| a.code.clone()) + .unwrap_or_else(|| self.underlying.get_code(account)) + } + fn get_balance(&self, account: &T::AccountId) -> T::Balance { + self.local.borrow().get(account) + .and_then(|a| a.balance) + .unwrap_or_else(|| self.underlying.get_balance(account)) + } + fn set_storage(&self, account: &T::AccountId, location: Vec<u8>, value: Option<Vec<u8>>) { + self.local.borrow_mut() + .entry(account.clone()) + .or_insert(Default::default()) + .storage.insert(location, value); + } + fn set_code(&self, account: &T::AccountId, code: Vec<u8>) { + self.local.borrow_mut() + .entry(account.clone()) + .or_insert(Default::default()) + .code = Some(code); + } + fn set_balance(&self, account: &T::AccountId, balance: T::Balance) { + self.local.borrow_mut() + .entry(account.clone()) + .or_insert(Default::default()) + .balance = Some(balance); + } + fn merge(&self, s: State<T>) { + let mut local = self.local.borrow_mut(); + + for (address, changed) in s.into_iter() { match local.entry(address) { Entry::Occupied(e) => { let mut value = e.into_mut(); @@ -462,14 +504,16 @@ impl<T: Trait> Module<T> { } } } +} - fn effect_create<E: Externalities<T>>( +impl<T: Trait> Module<T> { + fn effect_create<DB: AccountDb<T>>( transactor: &T::AccountId, code: &[u8], value: T::Balance, - ext: E + account_db: DB ) -> Option<State<T>> { - let from_balance = ext.get_balance(transactor); + let from_balance = account_db.get_balance(transactor); // TODO: a fee. assert!(from_balance >= value); @@ -490,16 +534,16 @@ impl<T: Trait> Module<T> { Some(local) } - fn effect_transfer<E: Externalities<T>>( + fn effect_transfer<DB: AccountDb<T>>( transactor: &T::AccountId, dest: &T::AccountId, value: T::Balance, - ext: E + account_db: DB ) -> Option<State<T>> { - let from_balance = ext.get_balance(transactor); + let from_balance = account_db.get_balance(transactor); assert!(from_balance >= value); - let to_balance = ext.get_balance(dest); + let to_balance = account_db.get_balance(dest); assert!(<Bondage<T>>::get(transactor) <= <Bondage<T>>::get(dest)); assert!(to_balance + value > to_balance); // no overflow @@ -507,57 +551,23 @@ impl<T: Trait> Module<T> { // TODO: consider storing upper-bound for contract's gas limit in fixed-length runtime // code in contract itself and use that. - let local: RefCell<State<T>> = RefCell::new(BTreeMap::new()); + // Our local overlay: Should be used for any transfers and creates that happen internally. + let overlay = OverlayAccountDb::new(&account_db); if transactor != dest { - let mut local = local.borrow_mut(); - local.insert(transactor.clone(), ChangeEntry::balance_changed(from_balance - value)); - local.insert(dest.clone(), ChangeEntry::balance_changed(to_balance + value)); + overlay.set_balance(transactor, from_balance - value); + overlay.set_balance(dest, to_balance + value); } let should_commit = { - // Our local ext: Should be used for any transfers and creates that happen internally. - let ext = || Ext { - do_get_storage: |account: &T::AccountId, location: &[u8]| - local.borrow().get(account) - .and_then(|a| a.storage.get(location)) - .cloned() - .unwrap_or_else(|| ext.get_storage(account, location)), - do_get_code: |account: &T::AccountId| - local.borrow().get(account) - .and_then(|a| a.code.clone()) - .unwrap_or_else(|| ext.get_code(account)), - do_get_balance: |account: &T::AccountId| - local.borrow().get(account) - .and_then(|a| a.balance) - .unwrap_or_else(|| ext.get_balance(account)), - _unused: Default::default(), - }; - let mut _transfer = |inner_dest: &T::AccountId, value: T::Balance| { - if let Some(commit_state) = Self::effect_transfer(dest, inner_dest, value, ext()) { - Self::merge_state(commit_state, &mut *local.borrow_mut()); - } - }; - let mut _create = |code: &[u8], value: T::Balance| { - if let Some(commit_state) = Self::effect_create(dest, code, value, ext()) { - Self::merge_state(commit_state, &mut *local.borrow_mut()); - } - }; - let mut _put_storage = |location: Vec<u8>, value: Option<Vec<u8>>| { - local.borrow_mut() - .entry(dest.clone()) - .or_insert(Default::default()) - .storage.insert(location, value); - }; - // TODO: logging (logs are just appended into a notable storage-based vector and cleared every // block). - // TODO: execute code with ext(), put_storage, create and transfer as externalities. + // TODO: if `overlay.get_code(dest)` isn't empty then execute code with `overlay`. true }; if should_commit { - Some(local.into_inner()) + Some(overlay.into_state()) } else { None } diff --git a/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm b/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm index 2f8ace8b215fc2ffacdc53f9297fccd0043cb816..22b9ccbd4e756d3e6120289f8707d82348021b53 100644 Binary files a/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm and b/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm differ diff --git a/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm b/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm index 2f94b9a9c82efae416d7a354f7b6b2cf7becccad..4b58dd7820463a629bdea8c0acc812f3cc667bf5 100755 Binary files a/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm and b/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm differ