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