rename State::snapshot to checkpoint to avoid confusion (#2796)
This commit is contained in:
parent
3ff1ca81f4
commit
8e5c9ff162
@ -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(¶ms.code_address, data);
|
||||
if cost <= params.gas {
|
||||
self.engine.execute_builtin(¶ms.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);
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user