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
) -> evm::Result<U256> where T: Tracer, V: VMTracer {
// backup used in case of running out of gas
self.state.snapshot();
self.state.checkpoint();
// at first, transfer value to destination
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);
if cost <= params.gas {
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
if self.depth == 0 {
@ -289,7 +289,7 @@ impl<'a> Executive<'a> {
Ok(params.gas - cost)
} else {
// 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());
@ -335,7 +335,7 @@ impl<'a> Executive<'a> {
res
} else {
// 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![]);
Ok(params.gas)
@ -354,7 +354,7 @@ impl<'a> Executive<'a> {
vm_tracer: &mut V
) -> evm::Result<U256> where T: Tracer, V: VMTracer {
// backup used in case of running out of gas
self.state.snapshot();
self.state.checkpoint();
// part of substate that may be reverted
let mut unconfirmed_substate = Substate::new();
@ -485,10 +485,10 @@ impl<'a> Executive<'a> {
| Err(evm::Error::BadInstruction {.. })
| Err(evm::Error::StackUnderflow {..})
| Err(evm::Error::OutOfStack {..}) => {
self.state.revert_to_snapshot();
self.state.revert_to_checkpoint();
},
Ok(_) | Err(evm::Error::Internal) => {
self.state.discard_snapshot();
self.state.discard_checkpoint();
substate.accrue(un_substate);
}
}

View File

@ -167,24 +167,24 @@ impl AccountEntry {
/// Upon destruction all the local cache data propagated into the global cache.
/// 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.
/// When a snapshot is active all changes are applied directly into
/// `cache` and the original value is copied into an active snapshot.
/// Reverting a snapshot with `revert_to_snapshot` involves copying
/// original values from the latest snapshot back into `cache`. The code
/// When a checkpoint is active all changes are applied directly into
/// `cache` and the original value is copied into an active checkpoint.
/// Reverting a checkpoint with `revert_to_checkpoint` involves copying
/// original values from the latest checkpoint back into `cache`. The code
/// takes care not to overwrite cached storage while doing that.
/// Snapshot can be discateded with `discard_snapshot`. All of the orignal
/// backed-up values are moved into a parent snapshot (if any).
/// checkpoint can be discateded with `discard_checkpoint`. All of the orignal
/// backed-up values are moved into a parent checkpoint (if any).
///
pub struct State {
db: StateDB,
root: H256,
cache: RefCell<HashMap<Address, AccountEntry>>,
// The original account is preserved in
snapshots: RefCell<Vec<HashMap<Address, Option<AccountEntry>>>>,
checkpoints: RefCell<Vec<HashMap<Address, Option<AccountEntry>>>>,
account_start_nonce: U256,
factories: Factories,
}
@ -213,7 +213,7 @@ impl State {
db: db,
root: root,
cache: RefCell::new(HashMap::new()),
snapshots: RefCell::new(Vec::new()),
checkpoints: RefCell::new(Vec::new()),
account_start_nonce: account_start_nonce,
factories: factories,
}
@ -229,7 +229,7 @@ impl State {
db: db,
root: root,
cache: RefCell::new(HashMap::new()),
snapshots: RefCell::new(Vec::new()),
checkpoints: RefCell::new(Vec::new()),
account_start_nonce: account_start_nonce,
factories: factories
};
@ -237,21 +237,21 @@ impl State {
Ok(state)
}
/// Create a recoverable snaphot of this state.
pub fn snapshot(&mut self) {
self.snapshots.get_mut().push(HashMap::new());
/// Create a recoverable checkpoint of this state.
pub fn checkpoint(&mut self) {
self.checkpoints.get_mut().push(HashMap::new());
}
/// Merge last snapshot with previous.
pub fn discard_snapshot(&mut self) {
// merge with previous snapshot
let last = self.snapshots.get_mut().pop();
if let Some(mut snapshot) = last {
if let Some(ref mut prev) = self.snapshots.get_mut().last_mut() {
/// Merge last checkpoint with previous.
pub fn discard_checkpoint(&mut self) {
// merge with previous checkpoint
let last = self.checkpoints.get_mut().pop();
if let Some(mut checkpoint) = last {
if let Some(ref mut prev) = self.checkpoints.get_mut().last_mut() {
if prev.is_empty() {
**prev = snapshot;
**prev = checkpoint;
} else {
for (k, v) in snapshot.drain() {
for (k, v) in checkpoint.drain() {
prev.entry(k).or_insert(v);
}
}
@ -259,15 +259,15 @@ impl State {
}
}
/// Revert to the last snapshot and discard it.
pub fn revert_to_snapshot(&mut self) {
if let Some(mut snapshot) = self.snapshots.get_mut().pop() {
for (k, v) in snapshot.drain() {
/// Revert to the last checkpoint and discard it.
pub fn revert_to_checkpoint(&mut self) {
if let Some(mut checkpoint) = self.checkpoints.get_mut().pop() {
for (k, v) in checkpoint.drain() {
match v {
Some(v) => {
match self.cache.get_mut().entry(k) {
Entry::Occupied(mut e) => {
// Merge snapshotted changes back into the main account
// Merge checkpointed changes back into the main account
// storage preserving the cache.
e.get_mut().overwrite_with(v);
},
@ -293,14 +293,14 @@ impl State {
fn insert_cache(&self, address: &Address, account: AccountEntry) {
// 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
// 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 let Some(ref mut snapshot) = self.snapshots.borrow_mut().last_mut() {
if !snapshot.contains_key(address) {
snapshot.insert(address.clone(), self.cache.borrow_mut().insert(address.clone(), account));
if let Some(ref mut checkpoint) = self.checkpoints.borrow_mut().last_mut() {
if !checkpoint.contains_key(address) {
checkpoint.insert(address.clone(), self.cache.borrow_mut().insert(address.clone(), account));
return;
}
}
@ -309,9 +309,9 @@ impl State {
}
fn note_cache(&self, address: &Address) {
if let Some(ref mut snapshot) = self.snapshots.borrow_mut().last_mut() {
if !snapshot.contains_key(address) {
snapshot.insert(address.clone(), self.cache.borrow().get(address).map(AccountEntry::clone_dirty));
if let Some(ref mut checkpoint) = self.checkpoints.borrow_mut().last_mut() {
if !checkpoint.contains_key(address) {
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.
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())
}
@ -561,7 +561,7 @@ impl State {
#[cfg(feature = "json-tests")]
/// Populate the state from `accounts`.
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() {
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.
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.
// will need fat db.
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(),
root: self.root.clone(),
cache: RefCell::new(cache),
snapshots: RefCell::new(Vec::new()),
checkpoints: RefCell::new(Vec::new()),
account_start_nonce: self.account_start_nonce.clone(),
factories: self.factories.clone(),
}
@ -1777,34 +1777,34 @@ fn ensure_cached() {
}
#[test]
fn snapshot_basic() {
fn checkpoint_basic() {
let mut state_result = get_temp_state();
let mut state = state_result.reference_mut();
let a = Address::zero();
state.snapshot();
state.checkpoint();
state.add_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));
state.snapshot();
state.checkpoint();
state.add_balance(&a, &U256::from(1u64));
assert_eq!(state.balance(&a), U256::from(70u64));
state.revert_to_snapshot();
state.revert_to_checkpoint();
assert_eq!(state.balance(&a), U256::from(69u64));
}
#[test]
fn snapshot_nested() {
fn checkpoint_nested() {
let mut state_result = get_temp_state();
let mut state = state_result.reference_mut();
let a = Address::zero();
state.snapshot();
state.snapshot();
state.checkpoint();
state.checkpoint();
state.add_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));
state.revert_to_snapshot();
state.revert_to_checkpoint();
assert_eq!(state.balance(&a), U256::from(0));
}