Files
pezkuwi-subxt/substrate/srml/contract/src/account_db.rs
T
Gav Wood 1e01162505 Phase 1 of repo reorg (#719)
* Remove unneeded script

* Rename Substrate Demo -> Substrate

* Rename demo -> node

* Build wasm from last rename.

* Merge ed25519 into substrate-primitives

* Minor tweak

* Rename substrate -> core

* Move substrate-runtime-support to core/runtime/support

* Rename/move substrate-runtime-version

* Move codec up a level

* Rename substrate-codec -> parity-codec

* Move environmental up a level

* Move pwasm-* up to top, ready for removal

* Remove requirement of s-r-support from s-r-primitives

* Move core/runtime/primitives into core/runtime-primitives

* Remove s-r-support dep from s-r-version

* Remove dep of s-r-support from bft

* Remove dep of s-r-support from node/consensus

* Sever all other core deps from s-r-support

* Forgot the no_std directive

* Rename non-SRML modules to sr-* to avoid match clashes

* Move runtime/* to srml/*

* Rename substrate-runtime-* -> srml-*

* Move srml to top-level
2018-09-12 11:13:31 +02:00

181 lines
5.2 KiB
Rust

// Copyright 2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate 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.
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Auxilliaries to help with managing partial changes to accounts state.
use super::{CodeOf, StorageOf, Trait};
use double_map::StorageDoubleMap;
use rstd::cell::RefCell;
use rstd::collections::btree_map::{BTreeMap, Entry};
use rstd::prelude::*;
use runtime_support::StorageMap;
use {balances, system};
pub struct ChangeEntry<T: Trait> {
balance: Option<T::Balance>,
code: Option<Vec<u8>>,
storage: BTreeMap<Vec<u8>, Option<Vec<u8>>>,
}
// Cannot derive(Default) since it erroneously bounds T by Default.
impl<T: Trait> Default for ChangeEntry<T> {
fn default() -> Self {
ChangeEntry {
balance: Default::default(),
code: Default::default(),
storage: Default::default(),
}
}
}
pub type ChangeSet<T> = BTreeMap<<T as system::Trait>::AccountId, ChangeEntry<T>>;
pub 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;
fn commit(&mut self, change_set: ChangeSet<T>);
}
pub 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())
}
fn get_code(&self, account: &T::AccountId) -> Vec<u8> {
<CodeOf<T>>::get(account)
}
fn get_balance(&self, account: &T::AccountId) -> T::Balance {
balances::Module::<T>::free_balance(account)
}
fn commit(&mut self, s: ChangeSet<T>) {
for (address, changed) in s.into_iter() {
if let Some(balance) = changed.balance {
if let balances::UpdateBalanceOutcome::AccountKilled =
balances::Module::<T>::set_free_balance_creating(&address, balance)
{
// Account killed. This will ultimately lead to calling `OnFreeBalanceZero` callback
// which will make removal of CodeOf and StorageOf for this account.
// In order to avoid writing over the deleted properties we `continue` here.
continue;
}
}
if let Some(code) = changed.code {
<CodeOf<T>>::insert(&address, &code);
}
for (k, v) in changed.storage.into_iter() {
if let Some(value) = v {
<StorageOf<T>>::insert(address.clone(), k, value);
} else {
<StorageOf<T>>::remove(address.clone(), k);
}
}
}
}
}
pub struct OverlayAccountDb<'a, T: Trait + 'a> {
local: RefCell<ChangeSet<T>>,
underlying: &'a AccountDb<T>,
}
impl<'a, T: Trait> OverlayAccountDb<'a, T> {
pub fn new(underlying: &'a AccountDb<T>) -> OverlayAccountDb<'a, T> {
OverlayAccountDb {
local: RefCell::new(ChangeSet::new()),
underlying,
}
}
pub fn into_change_set(self) -> ChangeSet<T> {
self.local.into_inner()
}
pub fn set_storage(
&mut 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);
}
pub fn set_code(&mut self, account: &T::AccountId, code: Vec<u8>) {
self.local
.borrow_mut()
.entry(account.clone())
.or_insert(Default::default())
.code = Some(code);
}
pub fn set_balance(&mut self, account: &T::AccountId, balance: T::Balance) {
self.local
.borrow_mut()
.entry(account.clone())
.or_insert(Default::default())
.balance = Some(balance);
}
}
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 commit(&mut self, s: ChangeSet<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();
if changed.balance.is_some() {
value.balance = changed.balance;
}
if changed.code.is_some() {
value.code = changed.code;
}
value.storage.extend(changed.storage.into_iter());
}
Entry::Vacant(e) => {
e.insert(changed);
}
}
}
}
}