github.com/zecrey-Labs/bor@v0.1.4/core/state/state_object.go (about) 1 // Copyright 2014 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package state 18 19 import ( 20 "bytes" 21 "fmt" 22 "io" 23 "math/big" 24 "time" 25 26 "github.com/maticnetwork/bor/common" 27 "github.com/maticnetwork/bor/crypto" 28 "github.com/maticnetwork/bor/metrics" 29 "github.com/maticnetwork/bor/rlp" 30 ) 31 32 var emptyCodeHash = crypto.Keccak256(nil) 33 34 type Code []byte 35 36 func (c Code) String() string { 37 return string(c) //strings.Join(Disassemble(c), " ") 38 } 39 40 type Storage map[common.Hash]common.Hash 41 42 func (s Storage) String() (str string) { 43 for key, value := range s { 44 str += fmt.Sprintf("%X : %X\n", key, value) 45 } 46 47 return 48 } 49 50 func (s Storage) Copy() Storage { 51 cpy := make(Storage) 52 for key, value := range s { 53 cpy[key] = value 54 } 55 56 return cpy 57 } 58 59 // stateObject represents an Ethereum account which is being modified. 60 // 61 // The usage pattern is as follows: 62 // First you need to obtain a state object. 63 // Account values can be accessed and modified through the object. 64 // Finally, call CommitTrie to write the modified storage trie into a database. 65 type stateObject struct { 66 address common.Address 67 addrHash common.Hash // hash of ethereum address of the account 68 data Account 69 db *StateDB 70 71 // DB error. 72 // State objects are used by the consensus core and VM which are 73 // unable to deal with database-level errors. Any error that occurs 74 // during a database read is memoized here and will eventually be returned 75 // by StateDB.Commit. 76 dbErr error 77 78 // Write caches. 79 trie Trie // storage trie, which becomes non-nil on first access 80 code Code // contract bytecode, which gets set when code is loaded 81 82 originStorage Storage // Storage cache of original entries to dedup rewrites 83 dirtyStorage Storage // Storage entries that need to be flushed to disk 84 85 // Cache flags. 86 // When an object is marked suicided it will be delete from the trie 87 // during the "update" phase of the state transition. 88 dirtyCode bool // true if the code was updated 89 suicided bool 90 deleted bool 91 } 92 93 // empty returns whether the account is considered empty. 94 func (s *stateObject) empty() bool { 95 return s.data.Nonce == 0 && s.data.Balance.Sign() == 0 && bytes.Equal(s.data.CodeHash, emptyCodeHash) 96 } 97 98 // Account is the Ethereum consensus representation of accounts. 99 // These objects are stored in the main account trie. 100 type Account struct { 101 Nonce uint64 102 Balance *big.Int 103 Root common.Hash // merkle root of the storage trie 104 CodeHash []byte 105 } 106 107 // newObject creates a state object. 108 func newObject(db *StateDB, address common.Address, data Account) *stateObject { 109 if data.Balance == nil { 110 data.Balance = new(big.Int) 111 } 112 if data.CodeHash == nil { 113 data.CodeHash = emptyCodeHash 114 } 115 return &stateObject{ 116 db: db, 117 address: address, 118 addrHash: crypto.Keccak256Hash(address[:]), 119 data: data, 120 originStorage: make(Storage), 121 dirtyStorage: make(Storage), 122 } 123 } 124 125 // EncodeRLP implements rlp.Encoder. 126 func (s *stateObject) EncodeRLP(w io.Writer) error { 127 return rlp.Encode(w, s.data) 128 } 129 130 // setError remembers the first non-nil error it is called with. 131 func (s *stateObject) setError(err error) { 132 if s.dbErr == nil { 133 s.dbErr = err 134 } 135 } 136 137 func (s *stateObject) markSuicided() { 138 s.suicided = true 139 } 140 141 func (s *stateObject) touch() { 142 s.db.journal.append(touchChange{ 143 account: &s.address, 144 }) 145 if s.address == ripemd { 146 // Explicitly put it in the dirty-cache, which is otherwise generated from 147 // flattened journals. 148 s.db.journal.dirty(s.address) 149 } 150 } 151 152 func (s *stateObject) getTrie(db Database) Trie { 153 if s.trie == nil { 154 var err error 155 s.trie, err = db.OpenStorageTrie(s.addrHash, s.data.Root) 156 if err != nil { 157 s.trie, _ = db.OpenStorageTrie(s.addrHash, common.Hash{}) 158 s.setError(fmt.Errorf("can't create storage trie: %v", err)) 159 } 160 } 161 return s.trie 162 } 163 164 // GetState retrieves a value from the account storage trie. 165 func (s *stateObject) GetState(db Database, key common.Hash) common.Hash { 166 // If we have a dirty value for this state entry, return it 167 value, dirty := s.dirtyStorage[key] 168 if dirty { 169 return value 170 } 171 // Otherwise return the entry's original value 172 return s.GetCommittedState(db, key) 173 } 174 175 // GetCommittedState retrieves a value from the committed account storage trie. 176 func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Hash { 177 // If we have the original value cached, return that 178 value, cached := s.originStorage[key] 179 if cached { 180 return value 181 } 182 // Track the amount of time wasted on reading the storge trie 183 if metrics.EnabledExpensive { 184 defer func(start time.Time) { s.db.StorageReads += time.Since(start) }(time.Now()) 185 } 186 // Otherwise load the value from the database 187 enc, err := s.getTrie(db).TryGet(key[:]) 188 if err != nil { 189 s.setError(err) 190 return common.Hash{} 191 } 192 if len(enc) > 0 { 193 _, content, _, err := rlp.Split(enc) 194 if err != nil { 195 s.setError(err) 196 } 197 value.SetBytes(content) 198 } 199 s.originStorage[key] = value 200 return value 201 } 202 203 // SetState updates a value in account storage. 204 func (s *stateObject) SetState(db Database, key, value common.Hash) { 205 // If the new value is the same as old, don't set 206 prev := s.GetState(db, key) 207 if prev == value { 208 return 209 } 210 // New value is different, update and journal the change 211 s.db.journal.append(storageChange{ 212 account: &s.address, 213 key: key, 214 prevalue: prev, 215 }) 216 s.setState(key, value) 217 } 218 219 func (s *stateObject) setState(key, value common.Hash) { 220 s.dirtyStorage[key] = value 221 } 222 223 // updateTrie writes cached storage modifications into the object's storage trie. 224 func (s *stateObject) updateTrie(db Database) Trie { 225 // Track the amount of time wasted on updating the storge trie 226 if metrics.EnabledExpensive { 227 defer func(start time.Time) { s.db.StorageUpdates += time.Since(start) }(time.Now()) 228 } 229 // Update all the dirty slots in the trie 230 tr := s.getTrie(db) 231 for key, value := range s.dirtyStorage { 232 delete(s.dirtyStorage, key) 233 234 // Skip noop changes, persist actual changes 235 if value == s.originStorage[key] { 236 continue 237 } 238 s.originStorage[key] = value 239 240 if (value == common.Hash{}) { 241 s.setError(tr.TryDelete(key[:])) 242 continue 243 } 244 // Encoding []byte cannot fail, ok to ignore the error. 245 v, _ := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00")) 246 s.setError(tr.TryUpdate(key[:], v)) 247 } 248 return tr 249 } 250 251 // UpdateRoot sets the trie root to the current root hash of 252 func (s *stateObject) updateRoot(db Database) { 253 s.updateTrie(db) 254 255 // Track the amount of time wasted on hashing the storge trie 256 if metrics.EnabledExpensive { 257 defer func(start time.Time) { s.db.StorageHashes += time.Since(start) }(time.Now()) 258 } 259 s.data.Root = s.trie.Hash() 260 } 261 262 // CommitTrie the storage trie of the object to db. 263 // This updates the trie root. 264 func (s *stateObject) CommitTrie(db Database) error { 265 s.updateTrie(db) 266 if s.dbErr != nil { 267 return s.dbErr 268 } 269 // Track the amount of time wasted on committing the storge trie 270 if metrics.EnabledExpensive { 271 defer func(start time.Time) { s.db.StorageCommits += time.Since(start) }(time.Now()) 272 } 273 root, err := s.trie.Commit(nil) 274 if err == nil { 275 s.data.Root = root 276 } 277 return err 278 } 279 280 // AddBalance removes amount from c's balance. 281 // It is used to add funds to the destination account of a transfer. 282 func (s *stateObject) AddBalance(amount *big.Int) { 283 // EIP158: We must check emptiness for the objects such that the account 284 // clearing (0,0,0 objects) can take effect. 285 if amount.Sign() == 0 { 286 if s.empty() { 287 s.touch() 288 } 289 290 return 291 } 292 s.SetBalance(new(big.Int).Add(s.Balance(), amount)) 293 } 294 295 // SubBalance removes amount from c's balance. 296 // It is used to remove funds from the origin account of a transfer. 297 func (s *stateObject) SubBalance(amount *big.Int) { 298 if amount.Sign() == 0 { 299 return 300 } 301 s.SetBalance(new(big.Int).Sub(s.Balance(), amount)) 302 } 303 304 func (s *stateObject) SetBalance(amount *big.Int) { 305 s.db.journal.append(balanceChange{ 306 account: &s.address, 307 prev: new(big.Int).Set(s.data.Balance), 308 }) 309 s.setBalance(amount) 310 } 311 312 func (s *stateObject) setBalance(amount *big.Int) { 313 s.data.Balance = amount 314 } 315 316 // Return the gas back to the origin. Used by the Virtual machine or Closures 317 func (s *stateObject) ReturnGas(gas *big.Int) {} 318 319 func (s *stateObject) deepCopy(db *StateDB) *stateObject { 320 stateObject := newObject(db, s.address, s.data) 321 if s.trie != nil { 322 stateObject.trie = db.db.CopyTrie(s.trie) 323 } 324 stateObject.code = s.code 325 stateObject.dirtyStorage = s.dirtyStorage.Copy() 326 stateObject.originStorage = s.originStorage.Copy() 327 stateObject.suicided = s.suicided 328 stateObject.dirtyCode = s.dirtyCode 329 stateObject.deleted = s.deleted 330 return stateObject 331 } 332 333 // 334 // Attribute accessors 335 // 336 337 // Returns the address of the contract/account 338 func (s *stateObject) Address() common.Address { 339 return s.address 340 } 341 342 // Code returns the contract code associated with this object, if any. 343 func (s *stateObject) Code(db Database) []byte { 344 if s.code != nil { 345 return s.code 346 } 347 if bytes.Equal(s.CodeHash(), emptyCodeHash) { 348 return nil 349 } 350 code, err := db.ContractCode(s.addrHash, common.BytesToHash(s.CodeHash())) 351 if err != nil { 352 s.setError(fmt.Errorf("can't load code hash %x: %v", s.CodeHash(), err)) 353 } 354 s.code = code 355 return code 356 } 357 358 func (s *stateObject) SetCode(codeHash common.Hash, code []byte) { 359 prevcode := s.Code(s.db.db) 360 s.db.journal.append(codeChange{ 361 account: &s.address, 362 prevhash: s.CodeHash(), 363 prevcode: prevcode, 364 }) 365 s.setCode(codeHash, code) 366 } 367 368 func (s *stateObject) setCode(codeHash common.Hash, code []byte) { 369 s.code = code 370 s.data.CodeHash = codeHash[:] 371 s.dirtyCode = true 372 } 373 374 func (s *stateObject) SetNonce(nonce uint64) { 375 s.db.journal.append(nonceChange{ 376 account: &s.address, 377 prev: s.data.Nonce, 378 }) 379 s.setNonce(nonce) 380 } 381 382 func (s *stateObject) setNonce(nonce uint64) { 383 s.data.Nonce = nonce 384 } 385 386 func (s *stateObject) CodeHash() []byte { 387 return s.data.CodeHash 388 } 389 390 func (s *stateObject) Balance() *big.Int { 391 return s.data.Balance 392 } 393 394 func (s *stateObject) Nonce() uint64 { 395 return s.data.Nonce 396 } 397 398 // Never called, but must be present to allow stateObject to be used 399 // as a vm.Account interface that also satisfies the vm.ContractRef 400 // interface. Interfaces are awesome. 401 func (s *stateObject) Value() *big.Int { 402 panic("Value on stateObject should never be called") 403 }