mitigate refcell conflict in state diffing (#2601)
* mitigate refcell conflict in state diffing Also uses RefCell::get_mut in a few places. * Add test case
This commit is contained in:
parent
4bcc9e3b49
commit
4581469e78
@ -239,15 +239,15 @@ impl State {
|
|||||||
|
|
||||||
/// Create a recoverable snaphot of this state.
|
/// Create a recoverable snaphot of this state.
|
||||||
pub fn snapshot(&mut self) {
|
pub fn snapshot(&mut self) {
|
||||||
self.snapshots.borrow_mut().push(HashMap::new());
|
self.snapshots.get_mut().push(HashMap::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Merge last snapshot with previous.
|
/// Merge last snapshot with previous.
|
||||||
pub fn discard_snapshot(&mut self) {
|
pub fn discard_snapshot(&mut self) {
|
||||||
// merge with previous snapshot
|
// merge with previous snapshot
|
||||||
let last = self.snapshots.borrow_mut().pop();
|
let last = self.snapshots.get_mut().pop();
|
||||||
if let Some(mut snapshot) = last {
|
if let Some(mut snapshot) = last {
|
||||||
if let Some(ref mut prev) = self.snapshots.borrow_mut().last_mut() {
|
if let Some(ref mut prev) = self.snapshots.get_mut().last_mut() {
|
||||||
if prev.is_empty() {
|
if prev.is_empty() {
|
||||||
**prev = snapshot;
|
**prev = snapshot;
|
||||||
} else {
|
} else {
|
||||||
@ -261,11 +261,11 @@ impl State {
|
|||||||
|
|
||||||
/// Revert to the last snapshot and discard it.
|
/// Revert to the last snapshot and discard it.
|
||||||
pub fn revert_to_snapshot(&mut self) {
|
pub fn revert_to_snapshot(&mut self) {
|
||||||
if let Some(mut snapshot) = self.snapshots.borrow_mut().pop() {
|
if let Some(mut snapshot) = self.snapshots.get_mut().pop() {
|
||||||
for (k, v) in snapshot.drain() {
|
for (k, v) in snapshot.drain() {
|
||||||
match v {
|
match v {
|
||||||
Some(v) => {
|
Some(v) => {
|
||||||
match self.cache.borrow_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 snapshotted changes back into the main account
|
||||||
// storage preserving the cache.
|
// storage preserving the cache.
|
||||||
@ -277,7 +277,7 @@ impl State {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
match self.cache.borrow_mut().entry(k) {
|
match self.cache.get_mut().entry(k) {
|
||||||
Entry::Occupied(e) => {
|
Entry::Occupied(e) => {
|
||||||
if e.get().is_dirty() {
|
if e.get().is_dirty() {
|
||||||
e.remove();
|
e.remove();
|
||||||
@ -578,14 +578,14 @@ impl State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn query_pod(&mut self, query: &PodState) {
|
fn query_pod(&mut self, query: &PodState) {
|
||||||
for (address, pod_account) in query.get() {
|
for (address, pod_account) in query.get().into_iter()
|
||||||
self.ensure_cached(address, RequireCache::Code, |a| {
|
.filter(|&(ref a, _)| self.ensure_cached(a, RequireCache::Code, |a| a.is_some()))
|
||||||
if a.is_some() {
|
{
|
||||||
for key in pod_account.storage.keys() {
|
// needs to be split into two parts for the refcell code here
|
||||||
self.storage_at(address, key);
|
// to work.
|
||||||
}
|
for key in pod_account.storage.keys() {
|
||||||
}
|
self.storage_at(address, key);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1797,4 +1797,20 @@ fn create_empty() {
|
|||||||
assert_eq!(state.root().hex(), "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421");
|
assert_eq!(state.root().hex(), "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_not_panic_on_state_diff_with_storage() {
|
||||||
|
let state = get_temp_state();
|
||||||
|
let mut state = state.reference().clone();
|
||||||
|
|
||||||
|
let a: Address = 0xa.into();
|
||||||
|
state.init_code(&a, b"abcdefg".to_vec());
|
||||||
|
state.add_balance(&a, &256.into());
|
||||||
|
state.set_storage(&a, 0xb.into(), 0xc.into());
|
||||||
|
|
||||||
|
let mut new_state = state.clone();
|
||||||
|
new_state.set_storage(&a, 0xb.into(), 0xd.into());
|
||||||
|
|
||||||
|
new_state.diff_from(state);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user