github.com/waltonchain/waltonchain_gwtc_src@v1.1.4-0.20201225072101-8a298c95a819/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-wtc 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-wtc 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/wtc/go-wtc/common" 26 "github.com/wtc/go-wtc/crypto" 27 "github.com/wtc/go-wtc/rlp" 28 "github.com/wtc/go-wtc/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 Wtc 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 wtc 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 && s.data.CoinAge.Sign() == 0 && bytes.Equal(s.data.CodeHash, emptyCodeHash) 97 } 98 99 // Account is the Wtc 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 CoinAge *big.Int 105 //FUBlockNum *big.Int 106 FUBlockTime *big.Int //final update block,use for set coinage 107 Root common.Hash // merkle root of the storage trie 108 CodeHash []byte 109 } 110 111 // newObject creates a state object. 112 func newObject(db *StateDB, address common.Address, data Account, onDirty func(addr common.Address)) *stateObject { 113 if data.Balance == nil { 114 data.Balance = new(big.Int) 115 } 116 if data.CoinAge == nil { 117 data.CoinAge = new(big.Int) 118 } 119 if data.FUBlockTime == nil { 120 data.FUBlockTime = new(big.Int) 121 } 122 if data.CodeHash == nil { 123 data.CodeHash = emptyCodeHash 124 } 125 return &stateObject{ 126 db: db, 127 address: address, 128 addrHash: crypto.Keccak256Hash(address[:]), 129 data: data, 130 cachedStorage: make(Storage), 131 dirtyStorage: make(Storage), 132 onDirty: onDirty, 133 } 134 } 135 136 // EncodeRLP implements rlp.Encoder. 137 func (c *stateObject) EncodeRLP(w io.Writer) error { 138 return rlp.Encode(w, c.data) 139 } 140 141 // setError remembers the first non-nil error it is called with. 142 func (self *stateObject) setError(err error) { 143 if self.dbErr == nil { 144 self.dbErr = err 145 } 146 } 147 148 func (self *stateObject) markSuicided() { 149 self.suicided = true 150 if self.onDirty != nil { 151 self.onDirty(self.Address()) 152 self.onDirty = nil 153 } 154 } 155 156 func (c *stateObject) touch() { 157 c.db.journal = append(c.db.journal, touchChange{ 158 account: &c.address, 159 prev: c.touched, 160 prevDirty: c.onDirty == nil, 161 }) 162 if c.onDirty != nil { 163 c.onDirty(c.Address()) 164 c.onDirty = nil 165 } 166 c.touched = true 167 } 168 169 func (c *stateObject) getTrie(db Database) Trie { 170 if c.trie == nil { 171 var err error 172 c.trie, err = db.OpenStorageTrie(c.addrHash, c.data.Root) 173 if err != nil { 174 c.trie, _ = db.OpenStorageTrie(c.addrHash, common.Hash{}) 175 c.setError(fmt.Errorf("can't create storage trie: %v", err)) 176 } 177 } 178 return c.trie 179 } 180 181 // GetState returns a value in account storage. 182 func (self *stateObject) GetState(db Database, key common.Hash) common.Hash { 183 value, exists := self.cachedStorage[key] 184 if exists { 185 return value 186 } 187 // Load from DB in case it is missing. 188 enc, err := self.getTrie(db).TryGet(key[:]) 189 if err != nil { 190 self.setError(err) 191 return common.Hash{} 192 } 193 if len(enc) > 0 { 194 _, content, _, err := rlp.Split(enc) 195 if err != nil { 196 self.setError(err) 197 } 198 value.SetBytes(content) 199 } 200 if (value != common.Hash{}) { 201 self.cachedStorage[key] = value 202 } 203 return value 204 } 205 206 // SetState updates a value in account storage. 207 func (self *stateObject) SetState(db Database, key, value common.Hash) { 208 self.db.journal = append(self.db.journal, storageChange{ 209 account: &self.address, 210 key: key, 211 prevalue: self.GetState(db, key), 212 }) 213 self.setState(key, value) 214 } 215 216 func (self *stateObject) setState(key, value common.Hash) { 217 self.cachedStorage[key] = value 218 self.dirtyStorage[key] = value 219 220 if self.onDirty != nil { 221 self.onDirty(self.Address()) 222 self.onDirty = nil 223 } 224 } 225 226 // updateTrie writes cached storage modifications into the object's storage trie. 227 func (self *stateObject) updateTrie(db Database) Trie { 228 tr := self.getTrie(db) 229 for key, value := range self.dirtyStorage { 230 delete(self.dirtyStorage, key) 231 if (value == common.Hash{}) { 232 self.setError(tr.TryDelete(key[:])) 233 continue 234 } 235 // Encoding []byte cannot fail, ok to ignore the error. 236 v, _ := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00")) 237 self.setError(tr.TryUpdate(key[:], v)) 238 } 239 return tr 240 } 241 242 // UpdateRoot sets the trie root to the current root hash of 243 func (self *stateObject) updateRoot(db Database) { 244 self.updateTrie(db) 245 self.data.Root = self.trie.Hash() 246 } 247 248 // CommitTrie the storage trie of the object to dwb. 249 // This updates the trie root. 250 func (self *stateObject) CommitTrie(db Database, dbw trie.DatabaseWriter) error { 251 self.updateTrie(db) 252 if self.dbErr != nil { 253 return self.dbErr 254 } 255 root, err := self.trie.CommitTo(dbw) 256 if err == nil { 257 self.data.Root = root 258 } 259 return err 260 } 261 262 // AddBalance removes amount from c's balance. 263 // It is used to add funds to the destination account of a transfer. 264 func (c *stateObject) AddBalance(amount, Num, Time *big.Int) { 265 c.UpdateCoinAge(Num, Time) 266 // EIP158: We must check emptiness for the objects such that the account 267 // clearing (0,0,0 objects) can take effect. 268 if amount.Sign() == 0 { 269 if c.empty() { 270 c.touch() 271 } 272 273 return 274 } 275 c.SetBalance(new(big.Int).Add(c.Balance(), amount), Num, Time) 276 } 277 278 // SubBalance removes amount from c's balance. 279 // It is used to remove funds from the origin account of a transfer. 280 func (c *stateObject) SubBalance(amount, Num, Time *big.Int) { 281 c.UpdateCoinAge(Num, Time) 282 if amount.Sign() == 0 { 283 return 284 } 285 c.SetBalance(new(big.Int).Sub(c.Balance(), amount), Num, Time) 286 } 287 288 func (self *stateObject) SetBalance(amount, Num, Time *big.Int) { 289 self.db.journal = append(self.db.journal, balanceChange{ 290 account: &self.address, 291 prev: new(big.Int).Set(self.data.Balance), 292 }) 293 //self.UpdateCoinAge(Num, Time) 294 self.setBalance(amount) 295 } 296 297 func (self *stateObject) setBalance(amount *big.Int) { 298 self.data.Balance = amount 299 if self.onDirty != nil { 300 self.onDirty(self.Address()) 301 self.onDirty = nil 302 } 303 } 304 305 func (c *stateObject) AddCoinAge(amount *big.Int) { 306 if amount.Sign() == 0 { 307 if c.empty() { 308 c.touch() 309 } 310 311 return 312 } 313 c.SetCoinAge(new(big.Int).Add(c.CoinAge(), amount)) 314 } 315 316 func (c *stateObject) SubCoinAge(amount *big.Int) { 317 318 if amount.Sign() == 0 { 319 return 320 } 321 c.SetCoinAge(new(big.Int).Sub(c.CoinAge(), amount)) 322 } 323 324 func (self *stateObject) SetCoinAge(amount *big.Int) { 325 self.db.journal = append(self.db.journal, coinageChange{ 326 account: &self.address, 327 prev: new(big.Int).Set(self.data.CoinAge), 328 }) 329 self.setCoinAge(amount) 330 } 331 332 func (self *stateObject) setCoinAge(amount *big.Int) { 333 self.data.CoinAge = amount 334 if self.onDirty != nil { 335 self.onDirty(self.Address()) 336 self.onDirty = nil 337 } 338 } 339 340 func (self *stateObject) SetFUBlock(Time *big.Int) { 341 self.db.journal = append(self.db.journal, fublockChange{ 342 account: &self.address, 343 //prevnum: self.data.FUBlockNum, 344 prevtime: self.data.FUBlockTime, 345 }) 346 self.setFUBlock(Time) 347 } 348 349 func (self *stateObject) setFUBlock(Time *big.Int) { 350 //self.data.FUBlockNum = Num 351 self.data.FUBlockTime = Time 352 if self.onDirty != nil { 353 self.onDirty(self.Address()) 354 self.onDirty = nil 355 } 356 } 357 358 // Return the gas back to the origin. Used by the Virtual machine or Closures 359 func (c *stateObject) ReturnGas(gas *big.Int) {} 360 361 func (self *stateObject) deepCopy(db *StateDB, onDirty func(addr common.Address)) *stateObject { 362 stateObject := newObject(db, self.address, self.data, onDirty) 363 if self.trie != nil { 364 stateObject.trie = db.db.CopyTrie(self.trie) 365 } 366 stateObject.code = self.code 367 stateObject.dirtyStorage = self.dirtyStorage.Copy() 368 stateObject.cachedStorage = self.dirtyStorage.Copy() 369 stateObject.suicided = self.suicided 370 stateObject.dirtyCode = self.dirtyCode 371 stateObject.deleted = self.deleted 372 return stateObject 373 } 374 375 // 376 // Attribute accessors 377 // 378 379 // Returns the address of the contract/account 380 func (c *stateObject) Address() common.Address { 381 return c.address 382 } 383 384 // Code returns the contract code associated with this object, if any. 385 func (self *stateObject) Code(db Database) []byte { 386 if self.code != nil { 387 return self.code 388 } 389 if bytes.Equal(self.CodeHash(), emptyCodeHash) { 390 return nil 391 } 392 code, err := db.ContractCode(self.addrHash, common.BytesToHash(self.CodeHash())) 393 if err != nil { 394 self.setError(fmt.Errorf("can't load code hash %x: %v", self.CodeHash(), err)) 395 } 396 self.code = code 397 return code 398 } 399 400 func (self *stateObject) SetCode(codeHash common.Hash, code []byte) { 401 prevcode := self.Code(self.db.db) 402 self.db.journal = append(self.db.journal, codeChange{ 403 account: &self.address, 404 prevhash: self.CodeHash(), 405 prevcode: prevcode, 406 }) 407 self.setCode(codeHash, code) 408 } 409 410 func (self *stateObject) setCode(codeHash common.Hash, code []byte) { 411 self.code = code 412 self.data.CodeHash = codeHash[:] 413 self.dirtyCode = true 414 if self.onDirty != nil { 415 self.onDirty(self.Address()) 416 self.onDirty = nil 417 } 418 } 419 420 func (self *stateObject) SetNonce(nonce uint64) { 421 self.db.journal = append(self.db.journal, nonceChange{ 422 account: &self.address, 423 prev: self.data.Nonce, 424 }) 425 self.setNonce(nonce) 426 } 427 428 func (self *stateObject) setNonce(nonce uint64) { 429 self.data.Nonce = nonce 430 if self.onDirty != nil { 431 self.onDirty(self.Address()) 432 self.onDirty = nil 433 } 434 } 435 436 func (self *stateObject) CodeHash() []byte { 437 return self.data.CodeHash 438 } 439 440 func (self *stateObject) Balance() *big.Int { 441 return self.data.Balance 442 } 443 444 func (self *stateObject) FUBlock() (*big.Int) { 445 return self.data.FUBlockTime 446 } 447 448 func (self *stateObject) CoinAge() *big.Int { 449 return self.data.CoinAge 450 } 451 452 func (self *stateObject) Nonce() uint64 { 453 return self.data.Nonce 454 } 455 456 // Never called, but must be present to allow stateObject to be used 457 // as a vm.Account interface that also satisfies the vm.ContractRef 458 // interface. Interfaces are awesome. 459 func (self *stateObject) Value() *big.Int { 460 panic("Value on stateObject should never be called") 461 } 462 463 func (self *stateObject) UpdateCoinAge(Num,Time *big.Int) { 464 fut := self.FUBlock() 465 if fut.Cmp(Time) < 0 { 466 t := new(big.Int).Sub(Time,fut) 467 self.AddCoinAge(new(big.Int).Mul(self.Balance(),t)) 468 self.SetFUBlock(Time) 469 } 470 }