1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use std::collections::HashSet;
use ethereum_types::{U256, Address};
use log_entry::LogEntry;
use evm::{Schedule, CleanDustMode};
use super::CleanupMode;
#[derive(Debug, Default)]
pub struct Substate {
pub suicides: HashSet<Address>,
pub touched: HashSet<Address>,
pub logs: Vec<LogEntry>,
pub sstore_clears_count: U256,
pub contracts_created: Vec<Address>,
}
impl Substate {
pub fn new() -> Self {
Substate::default()
}
pub fn accrue(&mut self, s: Substate) {
self.suicides.extend(s.suicides);
self.touched.extend(s.touched);
self.logs.extend(s.logs);
self.sstore_clears_count = self.sstore_clears_count + s.sstore_clears_count;
self.contracts_created.extend(s.contracts_created);
}
pub fn to_cleanup_mode(&mut self, schedule: &Schedule) -> CleanupMode {
match (schedule.kill_dust != CleanDustMode::Off, schedule.no_empty, schedule.kill_empty) {
(false, false, _) => CleanupMode::ForceCreate,
(false, true, false) => CleanupMode::NoEmpty,
(false, true, true) | (true, _, _,) => CleanupMode::TrackTouched(&mut self.touched),
}
}
}
#[cfg(test)]
mod tests {
use super::Substate;
use log_entry::LogEntry;
#[test]
fn created() {
let sub_state = Substate::new();
assert_eq!(sub_state.suicides.len(), 0);
}
#[test]
fn accrue() {
let mut sub_state = Substate::new();
sub_state.contracts_created.push(1u64.into());
sub_state.logs.push(LogEntry {
address: 1u64.into(),
topics: vec![],
data: vec![]
});
sub_state.sstore_clears_count = 5.into();
sub_state.suicides.insert(10u64.into());
let mut sub_state_2 = Substate::new();
sub_state_2.contracts_created.push(2u64.into());
sub_state_2.logs.push(LogEntry {
address: 1u64.into(),
topics: vec![],
data: vec![]
});
sub_state_2.sstore_clears_count = 7.into();
sub_state.accrue(sub_state_2);
assert_eq!(sub_state.contracts_created.len(), 2);
assert_eq!(sub_state.sstore_clears_count, 12.into());
assert_eq!(sub_state.suicides.len(), 1);
}
}