@@ -15,27 +15,8 @@ pub enum AccountStatus {
15
15
}
16
16
17
17
impl AccountStatus {
18
- /// Transition to other state while preserving invariance of this state.
19
- ///
20
- /// It this account was Destroyed and other account is not:
21
- /// we should mark extended account as destroyed too.
22
- /// and as other account had some changes, extended account
23
- /// should be marked as DestroyedChanged.
24
- ///
25
- /// If both account are not destroyed and if this account is in memory:
26
- /// this means that extended account is in memory too.
27
- ///
28
- /// Otherwise, if both are destroyed or other is destroyed:
29
- /// set other status to extended account.
30
- pub fn transition ( & mut self , other : Self ) {
31
- * self = match ( self . was_destroyed ( ) , other. was_destroyed ( ) ) {
32
- ( true , false ) => Self :: DestroyedChanged ,
33
- ( false , false ) if * self == Self :: InMemoryChange => Self :: InMemoryChange ,
34
- _ => other,
35
- } ;
36
- }
37
18
/// Account is not modified and just loaded from database.
38
- pub fn not_modified ( & self ) -> bool {
19
+ pub fn is_not_modified ( & self ) -> bool {
39
20
matches ! (
40
21
self ,
41
22
AccountStatus :: LoadedNotExisting
@@ -46,7 +27,7 @@ impl AccountStatus {
46
27
47
28
/// Account was destroyed by calling SELFDESTRUCT.
48
29
/// This means that full account and storage are inside memory.
49
- pub fn was_destroyed ( & self ) -> bool {
30
+ pub fn is_destroyed ( & self ) -> bool {
50
31
matches ! (
51
32
self ,
52
33
AccountStatus :: Destroyed
@@ -56,7 +37,7 @@ impl AccountStatus {
56
37
}
57
38
58
39
/// This means storage is known, it can be newly created or storage got destroyed.
59
- pub fn storage_known ( & self ) -> bool {
40
+ pub fn is_storage_known ( & self ) -> bool {
60
41
matches ! (
61
42
self ,
62
43
AccountStatus :: LoadedNotExisting
@@ -70,9 +51,153 @@ impl AccountStatus {
70
51
/// Account is modified but not destroyed.
71
52
/// This means that some storage values can be found in both
72
53
/// memory and database.
73
- pub fn modified_but_not_destroyed ( & self ) -> bool {
54
+ pub fn is_modified_and_not_destroyed ( & self ) -> bool {
74
55
matches ! ( self , AccountStatus :: Changed | AccountStatus :: InMemoryChange )
75
56
}
57
+
58
+ /// Returns the next account status on creation.
59
+ pub fn on_created ( & self ) -> AccountStatus {
60
+ match self {
61
+ // if account was destroyed previously just copy new info to it.
62
+ AccountStatus :: DestroyedAgain
63
+ | AccountStatus :: Destroyed
64
+ | AccountStatus :: DestroyedChanged => AccountStatus :: DestroyedChanged ,
65
+ // if account is loaded from db.
66
+ AccountStatus :: LoadedNotExisting
67
+ // Loaded empty eip161 to creates is not possible as CREATE2 was added after EIP-161
68
+ | AccountStatus :: LoadedEmptyEIP161
69
+ | AccountStatus :: Loaded
70
+ | AccountStatus :: Changed
71
+ | AccountStatus :: InMemoryChange => {
72
+ // If account is loaded and not empty this means that account has some balance.
73
+ // This means that account cannot be created.
74
+ // We are assuming that EVM did necessary checks before allowing account to be created.
75
+ AccountStatus :: InMemoryChange
76
+ }
77
+ }
78
+ }
79
+
80
+ /// Returns the next account status on touched empty account post state clear EIP (EIP-161).
81
+ ///
82
+ /// # Panics
83
+ ///
84
+ /// If current status is [AccountStatus::Loaded] or [AccountStatus::Changed].
85
+ pub fn on_touched_empty_post_eip161 ( & self ) -> AccountStatus {
86
+ match self {
87
+ // Account can be touched but not existing. The status should remain the same.
88
+ AccountStatus :: LoadedNotExisting => AccountStatus :: LoadedNotExisting ,
89
+ // Account can be created empty and only then touched.
90
+ AccountStatus :: InMemoryChange
91
+ | AccountStatus :: Destroyed
92
+ | AccountStatus :: LoadedEmptyEIP161 => AccountStatus :: Destroyed ,
93
+ // Transition to destroy the account.
94
+ AccountStatus :: DestroyedAgain | AccountStatus :: DestroyedChanged => {
95
+ AccountStatus :: DestroyedAgain
96
+ }
97
+ // Account statuses considered unreachable.
98
+ AccountStatus :: Loaded | AccountStatus :: Changed => {
99
+ unreachable ! ( "Wrong state transition, touch empty is not possible from {self:?}" ) ;
100
+ }
101
+ }
102
+ }
103
+
104
+ /// Returns the next account status on touched or created account pre state clear EIP (EIP-161).
105
+ /// Returns `None` if the account status didn't change.
106
+ ///
107
+ /// # Panics
108
+ ///
109
+ /// If current status is [AccountStatus::Loaded] or [AccountStatus::Changed].
110
+ pub fn on_touched_created_pre_eip161 ( & self , had_no_info : bool ) -> Option < AccountStatus > {
111
+ match self {
112
+ AccountStatus :: LoadedEmptyEIP161 => None ,
113
+ AccountStatus :: DestroyedChanged => {
114
+ if had_no_info {
115
+ None
116
+ } else {
117
+ Some ( AccountStatus :: DestroyedChanged )
118
+ }
119
+ }
120
+ AccountStatus :: Destroyed | AccountStatus :: DestroyedAgain => {
121
+ Some ( AccountStatus :: DestroyedChanged )
122
+ }
123
+ AccountStatus :: InMemoryChange | AccountStatus :: LoadedNotExisting => {
124
+ Some ( AccountStatus :: InMemoryChange )
125
+ }
126
+ AccountStatus :: Loaded | AccountStatus :: Changed => {
127
+ unreachable ! ( "Wrong state transition, touch crate is not possible from {self:?}" )
128
+ }
129
+ }
130
+ }
131
+
132
+ /// Returns the next account status on change.
133
+ pub fn on_changed ( & self , had_no_nonce_and_code : bool ) -> AccountStatus {
134
+ match self {
135
+ // If the account was loaded as not existing, promote it to changed.
136
+ // This account was likely created by a balance transfer.
137
+ AccountStatus :: LoadedNotExisting => AccountStatus :: InMemoryChange ,
138
+ // Change on empty account, should transfer storage if there is any.
139
+ // There is possibility that there are storage entries inside db.
140
+ // That storage is used in merkle tree calculation before state clear EIP.
141
+ AccountStatus :: LoadedEmptyEIP161 => AccountStatus :: InMemoryChange ,
142
+ // The account was loaded as existing.
143
+ AccountStatus :: Loaded => {
144
+ if had_no_nonce_and_code {
145
+ // account is fully in memory
146
+ AccountStatus :: InMemoryChange
147
+ } else {
148
+ // can be contract and some of storage slots can be present inside db.
149
+ AccountStatus :: Changed
150
+ }
151
+ }
152
+
153
+ // On change, the "changed" type account statuses are preserved.
154
+ // Any checks for empty accounts are done outside of this fn.
155
+ AccountStatus :: Changed => AccountStatus :: Changed ,
156
+ AccountStatus :: InMemoryChange => AccountStatus :: InMemoryChange ,
157
+ AccountStatus :: DestroyedChanged => AccountStatus :: DestroyedChanged ,
158
+
159
+ // If account is destroyed and then changed this means this is
160
+ // balance transfer.
161
+ AccountStatus :: Destroyed | AccountStatus :: DestroyedAgain => {
162
+ AccountStatus :: DestroyedChanged
163
+ }
164
+ }
165
+ }
166
+
167
+ /// Returns the next account status on selfdestruct.
168
+ pub fn on_selfdestructed ( & self ) -> AccountStatus {
169
+ match self {
170
+ // If account is created and selfdestructed in the same block, mark it as destroyed again.
171
+ // Note: there is no big difference between Destroyed and DestroyedAgain in this case,
172
+ // but was added for clarity.
173
+ AccountStatus :: DestroyedChanged
174
+ | AccountStatus :: DestroyedAgain
175
+ | AccountStatus :: Destroyed => AccountStatus :: DestroyedAgain ,
176
+
177
+ // Transition to destroyed status.
178
+ _ => AccountStatus :: Destroyed ,
179
+ }
180
+ }
181
+
182
+ /// Transition to other state while preserving invariance of this state.
183
+ ///
184
+ /// It this account was Destroyed and other account is not:
185
+ /// we should mark extended account as destroyed too.
186
+ /// and as other account had some changes, extended account
187
+ /// should be marked as DestroyedChanged.
188
+ ///
189
+ /// If both account are not destroyed and if this account is in memory:
190
+ /// this means that extended account is in memory too.
191
+ ///
192
+ /// Otherwise, if both are destroyed or other is destroyed:
193
+ /// set other status to extended account.
194
+ pub fn transition ( & mut self , other : Self ) {
195
+ * self = match ( self . is_destroyed ( ) , other. is_destroyed ( ) ) {
196
+ ( true , false ) => Self :: DestroyedChanged ,
197
+ ( false , false ) if * self == Self :: InMemoryChange => Self :: InMemoryChange ,
198
+ _ => other,
199
+ } ;
200
+ }
76
201
}
77
202
78
203
#[ cfg( test) ]
@@ -83,43 +208,43 @@ mod test {
83
208
#[ test]
84
209
fn test_account_status ( ) {
85
210
// account not modified
86
- assert ! ( AccountStatus :: Loaded . not_modified ( ) ) ;
87
- assert ! ( AccountStatus :: LoadedEmptyEIP161 . not_modified ( ) ) ;
88
- assert ! ( AccountStatus :: LoadedNotExisting . not_modified ( ) ) ;
89
- assert ! ( !AccountStatus :: Changed . not_modified ( ) ) ;
90
- assert ! ( !AccountStatus :: InMemoryChange . not_modified ( ) ) ;
91
- assert ! ( !AccountStatus :: Destroyed . not_modified ( ) ) ;
92
- assert ! ( !AccountStatus :: DestroyedChanged . not_modified ( ) ) ;
93
- assert ! ( !AccountStatus :: DestroyedAgain . not_modified ( ) ) ;
211
+ assert ! ( AccountStatus :: Loaded . is_not_modified ( ) ) ;
212
+ assert ! ( AccountStatus :: LoadedEmptyEIP161 . is_not_modified ( ) ) ;
213
+ assert ! ( AccountStatus :: LoadedNotExisting . is_not_modified ( ) ) ;
214
+ assert ! ( !AccountStatus :: Changed . is_not_modified ( ) ) ;
215
+ assert ! ( !AccountStatus :: InMemoryChange . is_not_modified ( ) ) ;
216
+ assert ! ( !AccountStatus :: Destroyed . is_not_modified ( ) ) ;
217
+ assert ! ( !AccountStatus :: DestroyedChanged . is_not_modified ( ) ) ;
218
+ assert ! ( !AccountStatus :: DestroyedAgain . is_not_modified ( ) ) ;
94
219
95
220
// we know full storage
96
- assert ! ( !AccountStatus :: LoadedEmptyEIP161 . storage_known ( ) ) ;
97
- assert ! ( AccountStatus :: LoadedNotExisting . storage_known ( ) ) ;
98
- assert ! ( AccountStatus :: InMemoryChange . storage_known ( ) ) ;
99
- assert ! ( AccountStatus :: Destroyed . storage_known ( ) ) ;
100
- assert ! ( AccountStatus :: DestroyedChanged . storage_known ( ) ) ;
101
- assert ! ( AccountStatus :: DestroyedAgain . storage_known ( ) ) ;
102
- assert ! ( !AccountStatus :: Loaded . storage_known ( ) ) ;
103
- assert ! ( !AccountStatus :: Changed . storage_known ( ) ) ;
221
+ assert ! ( !AccountStatus :: LoadedEmptyEIP161 . is_storage_known ( ) ) ;
222
+ assert ! ( AccountStatus :: LoadedNotExisting . is_storage_known ( ) ) ;
223
+ assert ! ( AccountStatus :: InMemoryChange . is_storage_known ( ) ) ;
224
+ assert ! ( AccountStatus :: Destroyed . is_storage_known ( ) ) ;
225
+ assert ! ( AccountStatus :: DestroyedChanged . is_storage_known ( ) ) ;
226
+ assert ! ( AccountStatus :: DestroyedAgain . is_storage_known ( ) ) ;
227
+ assert ! ( !AccountStatus :: Loaded . is_storage_known ( ) ) ;
228
+ assert ! ( !AccountStatus :: Changed . is_storage_known ( ) ) ;
104
229
105
230
// account was destroyed
106
- assert ! ( !AccountStatus :: LoadedEmptyEIP161 . was_destroyed ( ) ) ;
107
- assert ! ( !AccountStatus :: LoadedNotExisting . was_destroyed ( ) ) ;
108
- assert ! ( !AccountStatus :: InMemoryChange . was_destroyed ( ) ) ;
109
- assert ! ( AccountStatus :: Destroyed . was_destroyed ( ) ) ;
110
- assert ! ( AccountStatus :: DestroyedChanged . was_destroyed ( ) ) ;
111
- assert ! ( AccountStatus :: DestroyedAgain . was_destroyed ( ) ) ;
112
- assert ! ( !AccountStatus :: Loaded . was_destroyed ( ) ) ;
113
- assert ! ( !AccountStatus :: Changed . was_destroyed ( ) ) ;
231
+ assert ! ( !AccountStatus :: LoadedEmptyEIP161 . is_destroyed ( ) ) ;
232
+ assert ! ( !AccountStatus :: LoadedNotExisting . is_destroyed ( ) ) ;
233
+ assert ! ( !AccountStatus :: InMemoryChange . is_destroyed ( ) ) ;
234
+ assert ! ( AccountStatus :: Destroyed . is_destroyed ( ) ) ;
235
+ assert ! ( AccountStatus :: DestroyedChanged . is_destroyed ( ) ) ;
236
+ assert ! ( AccountStatus :: DestroyedAgain . is_destroyed ( ) ) ;
237
+ assert ! ( !AccountStatus :: Loaded . is_destroyed ( ) ) ;
238
+ assert ! ( !AccountStatus :: Changed . is_destroyed ( ) ) ;
114
239
115
240
// account modified but not destroyed
116
- assert ! ( AccountStatus :: Changed . modified_but_not_destroyed ( ) ) ;
117
- assert ! ( AccountStatus :: InMemoryChange . modified_but_not_destroyed ( ) ) ;
118
- assert ! ( !AccountStatus :: Loaded . modified_but_not_destroyed ( ) ) ;
119
- assert ! ( !AccountStatus :: LoadedEmptyEIP161 . modified_but_not_destroyed ( ) ) ;
120
- assert ! ( !AccountStatus :: LoadedNotExisting . modified_but_not_destroyed ( ) ) ;
121
- assert ! ( !AccountStatus :: Destroyed . modified_but_not_destroyed ( ) ) ;
122
- assert ! ( !AccountStatus :: DestroyedChanged . modified_but_not_destroyed ( ) ) ;
123
- assert ! ( !AccountStatus :: DestroyedAgain . modified_but_not_destroyed ( ) ) ;
241
+ assert ! ( AccountStatus :: Changed . is_modified_and_not_destroyed ( ) ) ;
242
+ assert ! ( AccountStatus :: InMemoryChange . is_modified_and_not_destroyed ( ) ) ;
243
+ assert ! ( !AccountStatus :: Loaded . is_modified_and_not_destroyed ( ) ) ;
244
+ assert ! ( !AccountStatus :: LoadedEmptyEIP161 . is_modified_and_not_destroyed ( ) ) ;
245
+ assert ! ( !AccountStatus :: LoadedNotExisting . is_modified_and_not_destroyed ( ) ) ;
246
+ assert ! ( !AccountStatus :: Destroyed . is_modified_and_not_destroyed ( ) ) ;
247
+ assert ! ( !AccountStatus :: DestroyedChanged . is_modified_and_not_destroyed ( ) ) ;
248
+ assert ! ( !AccountStatus :: DestroyedAgain . is_modified_and_not_destroyed ( ) ) ;
124
249
}
125
250
}
0 commit comments