#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
#[cfg(not(feature = "std"))]
use alloc::{collections::btree_map as map, collections::BTreeMap as Map, collections::BTreeSet as Set};
use bigint::{Address, M256, U256};
#[cfg(not(feature = "std"))]
use core::cell::RefCell;
#[cfg(feature = "std")]
use std::cell::RefCell;
#[cfg(feature = "std")]
use std::collections::{hash_map as map, HashMap as Map, HashSet as Set};
#[cfg(not(feature = "std"))]
use alloc::rc::Rc;
#[cfg(feature = "std")]
use std::rc::Rc;
use crate::{
errors::{CommitError, RequireError},
AccountPatch,
};
#[derive(Debug, Clone)]
pub struct Storage {
partial: bool,
address: Address,
storage: Map<U256, M256>,
}
impl Into<Map<U256, M256>> for Storage {
fn into(self) -> Map<U256, M256> {
self.storage
}
}
impl Storage {
fn new(address: Address, partial: bool) -> Self {
Storage {
partial,
address,
storage: Map::new(),
}
}
fn commit(&mut self, index: U256, value: M256) -> Result<(), CommitError> {
if !self.partial {
return Err(CommitError::InvalidCommitment);
}
if self.storage.contains_key(&index) {
return Err(CommitError::AlreadyCommitted);
}
self.storage.insert(index, value);
Ok(())
}
pub fn read(&self, index: U256) -> Result<M256, RequireError> {
match self.storage.get(&index) {
Some(&v) => Ok(v),
None => {
if self.partial {
Err(RequireError::AccountStorage(self.address, index))
} else {
Ok(M256::zero())
}
}
}
}
pub fn write(&mut self, index: U256, value: M256) -> Result<(), RequireError> {
if !self.storage.contains_key(&index) && self.partial {
return Err(RequireError::AccountStorage(self.address, index));
}
self.storage.insert(index, value);
Ok(())
}
#[inline]
pub fn len(&self) -> usize {
self.storage.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
#[derive(Debug, Clone)]
pub enum AccountCommitment {
Full {
nonce: U256,
address: Address,
balance: U256,
code: Rc<Vec<u8>>,
},
Code {
address: Address,
code: Rc<Vec<u8>>,
},
Storage {
address: Address,
index: U256,
value: M256,
},
Nonexist(Address),
}
impl AccountCommitment {
pub fn address(&self) -> Address {
match *self {
AccountCommitment::Full { address, .. } => address,
AccountCommitment::Code { address, .. } => address,
AccountCommitment::Storage { address, .. } => address,
AccountCommitment::Nonexist(address) => address,
}
}
}
#[derive(Debug, Clone)]
pub enum AccountChange {
Full {
nonce: U256,
address: Address,
balance: U256,
changing_storage: Storage,
code: Rc<Vec<u8>>,
},
IncreaseBalance(Address, U256),
Create {
nonce: U256,
address: Address,
balance: U256,
storage: Storage,
code: Rc<Vec<u8>>,
},
Nonexist(Address),
}
impl AccountChange {
pub fn address(&self) -> Address {
match *self {
AccountChange::Full { address, .. } => address,
AccountChange::IncreaseBalance(address, _) => address,
AccountChange::Create { address, .. } => address,
AccountChange::Nonexist(address) => address,
}
}
}
#[derive(Debug)]
pub struct AccountState<'a, A: AccountPatch> {
accounts: Map<Address, AccountChange>,
orig_storage: RefCell<Map<Address, Storage>>,
codes: Map<Address, Rc<Vec<u8>>>,
account_patch: &'a A,
}
impl<'a, A: AccountPatch> AccountState<'a, A> {
pub fn new(account_patch: &'a A) -> Self {
Self {
accounts: Map::new(),
codes: Map::new(),
orig_storage: RefCell::new(Map::new()),
account_patch,
}
}
pub fn derive_from<'b>(account_patch: &'a A, prev: &AccountState<'b, A>) -> Self {
Self {
accounts: prev.accounts.clone(),
orig_storage: prev.orig_storage.clone(),
codes: prev.codes.clone(),
account_patch,
}
}
}
impl<'a, A: AccountPatch> Clone for AccountState<'a, A> {
fn clone(&self) -> Self {
Self {
accounts: self.accounts.clone(),
orig_storage: self.orig_storage.clone(),
codes: self.codes.clone(),
account_patch: self.account_patch,
}
}
}
fn is_empty(nonce: U256, balance: U256, code: &[u8]) -> bool {
nonce == U256::zero() && balance == U256::zero() && code.is_empty()
}
impl<'a, A: AccountPatch> AccountState<'a, A> {
fn insert_account(&mut self, account: AccountChange) {
match account {
AccountChange::Full {
nonce,
address,
balance,
changing_storage,
code,
} => {
if (!self.account_patch.empty_considered_exists()) && is_empty(nonce, balance, &code) {
self.accounts.insert(address, AccountChange::Nonexist(address));
} else {
self.accounts.insert(
address,
AccountChange::Full {
nonce,
address,
balance,
changing_storage,
code,
},
);
}
}
AccountChange::Create {
nonce,
address,
balance,
storage,
code,
} => {
if (!self.account_patch.empty_considered_exists()) && is_empty(nonce, balance, &code) {
self.accounts.insert(address, AccountChange::Nonexist(address));
} else {
self.accounts.insert(
address,
AccountChange::Create {
nonce,
address,
balance,
storage,
code,
},
);
}
}
AccountChange::Nonexist(address) => {
self.accounts.insert(address, AccountChange::Nonexist(address));
}
AccountChange::IncreaseBalance(address, balance) => {
if self.account_patch.allow_partial_change() {
self.accounts
.insert(address, AccountChange::IncreaseBalance(address, balance));
} else {
panic!()
}
}
}
}
pub fn used_addresses(&self) -> Set<Address> {
let mut set = Set::new();
for account in self.accounts() {
set.insert(account.address());
}
for address in self.codes.keys() {
set.insert(*address);
}
set
}
pub fn accounts(&self) -> map::Values<Address, AccountChange> {
self.accounts.values()
}
pub fn require(&self, address: Address) -> Result<(), RequireError> {
match self.accounts.get(&address) {
Some(&AccountChange::Full { .. })
| Some(&AccountChange::Create { .. })
| Some(&AccountChange::Nonexist(_)) => Ok(()),
_ => Err(RequireError::Account(address)),
}
}
pub fn require_code(&self, address: Address) -> Result<(), RequireError> {
if self.codes.contains_key(&address) {
Ok(())
} else {
match self.accounts.get(&address) {
Some(&AccountChange::Full { .. })
| Some(&AccountChange::Create { .. })
| Some(&AccountChange::Nonexist(_)) => Ok(()),
_ => Err(RequireError::AccountCode(address)),
}
}
}
pub fn require_storage(&self, address: Address, index: U256) -> Result<(), RequireError> {
self.storage_read(address, index).and_then(|_| Ok(()))
}
pub fn commit(&mut self, commitment: AccountCommitment) -> Result<(), CommitError> {
match commitment {
AccountCommitment::Full {
nonce,
address,
balance,
code,
} => {
let account = if self.accounts.contains_key(&address) {
match self.accounts.remove(&address).unwrap() {
AccountChange::Full { .. } | AccountChange::Create { .. } | AccountChange::Nonexist(_) => {
return Err(CommitError::AlreadyCommitted);
}
AccountChange::IncreaseBalance(address, topup) => AccountChange::Full {
nonce,
address,
balance: balance + topup,
changing_storage: Storage::new(address, true),
code,
},
}
} else {
AccountChange::Full {
nonce,
address,
balance,
changing_storage: Storage::new(address, true),
code,
}
};
self.insert_account(account);
self.codes.remove(&address);
}
AccountCommitment::Code { address, code } => {
if self.accounts.contains_key(&address) || self.codes.contains_key(&address) {
return Err(CommitError::AlreadyCommitted);
}
self.codes.insert(address, code);
}
AccountCommitment::Storage { address, index, value } => {
match self.accounts.get_mut(&address) {
Some(&mut AccountChange::Full {
ref mut changing_storage,
..
}) => {
changing_storage.commit(index, value)?;
}
_ => {
return Err(CommitError::InvalidCommitment);
}
}
self.orig_storage
.borrow_mut()
.entry(address)
.or_insert_with(|| Storage::new(address, true))
.commit(index, value)?
}
AccountCommitment::Nonexist(address) => {
let account = if self.accounts.contains_key(&address) {
match self.accounts.remove(&address).unwrap() {
AccountChange::Full { .. } | AccountChange::Create { .. } | AccountChange::Nonexist(_) => {
return Err(CommitError::AlreadyCommitted);
}
AccountChange::IncreaseBalance(address, topup) => AccountChange::Create {
nonce: self.account_patch.initial_nonce(),
address,
balance: topup,
storage: Storage::new(address, false),
code: Rc::new(Vec::new()),
},
}
} else {
AccountChange::Nonexist(address)
};
self.insert_account(account);
self.codes.remove(&address);
}
}
Ok(())
}
pub fn exists(&self, address: Address) -> Result<bool, RequireError> {
match self.accounts.get(&address) {
Some(&AccountChange::Create {
nonce,
balance,
ref code,
..
}) => Ok(if self.account_patch.empty_considered_exists() {
true
} else {
!is_empty(nonce, balance, code)
}),
Some(&AccountChange::Full {
nonce,
balance,
ref code,
..
}) => Ok(if self.account_patch.empty_considered_exists() {
true
} else {
!is_empty(nonce, balance, code)
}),
Some(&AccountChange::Nonexist(_)) => Ok(false),
Some(&AccountChange::IncreaseBalance(address, topup)) => {
if self.account_patch.empty_considered_exists() || topup > U256::zero() {
Ok(true)
} else {
Err(RequireError::Account(address))
}
}
_ => Err(RequireError::Account(address)),
}
}
pub fn code(&self, address: Address) -> Result<Rc<Vec<u8>>, RequireError> {
self.code_opt_nonexist(address)
.map(|opt_code| opt_code.unwrap_or_else(|| Rc::new(Vec::new())))
}
pub fn code_opt_nonexist(&self, address: Address) -> Result<Option<Rc<Vec<u8>>>, RequireError> {
if self.accounts.contains_key(&address) {
match self.accounts[&address] {
AccountChange::Full { ref code, .. } | AccountChange::Create { ref code, .. } => {
return Ok(Some(code.clone()));
}
AccountChange::Nonexist(_) => return Ok(None),
AccountChange::IncreaseBalance(_, _) => (),
}
}
if self.codes.contains_key(&address) {
Ok(Some(self.codes[&address].clone()))
} else {
Err(RequireError::AccountCode(address))
}
}
pub fn nonce(&self, address: Address) -> Result<U256, RequireError> {
if self.accounts.contains_key(&address) {
match self.accounts[&address] {
AccountChange::Full { nonce, .. } => return Ok(nonce),
AccountChange::Create { nonce, .. } => return Ok(nonce),
AccountChange::Nonexist(_) => {
return Ok(self.account_patch.initial_nonce());
}
_ => (),
}
}
Err(RequireError::Account(address))
}
pub fn balance(&self, address: Address) -> Result<U256, RequireError> {
if self.accounts.contains_key(&address) {
match self.accounts[&address] {
AccountChange::Full { balance, .. } => return Ok(balance),
AccountChange::Create { balance, .. } => return Ok(balance),
AccountChange::Nonexist(_) => {
return Ok(U256::zero());
}
_ => (),
}
}
Err(RequireError::Account(address))
}
pub fn storage_read(&self, address: Address, index: U256) -> Result<M256, RequireError> {
if self.accounts.contains_key(&address) {
match self.accounts[&address] {
AccountChange::Full {
ref changing_storage, ..
} => return changing_storage.read(index),
AccountChange::Create { ref storage, .. } => return storage.read(index),
AccountChange::Nonexist(_) => return Ok(M256::zero()),
_ => (),
}
}
Err(RequireError::Account(address))
}
pub fn storage_read_orig(&self, address: Address, index: U256) -> Result<M256, RequireError> {
let mut orig_storage = self.orig_storage.borrow_mut();
let orig_account_storage = orig_storage
.entry(address)
.or_insert_with(|| Storage::new(address, true));
orig_account_storage.read(index)
}
pub fn storage_write(&mut self, address: Address, index: U256, value: M256) -> Result<(), RequireError> {
if self.accounts.contains_key(&address) {
match self.accounts.get_mut(&address).unwrap() {
AccountChange::Full {
ref mut changing_storage,
..
} => return changing_storage.write(index, value),
AccountChange::Create { ref mut storage, .. } => return storage.write(index, value),
val => {
let is_nonexist = match val {
AccountChange::Nonexist(_) => true,
_ => false,
};
if is_nonexist {
let mut storage = Storage::new(address, false);
let ret = storage.write(index, value);
*val = AccountChange::Create {
nonce: self.account_patch.initial_nonce(),
address,
balance: U256::zero(),
storage,
code: Rc::new(Vec::new()),
};
return ret;
}
}
}
}
Err(RequireError::Account(address))
}
pub fn create(&mut self, address: Address, topup: U256) -> Result<(), RequireError> {
let account = if self.accounts.contains_key(&address) {
match self.accounts.remove(&address).unwrap() {
AccountChange::Full { balance, .. } => AccountChange::Create {
address,
code: Rc::new(Vec::new()),
nonce: self.account_patch.initial_create_nonce(),
balance: balance + topup,
storage: Storage::new(address, false),
},
AccountChange::Create { balance, .. } => AccountChange::Create {
address,
code: Rc::new(Vec::new()),
nonce: self.account_patch.initial_create_nonce(),
balance: balance + topup,
storage: Storage::new(address, false),
},
AccountChange::Nonexist(_) => AccountChange::Create {
address,
code: Rc::new(Vec::new()),
nonce: self.account_patch.initial_create_nonce(),
balance: topup,
storage: Storage::new(address, false),
},
_ => {
return Err(RequireError::Account(address));
}
}
} else {
return Err(RequireError::Account(address));
};
self.codes.remove(&address);
self.insert_account(account);
Ok(())
}
pub fn code_deposit(&mut self, address: Address, new_code: Rc<Vec<u8>>) {
match self.accounts.get_mut(&address).unwrap() {
AccountChange::Create { ref mut code, .. } => {
*code = new_code;
}
_ => panic!(),
}
}
pub fn increase_balance(&mut self, address: Address, topup: U256) {
let account = match self.accounts.remove(&address) {
Some(AccountChange::Full {
address,
balance,
changing_storage,
code,
nonce,
}) => AccountChange::Full {
address,
balance: balance + topup,
changing_storage,
code,
nonce,
},
Some(AccountChange::IncreaseBalance(address, balance)) => {
AccountChange::IncreaseBalance(address, balance + topup)
}
Some(AccountChange::Create {
address,
balance,
storage,
code,
nonce,
}) => AccountChange::Create {
address,
balance: balance + topup,
storage,
code,
nonce,
},
Some(AccountChange::Nonexist(address)) => AccountChange::Create {
nonce: self.account_patch.initial_nonce(),
address,
balance: topup,
storage: Storage::new(address, false),
code: Rc::new(Vec::new()),
},
None => AccountChange::IncreaseBalance(address, topup),
};
self.insert_account(account);
}
pub fn decrease_balance(&mut self, address: Address, withdraw: U256) {
let account = match self.accounts.remove(&address) {
Some(AccountChange::Full {
address,
balance,
changing_storage,
code,
nonce,
}) => AccountChange::Full {
address,
balance: balance - withdraw,
changing_storage,
code,
nonce,
},
Some(AccountChange::Create {
address,
balance,
storage,
code,
nonce,
}) => AccountChange::Create {
address,
balance: balance - withdraw,
storage,
code,
nonce,
},
Some(AccountChange::IncreaseBalance(_, _)) => panic!(),
Some(AccountChange::Nonexist(_)) => panic!(),
None => panic!(),
};
self.insert_account(account);
}
pub fn set_nonce(&mut self, address: Address, new_nonce: U256) -> Result<(), RequireError> {
match self.accounts.get_mut(&address) {
Some(&mut AccountChange::Full { ref mut nonce, .. }) => {
*nonce = new_nonce;
Ok(())
}
Some(&mut AccountChange::Create { ref mut nonce, .. }) => {
*nonce = new_nonce;
Ok(())
}
Some(val) => {
let is_nonexist = match val {
AccountChange::Nonexist(_) => true,
_ => false,
};
if is_nonexist {
*val = AccountChange::Create {
nonce: new_nonce,
address,
balance: U256::zero(),
storage: Storage::new(address, false),
code: Rc::new(Vec::new()),
};
Ok(())
} else {
Err(RequireError::Account(address))
}
}
None => Err(RequireError::Account(address)),
}
}
pub fn remove(&mut self, address: Address) -> Result<(), RequireError> {
self.codes.remove(&address);
self.insert_account(AccountChange::Nonexist(address));
Ok(())
}
}