@@ -77,9 +77,9 @@ type stateObject struct {
77
77
trie Trie // storage trie, which becomes non-nil on first access
78
78
code Code // contract bytecode, which gets set when code is loaded
79
79
80
- cachedStorage Storage // Storage entry cache to avoid duplicate reads
80
+ originStorage Storage // Storage cache of original entries to dedup rewrites
81
81
dirtyStorage Storage // Storage entries that need to be flushed to disk
82
- originalValue Storage // Map of original storage values, at the beginning of current call context
82
+
83
83
// Cache flags.
84
84
// When an object is marked suicided it will be delete from the trie
85
85
// during the "update" phase of the state transition.
@@ -115,9 +115,8 @@ func newObject(db *StateDB, address common.Address, data Account) *stateObject {
115
115
address : address ,
116
116
addrHash : crypto .Keccak256Hash (address [:]),
117
117
data : data ,
118
- cachedStorage : make (Storage ),
118
+ originStorage : make (Storage ),
119
119
dirtyStorage : make (Storage ),
120
- originalValue : make (Storage ),
121
120
}
122
121
}
123
122
@@ -160,13 +159,25 @@ func (c *stateObject) getTrie(db Database) Trie {
160
159
return c .trie
161
160
}
162
161
163
- // GetState returns a value in account storage.
162
+ // GetState retrieves a value from the account storage trie .
164
163
func (self * stateObject ) GetState (db Database , key common.Hash ) common.Hash {
165
- value , exists := self .cachedStorage [key ]
166
- if exists {
164
+ // If we have a dirty value for this state entry, return it
165
+ value , dirty := self .dirtyStorage [key ]
166
+ if dirty {
167
+ return value
168
+ }
169
+ // Otherwise return the entry's original value
170
+ return self .GetCommittedState (db , key )
171
+ }
172
+
173
+ // GetCommittedState retrieves a value from the committed account storage trie.
174
+ func (self * stateObject ) GetCommittedState (db Database , key common.Hash ) common.Hash {
175
+ // If we have the original value cached, return that
176
+ value , cached := self .originStorage [key ]
177
+ if cached {
167
178
return value
168
179
}
169
- // Load from DB in case it is missing.
180
+ // Otherwise load the value from the database
170
181
enc , err := self .getTrie (db ).TryGet (key [:])
171
182
if err != nil {
172
183
self .setError (err )
@@ -179,37 +190,27 @@ func (self *stateObject) GetState(db Database, key common.Hash) common.Hash {
179
190
}
180
191
value .SetBytes (content )
181
192
}
182
- self .cachedStorage [key ] = value
193
+ self .originStorage [key ] = value
183
194
return value
184
195
}
185
196
186
- // GetOriginalStateValue returns the state value that is currently in the Trie, that is, ignoring any
187
- // changes that have been made but not yet written to trie.
188
- func (self * stateObject ) GetOriginalStateValue (db Database , key common.Hash ) common.Hash {
189
- if original , exist := self .originalValue [key ]; exist {
190
- // original value has been set, return it
191
- return original
192
- }
193
- return self .GetState (db , key )
194
- }
195
-
196
197
// SetState updates a value in account storage.
197
198
func (self * stateObject ) SetState (db Database , key , value common.Hash ) {
199
+ // If the new value is the same as old, don't set
198
200
prev := self .GetState (db , key )
201
+ if prev == value {
202
+ return
203
+ }
204
+ // New value is different, update and journal the change
199
205
self .db .journal .append (storageChange {
200
206
account : & self .address ,
201
207
key : key ,
202
208
prevalue : prev ,
203
209
})
204
- if _ , isSet := self .originalValue [key ]; ! isSet {
205
- // original value has not been set, so set it now
206
- self .originalValue [key ] = prev
207
- }
208
210
self .setState (key , value )
209
211
}
210
212
211
213
func (self * stateObject ) setState (key , value common.Hash ) {
212
- self .cachedStorage [key ] = value
213
214
self .dirtyStorage [key ] = value
214
215
}
215
216
@@ -218,6 +219,13 @@ func (self *stateObject) updateTrie(db Database) Trie {
218
219
tr := self .getTrie (db )
219
220
for key , value := range self .dirtyStorage {
220
221
delete (self .dirtyStorage , key )
222
+
223
+ // Skip noop changes, persist actual changes
224
+ if value == self .originStorage [key ] {
225
+ continue
226
+ }
227
+ self .originStorage [key ] = value
228
+
221
229
if (value == common.Hash {}) {
222
230
self .setError (tr .TryDelete (key [:]))
223
231
continue
@@ -226,10 +234,6 @@ func (self *stateObject) updateTrie(db Database) Trie {
226
234
v , _ := rlp .EncodeToBytes (bytes .TrimLeft (value [:], "\x00 " ))
227
235
self .setError (tr .TryUpdate (key [:], v ))
228
236
}
229
- // Clean the map containing 'original' value of storage entries
230
- for k , _ := range self .originalValue {
231
- delete (self .originalValue , k )
232
- }
233
237
return tr
234
238
}
235
239
@@ -299,8 +303,7 @@ func (self *stateObject) deepCopy(db *StateDB) *stateObject {
299
303
}
300
304
stateObject .code = self .code
301
305
stateObject .dirtyStorage = self .dirtyStorage .Copy ()
302
- stateObject .cachedStorage = self .dirtyStorage .Copy ()
303
- stateObject .originalValue = self .originalValue .Copy ()
306
+ stateObject .originStorage = self .originStorage .Copy ()
304
307
stateObject .suicided = self .suicided
305
308
stateObject .dirtyCode = self .dirtyCode
306
309
stateObject .deleted = self .deleted
0 commit comments