github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/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 25 "github.com/ethereumproject/go-ethereum/common" 26 "github.com/ethereumproject/go-ethereum/crypto" 27 "github.com/ethereumproject/go-ethereum/logger" 28 "github.com/ethereumproject/go-ethereum/logger/glog" 29 "github.com/ethereumproject/go-ethereum/rlp" 30 "github.com/ethereumproject/go-ethereum/trie" 31 ) 32 33 var emptyCodeHash = crypto.Keccak256(nil) 34 35 type Code []byte 36 37 func (self Code) String() string { 38 return string(self) //strings.Join(Disassemble(self), " ") 39 } 40 41 type Storage map[common.Hash]common.Hash 42 43 func (self Storage) String() (str string) { 44 for key, value := range self { 45 str += fmt.Sprintf("%X : %X\n", key, value) 46 } 47 48 return 49 } 50 51 func (self Storage) Copy() Storage { 52 cpy := make(Storage) 53 for key, value := range self { 54 cpy[key] = value 55 } 56 57 return cpy 58 } 59 60 // StateObject represents an Ethereum account which is being modified. 61 // 62 // The usage pattern is as follows: 63 // First you need to obtain a state object. 64 // Account values can be accessed and modified through the object. 65 // Finally, call CommitTrie to write the modified storage trie into a database. 66 type StateObject struct { 67 address common.Address 68 addrHash common.Hash // hash of ethereum address of the account 69 data Account 70 db *StateDB 71 72 // DB error. 73 // State objects are used by the consensus core and VM which are 74 // unable to deal with database-level errors. Any error that occurs 75 // during a database read is memoized here and will eventually be returned 76 // by StateDB.Commit. 77 dbErr error 78 79 // Write caches. 80 trie Trie // storage trie, which becomes non-nil on first access 81 code Code // contract bytecode, which gets set when code is loaded 82 83 cachedStorage Storage // Storage entry cache to avoid duplicate reads 84 dirtyStorage Storage // Storage entries that need to be flushed to disk 85 86 // Cache flags. 87 // When an object is marked suicided it will be delete from the trie 88 // during the "update" phase of the state transition. 89 dirtyCode bool // true if the code was updated 90 suicided bool 91 touched bool 92 deleted bool 93 onDirty func(addr common.Address) // Callback method to mark a state object newly dirty 94 } 95 96 // empty returns whether the account is considered empty. 97 func (s *StateObject) empty() bool { 98 return s.data.Nonce == 0 && s.data.Balance.Sign() == 0 && bytes.Equal(s.data.CodeHash, emptyCodeHash) 99 } 100 101 // Account is the Ethereum consensus representation of accounts. 102 // These objects are stored in the main account trie. 103 type Account struct { 104 Nonce uint64 105 Balance *big.Int 106 Root common.Hash // merkle root of the storage trie 107 CodeHash []byte 108 } 109 110 // newObject creates a state object. 111 func newObject(db *StateDB, address common.Address, data Account, onDirty func(addr common.Address)) *StateObject { 112 if data.Balance == nil { 113 data.Balance = new(big.Int) 114 } 115 if data.CodeHash == nil { 116 data.CodeHash = emptyCodeHash 117 } 118 return &StateObject{ 119 db: db, 120 address: address, 121 addrHash: crypto.Keccak256Hash(address[:]), 122 data: data, 123 cachedStorage: make(Storage), 124 dirtyStorage: make(Storage), 125 onDirty: onDirty, 126 } 127 } 128 129 // EncodeRLP implements rlp.Encoder. 130 func (c *StateObject) EncodeRLP(w io.Writer) error { 131 return rlp.Encode(w, c.data) 132 } 133 134 // setError remembers the first non-nil error it is called with. 135 func (self *StateObject) setError(err error) { 136 if self.dbErr == nil { 137 self.dbErr = err 138 } 139 } 140 141 func (self *StateObject) markSuicided() { 142 self.suicided = true 143 if self.onDirty != nil { 144 self.onDirty(self.Address()) 145 self.onDirty = nil 146 } 147 } 148 149 func (c *StateObject) touch() { 150 c.db.journal = append(c.db.journal, touchChange{ 151 account: &c.address, 152 prev: c.touched, 153 prevDirty: c.onDirty == nil, 154 }) 155 if c.onDirty != nil { 156 c.onDirty(c.Address()) 157 c.onDirty = nil 158 } 159 c.touched = true 160 } 161 162 func (c *StateObject) getTrie(db Database) Trie { 163 if c.trie == nil { 164 var err error 165 c.trie, err = db.OpenStorageTrie(c.addrHash, c.data.Root) 166 if err != nil { 167 c.trie, _ = db.OpenStorageTrie(c.addrHash, common.Hash{}) 168 c.setError(fmt.Errorf("can't create storage trie: %v", err)) 169 } 170 } 171 return c.trie 172 } 173 174 // GetState returns a value in account storage. 175 func (self *StateObject) GetState(db Database, key common.Hash) common.Hash { 176 value, exists := self.cachedStorage[key] 177 if exists { 178 return value 179 } 180 // Load from DB in case it is missing. 181 enc, err := self.getTrie(db).TryGet(key[:]) 182 if err != nil { 183 self.setError(err) 184 return common.Hash{} 185 } 186 if len(enc) > 0 { 187 _, content, _, err := rlp.Split(enc) 188 if err != nil { 189 self.setError(err) 190 } 191 value.SetBytes(content) 192 } 193 if (value != common.Hash{}) { 194 self.cachedStorage[key] = value 195 } 196 return value 197 } 198 199 // SetState updates a value in account storage. 200 func (self *StateObject) SetState(db Database, key, value common.Hash) { 201 self.db.journal = append(self.db.journal, storageChange{ 202 account: &self.address, 203 key: key, 204 prevalue: self.GetState(db, key), 205 }) 206 self.setState(key, value) 207 } 208 209 func (self *StateObject) setState(key, value common.Hash) { 210 self.cachedStorage[key] = value 211 self.dirtyStorage[key] = value 212 213 if self.onDirty != nil { 214 self.onDirty(self.Address()) 215 self.onDirty = nil 216 } 217 } 218 219 // updateTrie writes cached storage modifications into the object's storage trie. 220 func (self *StateObject) updateTrie(db Database) Trie { 221 tr := self.getTrie(db) 222 for key, value := range self.dirtyStorage { 223 delete(self.dirtyStorage, key) 224 if (value == common.Hash{}) { 225 self.setError(tr.TryDelete(key[:])) 226 continue 227 } 228 // Encoding []byte cannot fail, ok to ignore the error. 229 v, _ := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00")) 230 self.setError(tr.TryUpdate(key[:], v)) 231 } 232 return tr 233 } 234 235 // UpdateRoot sets the trie root to the current root hash of 236 func (self *StateObject) updateRoot(db Database) { 237 self.updateTrie(db) 238 self.data.Root = self.trie.Hash() 239 } 240 241 // CommitTrie the storage trie of the object to dwb. 242 // This updates the trie root. 243 func (self *StateObject) CommitTrie(db Database, dbw trie.DatabaseWriter) error { 244 self.updateTrie(db) 245 if self.dbErr != nil { 246 return self.dbErr 247 } 248 root, err := self.trie.CommitTo(dbw) 249 if err == nil { 250 self.data.Root = root 251 } 252 return err 253 } 254 255 // AddBalance removes amount from c's balance. 256 // It is used to add funds to the destination account of a transfer. 257 func (c *StateObject) AddBalance(amount *big.Int) { 258 // EIP158: We must check emptiness for the objects such that the account 259 // clearing (0,0,0 objects) can take effect. 260 if amount.Sign() == 0 { 261 if c.empty() { 262 c.touch() 263 } 264 265 return 266 } 267 c.SetBalance(new(big.Int).Add(c.Balance(), amount)) 268 if logger.MlogEnabled() { 269 mlogStateAddBalanceObject.AssignDetails( 270 c.Address().Hex(), 271 c.Nonce(), 272 c.Balance(), 273 amount, 274 ).Send(mlogState) 275 } 276 if glog.V(logger.Detail) { 277 glog.Infof("%x: #%d %v (+ %v)\n", c.Address(), c.Nonce(), c.Balance(), amount) 278 } 279 } 280 281 // SubBalance removes amount from c's balance. 282 // It is used to remove funds from the origin account of a transfer. 283 func (c *StateObject) SubBalance(amount *big.Int) { 284 if amount.Sign() == 0 { 285 return 286 } 287 c.SetBalance(new(big.Int).Sub(c.Balance(), amount)) 288 if logger.MlogEnabled() { 289 mlogStateSubBalanceObject.AssignDetails( 290 c.Address().Hex(), 291 c.Nonce(), 292 c.Balance(), 293 amount, 294 ).Send(mlogState) 295 } 296 if glog.V(logger.Detail) { 297 glog.Infof("%x: #%d %v (- %v)\n", c.Address(), c.Nonce(), c.Balance(), amount) 298 } 299 } 300 301 func (self *StateObject) SetBalance(amount *big.Int) { 302 self.db.journal = append(self.db.journal, balanceChange{ 303 account: &self.address, 304 prev: new(big.Int).Set(self.data.Balance), 305 }) 306 self.setBalance(amount) 307 } 308 309 func (self *StateObject) setBalance(amount *big.Int) { 310 self.data.Balance = amount 311 if self.onDirty != nil { 312 self.onDirty(self.Address()) 313 self.onDirty = nil 314 } 315 } 316 317 // Return the gas back to the origin. Used by the Virtual machine or Closures 318 func (c *StateObject) ReturnGas(*big.Int, *big.Int) {} 319 320 func (self *StateObject) deepCopy(db *StateDB, onDirty func(addr common.Address)) *StateObject { 321 stateObject := newObject(db, self.address, self.data, onDirty) 322 if self.trie != nil { 323 stateObject.trie = db.db.CopyTrie(self.trie) 324 } 325 stateObject.code = self.code 326 stateObject.dirtyStorage = self.dirtyStorage.Copy() 327 stateObject.cachedStorage = self.dirtyStorage.Copy() 328 stateObject.suicided = self.suicided 329 stateObject.dirtyCode = self.dirtyCode 330 stateObject.deleted = self.deleted 331 return stateObject 332 } 333 334 // 335 // Attribute accessors 336 // 337 338 // Returns the address of the contract/account 339 func (c *StateObject) Address() common.Address { 340 return c.address 341 } 342 343 // Code returns the contract code associated with this object, if any. 344 func (self *StateObject) Code(db Database) []byte { 345 if self.code != nil { 346 return self.code 347 } 348 if bytes.Equal(self.CodeHash(), emptyCodeHash) { 349 return nil 350 } 351 code, err := db.ContractCode(self.addrHash, common.BytesToHash(self.CodeHash())) 352 if err != nil { 353 self.setError(fmt.Errorf("can't load code hash %x: %v", self.CodeHash(), err)) 354 } 355 self.code = code 356 return code 357 } 358 359 func (self *StateObject) SetCode(codeHash common.Hash, code []byte) { 360 prevcode := self.Code(self.db.db) 361 self.db.journal = append(self.db.journal, codeChange{ 362 account: &self.address, 363 prevhash: self.CodeHash(), 364 prevcode: prevcode, 365 }) 366 self.setCode(codeHash, code) 367 } 368 369 func (self *StateObject) setCode(codeHash common.Hash, code []byte) { 370 self.code = code 371 self.data.CodeHash = codeHash[:] 372 self.dirtyCode = true 373 if self.onDirty != nil { 374 self.onDirty(self.Address()) 375 self.onDirty = nil 376 } 377 } 378 379 func (self *StateObject) SetNonce(nonce uint64) { 380 self.db.journal = append(self.db.journal, nonceChange{ 381 account: &self.address, 382 prev: self.data.Nonce, 383 }) 384 self.setNonce(nonce) 385 } 386 387 func (self *StateObject) setNonce(nonce uint64) { 388 self.data.Nonce = nonce 389 if self.onDirty != nil { 390 self.onDirty(self.Address()) 391 self.onDirty = nil 392 } 393 } 394 395 func (self *StateObject) CodeHash() []byte { 396 return self.data.CodeHash 397 } 398 399 func (self *StateObject) Balance() *big.Int { 400 return self.data.Balance 401 } 402 403 func (self *StateObject) Nonce() uint64 { 404 return self.data.Nonce 405 } 406 407 // Never called, but must be present to allow StateObject to be used 408 // as a vm.Account interface that also satisfies the vm.ContractRef 409 // interface. Interfaces are awesome. 410 func (self *StateObject) Value() *big.Int { 411 panic("Value on StateObject should never be called") 412 } 413 414 func (self *StateObject) ForEachStorage(cb func(key, value common.Hash) bool) { 415 // When iterating over the storage check the cache first 416 for h, value := range self.cachedStorage { 417 cb(h, value) 418 } 419 420 it := trie.NewIterator(self.getTrie(self.db.db).NodeIterator(nil)) 421 for it.Next() { 422 // ignore cached values 423 key := common.BytesToHash(self.trie.GetKey(it.Key)) 424 if _, ok := self.cachedStorage[key]; !ok { 425 cb(key, common.BytesToHash(it.Value)) 426 } 427 } 428 }