rename State::snapshot to checkpoint to avoid confusion (#2796)

This commit is contained in:
Robert Habermeier 2016-10-22 15:22:16 +02:00 committed by Gav Wood
parent 3ff1ca81f4
commit 8e5c9ff162
2 changed files with 56 additions and 56 deletions

View File

@ -250,7 +250,7 @@ impl<'a> Executive<'a> {
vm_tracer: &mut V vm_tracer: &mut V
) -> evm::Result<U256> where T: Tracer, V: VMTracer { ) -> evm::Result<U256> where T: Tracer, V: VMTracer {
// backup used in case of running out of gas // backup used in case of running out of gas
self.state.snapshot(); self.state.checkpoint();
// at first, transfer value to destination // at first, transfer value to destination
if let ActionValue::Transfer(val) = params.value { if let ActionValue::Transfer(val) = params.value {
@ -269,7 +269,7 @@ impl<'a> Executive<'a> {
let cost = self.engine.cost_of_builtin(&params.code_address, data); let cost = self.engine.cost_of_builtin(&params.code_address, data);
if cost <= params.gas { if cost <= params.gas {
self.engine.execute_builtin(&params.code_address, data, &mut output); self.engine.execute_builtin(&params.code_address, data, &mut output);
self.state.discard_snapshot(); self.state.discard_checkpoint();
// trace only top level calls to builtins to avoid DDoS attacks // trace only top level calls to builtins to avoid DDoS attacks
if self.depth == 0 { if self.depth == 0 {
@ -289,7 +289,7 @@ impl<'a> Executive<'a> {
Ok(params.gas - cost) Ok(params.gas - cost)
} else { } else {
// just drain the whole gas // just drain the whole gas
self.state.revert_to_snapshot(); self.state.revert_to_checkpoint();
tracer.trace_failed_call(trace_info, vec![], evm::Error::OutOfGas.into()); tracer.trace_failed_call(trace_info, vec![], evm::Error::OutOfGas.into());
@ -335,7 +335,7 @@ impl<'a> Executive<'a> {
res res
} else { } else {
// otherwise it's just a basic transaction, only do tracing, if necessary. // otherwise it's just a basic transaction, only do tracing, if necessary.
self.state.discard_snapshot(); self.state.discard_checkpoint();
tracer.trace_call(trace_info, U256::zero(), trace_output, vec![]); tracer.trace_call(trace_info, U256::zero(), trace_output, vec![]);
Ok(params.gas) Ok(params.gas)
@ -354,7 +354,7 @@ impl<'a> Executive<'a> {
vm_tracer: &mut V vm_tracer: &mut V
) -> evm::Result<U256> where T: Tracer, V: VMTracer { ) -> evm::Result<U256> where T: Tracer, V: VMTracer {
// backup used in case of running out of gas // backup used in case of running out of gas
self.state.snapshot(); self.state.checkpoint();
// part of substate that may be reverted // part of substate that may be reverted
let mut unconfirmed_substate = Substate::new(); let mut unconfirmed_substate = Substate::new();
@ -485,10 +485,10 @@ impl<'a> Executive<'a> {
| Err(evm::Error::BadInstruction {.. }) | Err(evm::Error::BadInstruction {.. })
| Err(evm::Error::StackUnderflow {..}) | Err(evm::Error::StackUnderflow {..})
| Err(evm::Error::OutOfStack {..}) => { | Err(evm::Error::OutOfStack {..}) => {
self.state.revert_to_snapshot(); self.state.revert_to_checkpoint();
}, },
Ok(_) | Err(evm::Error::Internal) => { Ok(_) | Err(evm::Error::Internal) => {
self.state.discard_snapshot(); self.state.discard_checkpoint();
substate.accrue(un_substate); substate.accrue(un_substate);
} }
} }

View File

@ -167,24 +167,24 @@ impl AccountEntry {
/// Upon destruction all the local cache data propagated into the global cache. /// Upon destruction all the local cache data propagated into the global cache.
/// Propagated items might be rejected if current state is non-canonical. /// Propagated items might be rejected if current state is non-canonical.
/// ///
/// State snapshotting. /// State checkpointing.
/// ///
/// A new snapshot can be created with `snapshot()`. Snapshots can be /// A new checkpoint can be created with `checkpoint()`. checkpoints can be
/// created in a hierarchy. /// created in a hierarchy.
/// When a snapshot is active all changes are applied directly into /// When a checkpoint is active all changes are applied directly into
/// `cache` and the original value is copied into an active snapshot. /// `cache` and the original value is copied into an active checkpoint.
/// Reverting a snapshot with `revert_to_snapshot` involves copying /// Reverting a checkpoint with `revert_to_checkpoint` involves copying
/// original values from the latest snapshot back into `cache`. The code /// original values from the latest checkpoint back into `cache`. The code
/// takes care not to overwrite cached storage while doing that. /// takes care not to overwrite cached storage while doing that.
/// Snapshot can be discateded with `discard_snapshot`. All of the orignal /// checkpoint can be discateded with `discard_checkpoint`. All of the orignal
/// backed-up values are moved into a parent snapshot (if any). /// backed-up values are moved into a parent checkpoint (if any).
/// ///
pub struct State { pub struct State {
db: StateDB, db: StateDB,
root: H256, root: H256,
cache: RefCell<HashMap<Address, AccountEntry>>, cache: RefCell<HashMap<Address, AccountEntry>>,
// The original account is preserved in // The original account is preserved in
snapshots: RefCell<Vec<HashMap<Address, Option<AccountEntry>>>>, checkpoints: RefCell<Vec<HashMap<Address, Option<AccountEntry>>>>,
account_start_nonce: U256, account_start_nonce: U256,
factories: Factories, factories: Factories,
} }
@ -213,7 +213,7 @@ impl State {
db: db, db: db,
root: root, root: root,
cache: RefCell::new(HashMap::new()), cache: RefCell::new(HashMap::new()),
snapshots: RefCell::new(Vec::new()), checkpoints: RefCell::new(Vec::new()),
account_start_nonce: account_start_nonce, account_start_nonce: account_start_nonce,
factories: factories, factories: factories,
} }
@ -229,7 +229,7 @@ impl State {
db: db, db: db,
root: root, root: root,
cache: RefCell::new(HashMap::new()), cache: RefCell::new(HashMap::new()),
snapshots: RefCell::new(Vec::new()), checkpoints: RefCell::new(Vec::new()),
account_start_nonce: account_start_nonce, account_start_nonce: account_start_nonce,
factories: factories factories: factories
}; };
@ -237,21 +237,21 @@ impl State {
Ok(state) Ok(state)
} }
/// Create a recoverable snaphot of this state. /// Create a recoverable checkpoint of this state.
pub fn snapshot(&mut self) { pub fn checkpoint(&mut self) {
self.snapshots.get_mut().push(HashMap::new()); self.checkpoints.get_mut().push(HashMap::new());
} }
/// Merge last snapshot with previous. /// Merge last checkpoint with previous.
pub fn discard_snapshot(&mut self) { pub fn discard_checkpoint(&mut self) {
// merge with previous snapshot // merge with previous checkpoint
let last = self.snapshots.get_mut().pop(); let last = self.checkpoints.get_mut().pop();
if let Some(mut snapshot) = last { if let Some(mut checkpoint) = last {
if let Some(ref mut prev) = self.snapshots.get_mut().last_mut() { if let Some(ref mut prev) = self.checkpoints.get_mut().last_mut() {
if prev.is_empty() { if prev.is_empty() {
**prev = snapshot; **prev = checkpoint;
} else { } else {
for (k, v) in snapshot.drain() { for (k, v) in checkpoint.drain() {
prev.entry(k).or_insert(v); prev.entry(k).or_insert(v);
} }
} }
@ -259,15 +259,15 @@ impl State {
} }
} }
/// Revert to the last snapshot and discard it. /// Revert to the last checkpoint and discard it.
pub fn revert_to_snapshot(&mut self) { pub fn revert_to_checkpoint(&mut self) {
if let Some(mut snapshot) = self.snapshots.get_mut().pop() { if let Some(mut checkpoint) = self.checkpoints.get_mut().pop() {
for (k, v) in snapshot.drain() { for (k, v) in checkpoint.drain() {
match v { match v {
Some(v) => { Some(v) => {
match self.cache.get_mut().entry(k) { match self.cache.get_mut().entry(k) {
Entry::Occupied(mut e) => { Entry::Occupied(mut e) => {
// Merge snapshotted changes back into the main account // Merge checkpointed changes back into the main account
// storage preserving the cache. // storage preserving the cache.
e.get_mut().overwrite_with(v); e.get_mut().overwrite_with(v);
}, },
@ -293,14 +293,14 @@ impl State {
fn insert_cache(&self, address: &Address, account: AccountEntry) { fn insert_cache(&self, address: &Address, account: AccountEntry) {
// Dirty account which is not in the cache means this is a new account. // Dirty account which is not in the cache means this is a new account.
// It goes directly into the snapshot as there's nothing to rever to. // It goes directly into the checkpoint as there's nothing to rever to.
// //
// In all other cases account is read as clean first, and after that made // In all other cases account is read as clean first, and after that made
// dirty in and added to the snapshot with `note_cache`. // dirty in and added to the checkpoint with `note_cache`.
if account.is_dirty() { if account.is_dirty() {
if let Some(ref mut snapshot) = self.snapshots.borrow_mut().last_mut() { if let Some(ref mut checkpoint) = self.checkpoints.borrow_mut().last_mut() {
if !snapshot.contains_key(address) { if !checkpoint.contains_key(address) {
snapshot.insert(address.clone(), self.cache.borrow_mut().insert(address.clone(), account)); checkpoint.insert(address.clone(), self.cache.borrow_mut().insert(address.clone(), account));
return; return;
} }
} }
@ -309,9 +309,9 @@ impl State {
} }
fn note_cache(&self, address: &Address) { fn note_cache(&self, address: &Address) {
if let Some(ref mut snapshot) = self.snapshots.borrow_mut().last_mut() { if let Some(ref mut checkpoint) = self.checkpoints.borrow_mut().last_mut() {
if !snapshot.contains_key(address) { if !checkpoint.contains_key(address) {
snapshot.insert(address.clone(), self.cache.borrow().get(address).map(AccountEntry::clone_dirty)); checkpoint.insert(address.clone(), self.cache.borrow().get(address).map(AccountEntry::clone_dirty));
} }
} }
} }
@ -548,7 +548,7 @@ impl State {
/// Commits our cached account changes into the trie. /// Commits our cached account changes into the trie.
pub fn commit(&mut self) -> Result<(), Error> { pub fn commit(&mut self) -> Result<(), Error> {
assert!(self.snapshots.borrow().is_empty()); assert!(self.checkpoints.borrow().is_empty());
Self::commit_into(&self.factories, &mut self.db, &mut self.root, &mut *self.cache.borrow_mut()) Self::commit_into(&self.factories, &mut self.db, &mut self.root, &mut *self.cache.borrow_mut())
} }
@ -561,7 +561,7 @@ impl State {
#[cfg(feature = "json-tests")] #[cfg(feature = "json-tests")]
/// Populate the state from `accounts`. /// Populate the state from `accounts`.
pub fn populate_from(&mut self, accounts: PodState) { pub fn populate_from(&mut self, accounts: PodState) {
assert!(self.snapshots.borrow().is_empty()); assert!(self.checkpoints.borrow().is_empty());
for (add, acc) in accounts.drain().into_iter() { for (add, acc) in accounts.drain().into_iter() {
self.cache.borrow_mut().insert(add, AccountEntry::new_dirty(Some(Account::from_pod(acc)))); self.cache.borrow_mut().insert(add, AccountEntry::new_dirty(Some(Account::from_pod(acc))));
} }
@ -569,7 +569,7 @@ impl State {
/// Populate a PodAccount map from this state. /// Populate a PodAccount map from this state.
pub fn to_pod(&self) -> PodState { pub fn to_pod(&self) -> PodState {
assert!(self.snapshots.borrow().is_empty()); assert!(self.checkpoints.borrow().is_empty());
// TODO: handle database rather than just the cache. // TODO: handle database rather than just the cache.
// will need fat db. // will need fat db.
PodState::from(self.cache.borrow().iter().fold(BTreeMap::new(), |mut m, (add, opt)| { PodState::from(self.cache.borrow().iter().fold(BTreeMap::new(), |mut m, (add, opt)| {
@ -739,7 +739,7 @@ impl Clone for State {
db: self.db.boxed_clone(), db: self.db.boxed_clone(),
root: self.root.clone(), root: self.root.clone(),
cache: RefCell::new(cache), cache: RefCell::new(cache),
snapshots: RefCell::new(Vec::new()), checkpoints: RefCell::new(Vec::new()),
account_start_nonce: self.account_start_nonce.clone(), account_start_nonce: self.account_start_nonce.clone(),
factories: self.factories.clone(), factories: self.factories.clone(),
} }
@ -1777,34 +1777,34 @@ fn ensure_cached() {
} }
#[test] #[test]
fn snapshot_basic() { fn checkpoint_basic() {
let mut state_result = get_temp_state(); let mut state_result = get_temp_state();
let mut state = state_result.reference_mut(); let mut state = state_result.reference_mut();
let a = Address::zero(); let a = Address::zero();
state.snapshot(); state.checkpoint();
state.add_balance(&a, &U256::from(69u64)); state.add_balance(&a, &U256::from(69u64));
assert_eq!(state.balance(&a), U256::from(69u64)); assert_eq!(state.balance(&a), U256::from(69u64));
state.discard_snapshot(); state.discard_checkpoint();
assert_eq!(state.balance(&a), U256::from(69u64)); assert_eq!(state.balance(&a), U256::from(69u64));
state.snapshot(); state.checkpoint();
state.add_balance(&a, &U256::from(1u64)); state.add_balance(&a, &U256::from(1u64));
assert_eq!(state.balance(&a), U256::from(70u64)); assert_eq!(state.balance(&a), U256::from(70u64));
state.revert_to_snapshot(); state.revert_to_checkpoint();
assert_eq!(state.balance(&a), U256::from(69u64)); assert_eq!(state.balance(&a), U256::from(69u64));
} }
#[test] #[test]
fn snapshot_nested() { fn checkpoint_nested() {
let mut state_result = get_temp_state(); let mut state_result = get_temp_state();
let mut state = state_result.reference_mut(); let mut state = state_result.reference_mut();
let a = Address::zero(); let a = Address::zero();
state.snapshot(); state.checkpoint();
state.snapshot(); state.checkpoint();
state.add_balance(&a, &U256::from(69u64)); state.add_balance(&a, &U256::from(69u64));
assert_eq!(state.balance(&a), U256::from(69u64)); assert_eq!(state.balance(&a), U256::from(69u64));
state.discard_snapshot(); state.discard_checkpoint();
assert_eq!(state.balance(&a), U256::from(69u64)); assert_eq!(state.balance(&a), U256::from(69u64));
state.revert_to_snapshot(); state.revert_to_checkpoint();
assert_eq!(state.balance(&a), U256::from(0)); assert_eq!(state.balance(&a), U256::from(0));
} }