github.com/amazechain/amc@v0.1.3/modules/state/intra_block_state.go (about) 1 // Copyright 2023 The AmazeChain Authors 2 // This file is part of the AmazeChain library. 3 // 4 // The AmazeChain 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 AmazeChain 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 AmazeChain library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package state provides a caching layer atop the Ethereum state trie. 18 package state 19 20 import ( 21 "fmt" 22 "github.com/amazechain/amc/common/account" 23 "github.com/amazechain/amc/common/block" 24 "github.com/amazechain/amc/common/crypto" 25 "github.com/amazechain/amc/common/hash" 26 27 "github.com/amazechain/amc/common/transaction" 28 "github.com/amazechain/amc/common/types" 29 "github.com/amazechain/amc/internal/avm/rlp" 30 "github.com/amazechain/amc/log" 31 "golang.org/x/crypto/sha3" 32 "sort" 33 "unsafe" 34 35 "github.com/holiman/uint256" 36 37 "github.com/amazechain/amc/params" 38 ) 39 40 type revision struct { 41 id int 42 journalIndex int 43 } 44 45 type StateTracer interface { 46 CaptureAccountRead(account types.Address) error 47 CaptureAccountWrite(account types.Address) error 48 } 49 50 // SystemAddress - sender address for internal state updates. 51 var SystemAddress = types.HexToAddress("0xfffffffffffffffffffffffffffffffffffffffe") 52 53 // BalanceIncrease represents the increase of balance of an account that did not require 54 // reading the account first 55 type BalanceIncrease struct { 56 increase uint256.Int 57 transferred bool // Set to true when the corresponding stateObject is created and balance increase is transferred to the stateObject 58 count int // Number of increases - this needs tracking for proper reversion 59 } 60 61 // IntraBlockState is responsible for caching and managing state changes 62 // that occur during block's execution. 63 // NOT THREAD SAFE! 64 type IntraBlockState struct { 65 stateReader StateReader 66 67 // This map holds 'live' objects, which will get modified while processing a state transition. 68 stateObjects map[types.Address]*stateObject 69 stateObjectsDirty map[types.Address]struct{} 70 71 nilAccounts map[types.Address]struct{} // Remember non-existent account to avoid reading them again 72 73 // DB error. 74 // State objects are used by the consensus core and VM which are 75 // unable to deal with database-level errors. Any error that occurs 76 // during a database read is memoized here and will eventually be returned 77 // by IntraBlockState.Commit. 78 savedErr error 79 80 // The refund counter, also used by state transitioning. 81 refund uint64 82 83 thash, bhash types.Hash 84 txIndex int 85 logs map[types.Hash][]*block.Log 86 logSize uint 87 88 // Journal of state modifications. This is the backbone of 89 // Snapshot and RevertToSnapshot. 90 journal *journal 91 validRevisions []revision 92 nextRevisionID int 93 tracer StateTracer 94 trace bool 95 accessList *accessList 96 balanceInc map[types.Address]*BalanceIncrease // Map of balance increases (without first reading the account) 97 98 snap *Snapshot 99 codeMap map[types.Hash][]byte 100 height uint64 101 } 102 103 // Create a new state from a given trie 104 func New(stateReader StateReader) *IntraBlockState { 105 return &IntraBlockState{ 106 stateReader: stateReader, 107 stateObjects: map[types.Address]*stateObject{}, 108 stateObjectsDirty: map[types.Address]struct{}{}, 109 nilAccounts: map[types.Address]struct{}{}, 110 logs: map[types.Hash][]*block.Log{}, 111 journal: newJournal(), 112 accessList: newAccessList(), 113 balanceInc: map[types.Address]*BalanceIncrease{}, 114 } 115 } 116 117 func (sdb *IntraBlockState) BeginWriteSnapshot() { 118 sdb.snap = NewWritableSnapshot() 119 } 120 121 func (sdb *IntraBlockState) BeginWriteCodes() { 122 sdb.codeMap = make(map[types.Hash][]byte, 0) 123 } 124 125 func (sdb *IntraBlockState) CodeHashes() map[types.Hash][]byte { 126 // it should be called end of block execute 127 for addr, stateObject := range sdb.stateObjects { 128 _, isDirty := sdb.stateObjectsDirty[addr] 129 if isDirty && (stateObject.created || !stateObject.selfdestructed) && stateObject.code != nil && stateObject.dirtyCode { 130 h := types.Hash{} 131 h.SetBytes(stateObject.CodeHash()) 132 sdb.codeMap[h] = stateObject.code 133 } 134 } 135 return sdb.codeMap 136 } 137 138 func (sdb *IntraBlockState) SetHeight(height uint64) { 139 sdb.height = height 140 } 141 142 func (sdb *IntraBlockState) Snap() *Snapshot { 143 return sdb.snap 144 } 145 146 func (sdb *IntraBlockState) SetOutHash(hash types.Hash) { 147 if sdb.snap == nil || !sdb.snap.CanWrite() { 148 return 149 } 150 sdb.snap.OutHash = hash 151 } 152 153 func (sdb *IntraBlockState) WrittenSnapshot(hash types.Hash) []byte { 154 if sdb.snap == nil || !sdb.snap.CanWrite() { 155 return nil 156 } 157 if sdb.snap.Items != nil { 158 sort.Sort(sdb.snap.Items) 159 } 160 sdb.snap.OutHash = hash 161 b, err := rlp.EncodeToBytes(sdb.snap) 162 if err != nil { 163 return nil 164 } 165 sdb.snap = nil 166 return b 167 } 168 169 func (s *IntraBlockState) SetGetOneFun(f1 GetOneFun) { 170 s.snap.SetGetFun(f1) 171 } 172 173 func (sdb *IntraBlockState) PrepareReadableSnapshot(data []byte) error { 174 snap, err := ReadSnapshotData(data) 175 if err != nil { 176 return err 177 } 178 sdb.snap = snap 179 return nil 180 } 181 182 func (sdb *IntraBlockState) SetSnapshot(snap *Snapshot) { 183 snap.accounts = make(map[string]int, len(snap.Items)) 184 snap.storage = make(map[string]int, len(snap.Items)) 185 for k, v := range snap.Items { 186 if len(v.Key) == types.AddressLength { 187 snap.accounts[*(*string)(unsafe.Pointer(&v.Key))] = k 188 } else { 189 snap.storage[*(*string)(unsafe.Pointer(&v.Key))] = k 190 } 191 } 192 sdb.snap = snap 193 } 194 195 func (sdb *IntraBlockState) SetTracer(tracer StateTracer) { 196 sdb.tracer = tracer 197 } 198 199 func (sdb *IntraBlockState) SetTrace(trace bool) { 200 sdb.trace = trace 201 } 202 203 // setErrorUnsafe sets error but should be called in medhods that already have locks 204 func (sdb *IntraBlockState) setErrorUnsafe(err error) { 205 if sdb.savedErr == nil { 206 sdb.savedErr = err 207 } 208 } 209 210 func (sdb *IntraBlockState) Error() error { 211 return sdb.savedErr 212 } 213 214 func (sdb *IntraBlockState) SetStateReader(reader StateReader) { 215 sdb.stateReader = reader 216 } 217 218 func (sdb *IntraBlockState) GetStateReader() StateReader { 219 return sdb.stateReader 220 } 221 222 // Reset clears out all ephemeral state objects from the state db, but keeps 223 // the underlying state trie to avoid reloading data for the next operations. 224 func (sdb *IntraBlockState) Reset() { 225 sdb.stateObjects = make(map[types.Address]*stateObject) 226 sdb.stateObjectsDirty = make(map[types.Address]struct{}) 227 sdb.thash = types.Hash{} 228 sdb.bhash = types.Hash{} 229 sdb.txIndex = 0 230 sdb.logs = make(map[types.Hash][]*block.Log) 231 sdb.logSize = 0 232 sdb.clearJournalAndRefund() 233 sdb.accessList = newAccessList() 234 sdb.balanceInc = make(map[types.Address]*BalanceIncrease) 235 } 236 237 func (sdb *IntraBlockState) AddLog(log2 *block.Log) { 238 sdb.journal.append(addLogChange{txhash: sdb.thash}) 239 log2.TxHash = sdb.thash 240 log2.BlockHash = sdb.bhash 241 log2.TxIndex = uint(sdb.txIndex) 242 log2.Index = sdb.logSize 243 sdb.logs[sdb.thash] = append(sdb.logs[sdb.thash], log2) 244 sdb.logSize++ 245 } 246 247 func (sdb *IntraBlockState) GetLogs(hash types.Hash) []*block.Log { 248 return sdb.logs[hash] 249 } 250 251 func (sdb *IntraBlockState) Logs() []*block.Log { 252 var logs []*block.Log 253 for _, lgs := range sdb.logs { 254 logs = append(logs, lgs...) 255 } 256 return logs 257 } 258 259 // AddRefund adds gas to the refund counter 260 func (sdb *IntraBlockState) AddRefund(gas uint64) { 261 sdb.journal.append(refundChange{prev: sdb.refund}) 262 sdb.refund += gas 263 } 264 265 // SubRefund removes gas from the refund counter. 266 // This method will panic if the refund counter goes below zero 267 func (sdb *IntraBlockState) SubRefund(gas uint64) { 268 sdb.journal.append(refundChange{prev: sdb.refund}) 269 if gas > sdb.refund { 270 sdb.setErrorUnsafe(fmt.Errorf("refund counter below zero")) 271 } 272 sdb.refund -= gas 273 } 274 275 // Exist reports whether the given account address exists in the state. 276 // Notably this also returns true for suicided accounts. 277 func (sdb *IntraBlockState) Exist(addr types.Address) bool { 278 if sdb.tracer != nil { 279 err := sdb.tracer.CaptureAccountRead(addr) 280 if sdb.trace { 281 fmt.Println("CaptureAccountRead err", err) 282 } 283 } 284 s := sdb.getStateObject(addr) 285 return s != nil && !s.deleted 286 } 287 288 // Empty returns whether the state object is either non-existent 289 // or empty according to the EIP161 specification (balance = nonce = code = 0) 290 func (sdb *IntraBlockState) Empty(addr types.Address) bool { 291 if sdb.tracer != nil { 292 err := sdb.tracer.CaptureAccountRead(addr) 293 if sdb.trace { 294 fmt.Println("CaptureAccountRead err", err) 295 } 296 } 297 so := sdb.getStateObject(addr) 298 return so == nil || so.deleted || so.empty() 299 } 300 301 // GetBalance retrieves the balance from the given address or 0 if object not found 302 // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account 303 func (sdb *IntraBlockState) GetBalance(addr types.Address) *uint256.Int { 304 if sdb.tracer != nil { 305 err := sdb.tracer.CaptureAccountRead(addr) 306 if sdb.trace { 307 fmt.Println("CaptureAccountRead err", err) 308 } 309 } 310 stateObject := sdb.getStateObject(addr) 311 if stateObject != nil && !stateObject.deleted { 312 return stateObject.Balance() 313 } 314 return uint256.NewInt(0) 315 } 316 317 // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account 318 func (sdb *IntraBlockState) GetNonce(addr types.Address) uint64 { 319 if sdb.tracer != nil { 320 err := sdb.tracer.CaptureAccountRead(addr) 321 if sdb.trace { 322 fmt.Println("CaptureAccountRead err", err) 323 } 324 } 325 stateObject := sdb.getStateObject(addr) 326 if stateObject != nil && !stateObject.deleted { 327 return stateObject.Nonce() 328 } 329 330 return 0 331 } 332 333 // TxIndex returns the current transaction index set by Prepare. 334 func (sdb *IntraBlockState) TxIndex() int { 335 return sdb.txIndex 336 } 337 338 // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account 339 func (sdb *IntraBlockState) GetCode(addr types.Address) []byte { 340 if sdb.tracer != nil { 341 err := sdb.tracer.CaptureAccountRead(addr) 342 if sdb.trace { 343 fmt.Println("CaptureAccountRead err", err) 344 } 345 } 346 stateObject := sdb.getStateObject(addr) 347 if stateObject != nil && !stateObject.deleted { 348 if sdb.trace { 349 fmt.Printf("GetCode %x, returned %d\n", addr, len(stateObject.Code())) 350 } 351 code := stateObject.Code() 352 if len(code) > 0 && sdb.codeMap != nil { 353 sdb.codeMap[types.BytesToHash(stateObject.CodeHash())] = code 354 } 355 return code 356 } 357 if sdb.trace { 358 fmt.Printf("GetCode %x, returned nil\n", addr) 359 } 360 return nil 361 } 362 363 // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account 364 func (sdb *IntraBlockState) GetCodeSize(addr types.Address) int { 365 if sdb.tracer != nil { 366 err := sdb.tracer.CaptureAccountRead(addr) 367 if sdb.trace { 368 fmt.Println("CaptureAccountRead err", err) 369 } 370 } 371 stateObject := sdb.getStateObject(addr) 372 if stateObject == nil || stateObject.deleted { 373 return 0 374 } 375 if stateObject.code != nil { 376 return len(stateObject.code) 377 } 378 len, err := sdb.stateReader.ReadAccountCodeSize(addr, stateObject.data.Incarnation, stateObject.data.CodeHash) 379 if err != nil { 380 sdb.setErrorUnsafe(err) 381 } 382 if len > 0 && sdb.codeMap != nil { 383 code, _ := sdb.stateReader.ReadAccountCode(addr, stateObject.data.Incarnation, types.BytesToHash(stateObject.CodeHash())) 384 sdb.codeMap[types.BytesToHash(stateObject.CodeHash())] = code 385 } 386 return len 387 } 388 389 // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account 390 func (sdb *IntraBlockState) GetCodeHash(addr types.Address) types.Hash { 391 if sdb.tracer != nil { 392 err := sdb.tracer.CaptureAccountRead(addr) 393 if sdb.trace { 394 fmt.Println("CaptureAccountRead err", err) 395 } 396 } 397 stateObject := sdb.getStateObject(addr) 398 if stateObject == nil || stateObject.deleted { 399 return types.Hash{} 400 } 401 return types.BytesToHash(stateObject.CodeHash()) 402 } 403 404 // GetState retrieves a value from the given account's storage trie. 405 // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account 406 func (sdb *IntraBlockState) GetState(addr types.Address, key *types.Hash, value *uint256.Int) { 407 stateObject := sdb.getStateObject(addr) 408 if stateObject != nil && !stateObject.deleted { 409 stateObject.GetState(key, value) 410 } else { 411 value.Clear() 412 } 413 } 414 415 // GetCommittedState retrieves a value from the given account's committed storage trie. 416 // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account 417 func (sdb *IntraBlockState) GetCommittedState(addr types.Address, key *types.Hash, value *uint256.Int) { 418 stateObject := sdb.getStateObject(addr) 419 if stateObject != nil && !stateObject.deleted { 420 stateObject.GetCommittedState(key, value) 421 } else { 422 value.Clear() 423 } 424 } 425 426 func (sdb *IntraBlockState) HasSuicided(addr types.Address) bool { 427 stateObject := sdb.getStateObject(addr) 428 if stateObject == nil { 429 return false 430 } 431 if stateObject.deleted { 432 return false 433 } 434 if stateObject.created { 435 return false 436 } 437 return stateObject.selfdestructed 438 } 439 440 /* 441 * SETTERS 442 */ 443 444 // AddBalance adds amount to the account associated with addr. 445 // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account 446 func (sdb *IntraBlockState) AddBalance(addr types.Address, amount *uint256.Int) { 447 if sdb.trace { 448 fmt.Printf("AddBalance %x, %d\n", addr, amount) 449 } 450 if sdb.tracer != nil { 451 err := sdb.tracer.CaptureAccountWrite(addr) 452 if sdb.trace { 453 fmt.Println("CaptureAccountWrite err", err) 454 } 455 } 456 // If this account has not been read, add to the balance increment map 457 _, needAccount := sdb.stateObjects[addr] 458 if !needAccount && addr == ripemd && amount.IsZero() { 459 needAccount = true 460 } 461 if !needAccount { 462 sdb.journal.append(balanceIncrease{ 463 account: &addr, 464 increase: *amount, 465 }) 466 bi, ok := sdb.balanceInc[addr] 467 if !ok { 468 bi = &BalanceIncrease{} 469 sdb.balanceInc[addr] = bi 470 } 471 bi.increase.Add(&bi.increase, amount) 472 bi.count++ 473 return 474 } 475 476 stateObject := sdb.GetOrNewStateObject(addr) 477 stateObject.AddBalance(amount) 478 } 479 480 // SubBalance subtracts amount from the account associated with addr. 481 // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account 482 func (sdb *IntraBlockState) SubBalance(addr types.Address, amount *uint256.Int) { 483 if sdb.trace { 484 fmt.Printf("SubBalance %x, %d\n", addr, amount) 485 } 486 if sdb.tracer != nil { 487 err := sdb.tracer.CaptureAccountWrite(addr) 488 if sdb.trace { 489 fmt.Println("CaptureAccountWrite err", err) 490 } 491 492 } 493 494 stateObject := sdb.GetOrNewStateObject(addr) 495 if stateObject != nil { 496 stateObject.SubBalance(amount) 497 } 498 } 499 500 // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account 501 func (sdb *IntraBlockState) SetBalance(addr types.Address, amount *uint256.Int) { 502 if sdb.tracer != nil { 503 err := sdb.tracer.CaptureAccountWrite(addr) 504 if sdb.trace { 505 fmt.Println("CaptureAccountWrite err", err) 506 } 507 } 508 509 stateObject := sdb.GetOrNewStateObject(addr) 510 if stateObject != nil { 511 stateObject.SetBalance(amount) 512 } 513 } 514 515 // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account 516 func (sdb *IntraBlockState) SetNonce(addr types.Address, nonce uint64) { 517 if sdb.tracer != nil { 518 err := sdb.tracer.CaptureAccountWrite(addr) 519 if sdb.trace { 520 fmt.Println("CaptureAccountWrite err", err) 521 } 522 } 523 524 stateObject := sdb.GetOrNewStateObject(addr) 525 if stateObject != nil { 526 stateObject.SetNonce(nonce) 527 } 528 } 529 530 // DESCRIBED: docs/programmers_guide/guide.md#code-hash 531 // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account 532 func (sdb *IntraBlockState) SetCode(addr types.Address, code []byte) { 533 if sdb.tracer != nil { 534 err := sdb.tracer.CaptureAccountWrite(addr) 535 if sdb.trace { 536 fmt.Println("CaptureAccountWrite err", err) 537 } 538 } 539 540 stateObject := sdb.GetOrNewStateObject(addr) 541 if stateObject != nil { 542 stateObject.SetCode(crypto.Keccak256Hash(code), code) 543 } 544 } 545 546 // DESCRIBED: docs/programmers_guide/guide.md#address---identifier-of-an-account 547 func (sdb *IntraBlockState) SetState(addr types.Address, key *types.Hash, value uint256.Int) { 548 stateObject := sdb.GetOrNewStateObject(addr) 549 if stateObject != nil { 550 stateObject.SetState(key, value) 551 } 552 } 553 554 // SetStorage replaces the entire storage for the specified account with given 555 // storage. This function should only be used for debugging. 556 func (sdb *IntraBlockState) SetStorage(addr types.Address, storage Storage) { 557 stateObject := sdb.GetOrNewStateObject(addr) 558 if stateObject != nil { 559 stateObject.SetStorage(storage) 560 } 561 } 562 563 // SetIncarnation sets incarnation for account if account exists 564 func (sdb *IntraBlockState) SetIncarnation(addr types.Address, incarnation uint16) { 565 stateObject := sdb.GetOrNewStateObject(addr) 566 if stateObject != nil { 567 stateObject.setIncarnation(incarnation) 568 } 569 } 570 571 func (sdb *IntraBlockState) GetIncarnation(addr types.Address) uint16 { 572 stateObject := sdb.getStateObject(addr) 573 if stateObject != nil { 574 return stateObject.data.Incarnation 575 } 576 return 0 577 } 578 579 // Suicide marks the given account as suicided. 580 // This clears the account balance. 581 // 582 // The account's state object is still available until the state is committed, 583 // getStateObject will return a non-nil account after Suicide. 584 func (sdb *IntraBlockState) Suicide(addr types.Address) bool { 585 if sdb.tracer != nil { 586 err := sdb.tracer.CaptureAccountRead(addr) 587 if sdb.trace { 588 fmt.Println("CaptureAccountRead err", err) 589 } 590 err = sdb.tracer.CaptureAccountWrite(addr) 591 if sdb.trace { 592 fmt.Println("CaptureAccountWrite err", err) 593 } 594 } 595 stateObject := sdb.getStateObject(addr) 596 if stateObject == nil || stateObject.deleted { 597 return false 598 } 599 sdb.journal.append(selfdestructChange{ 600 account: &addr, 601 prev: stateObject.selfdestructed, 602 prevbalance: *stateObject.Balance(), 603 }) 604 stateObject.markSelfdestructed() 605 stateObject.created = false 606 stateObject.data.Balance.Clear() 607 608 return true 609 } 610 611 func (sdb *IntraBlockState) getStateObject(addr types.Address) (stateObject *stateObject) { 612 // Prefer 'live' objects. 613 if obj := sdb.stateObjects[addr]; obj != nil { 614 return obj 615 } 616 617 // Load the object from the database. 618 if _, ok := sdb.nilAccounts[addr]; ok { 619 if bi, ok := sdb.balanceInc[addr]; ok && !bi.transferred { 620 return sdb.createObject(addr, nil) 621 } 622 return nil 623 } 624 account, err := sdb.stateReader.ReadAccountData(addr) 625 if err != nil { 626 sdb.setErrorUnsafe(err) 627 return nil 628 } 629 if account == nil { 630 sdb.nilAccounts[addr] = struct{}{} 631 if bi, ok := sdb.balanceInc[addr]; ok && !bi.transferred { 632 return sdb.createObject(addr, nil) 633 } 634 return nil 635 } 636 637 // snap write 638 if sdb.snap != nil && sdb.snap.CanWrite() { 639 sdb.snap.AddAccount(addr, account) 640 } 641 642 // Insert into the live set. 643 obj := newObject(sdb, addr, account, account) 644 sdb.setStateObject(addr, obj) 645 return obj 646 } 647 648 func (sdb *IntraBlockState) setStateObject(addr types.Address, object *stateObject) { 649 if bi, ok := sdb.balanceInc[addr]; ok && !bi.transferred { 650 object.data.Balance.Add(&object.data.Balance, &bi.increase) 651 bi.transferred = true 652 sdb.journal.append(balanceIncreaseTransfer{bi: bi}) 653 } 654 sdb.stateObjects[addr] = object 655 } 656 657 // Retrieve a state object or create a new state object if nil. 658 func (sdb *IntraBlockState) GetOrNewStateObject(addr types.Address) *stateObject { 659 stateObject := sdb.getStateObject(addr) 660 if stateObject == nil || stateObject.deleted { 661 stateObject = sdb.createObject(addr, stateObject /* previous */) 662 } 663 return stateObject 664 } 665 666 // createObject creates a new state object. If there is an existing account with 667 // the given address, it is overwritten. 668 func (sdb *IntraBlockState) createObject(addr types.Address, previous *stateObject) (newobj *stateObject) { 669 ac := new(account.StateAccount) 670 var original *account.StateAccount 671 if previous == nil { 672 original = &account.StateAccount{} 673 } else { 674 original = &previous.original 675 } 676 newobj = newObject(sdb, addr, ac, original) 677 newobj.setNonce(0) // sets the object to dirty 678 if previous == nil { 679 sdb.journal.append(createObjectChange{account: &addr}) 680 } else { 681 sdb.journal.append(resetObjectChange{account: &addr, prev: previous}) 682 } 683 sdb.setStateObject(addr, newobj) 684 return newobj 685 } 686 687 // CreateAccount explicitly creates a state object. If a state object with the address 688 // already exists the balance is carried over to the new account. 689 // 690 // CreateAccount is called during the EVM CREATE operation. The situation might arise that 691 // a contract does the following: 692 // 693 // 1. sends funds to sha(account ++ (nonce + 1)) 694 // 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1) 695 // 696 // Carrying over the balance ensures that AMT doesn't disappear. 697 func (sdb *IntraBlockState) CreateAccount(addr types.Address, contractCreation bool) { 698 if sdb.tracer != nil { 699 err := sdb.tracer.CaptureAccountRead(addr) 700 if sdb.trace && err != nil { 701 log.Error("error while CaptureAccountRead", "err", err) 702 } 703 704 err = sdb.tracer.CaptureAccountWrite(addr) 705 if sdb.trace && err != nil { 706 log.Error("error while CaptureAccountWrite", "err", err) 707 } 708 } 709 710 var prevInc uint16 711 previous := sdb.getStateObject(addr) 712 if contractCreation { 713 if previous != nil && previous.selfdestructed { 714 prevInc = previous.data.Incarnation 715 } else { 716 inc, err := sdb.stateReader.ReadAccountIncarnation(addr) 717 if sdb.trace && err != nil { 718 log.Error("error while ReadAccountIncarnation", "err", err) 719 } 720 if err == nil { 721 prevInc = inc 722 } 723 } 724 } 725 726 newObj := sdb.createObject(addr, previous) 727 if previous != nil { 728 newObj.data.Balance.Set(&previous.data.Balance) 729 newObj.data.Initialised = true 730 } 731 732 if contractCreation { 733 newObj.created = true 734 newObj.data.Incarnation = prevInc + 1 735 } else { 736 newObj.selfdestructed = false 737 } 738 } 739 740 // Snapshot returns an identifier for the current revision of the state. 741 func (sdb *IntraBlockState) Snapshot() int { 742 id := sdb.nextRevisionID 743 sdb.nextRevisionID++ 744 sdb.validRevisions = append(sdb.validRevisions, revision{id, sdb.journal.length()}) 745 return id 746 } 747 748 // RevertToSnapshot reverts all state changes made since the given revision. 749 func (sdb *IntraBlockState) RevertToSnapshot(revid int) { 750 // Find the snapshot in the stack of valid snapshots. 751 idx := sort.Search(len(sdb.validRevisions), func(i int) bool { 752 return sdb.validRevisions[i].id >= revid 753 }) 754 if idx == len(sdb.validRevisions) || sdb.validRevisions[idx].id != revid { 755 panic(fmt.Errorf("revision id %v cannot be reverted", revid)) 756 } 757 snapshot := sdb.validRevisions[idx].journalIndex 758 759 // Replay the journal to undo changes and remove invalidated snapshots 760 sdb.journal.revert(sdb, snapshot) 761 sdb.validRevisions = sdb.validRevisions[:idx] 762 } 763 764 // GetRefund returns the current value of the refund counter. 765 func (sdb *IntraBlockState) GetRefund() uint64 { 766 return sdb.refund 767 } 768 769 func updateAccount(EIP161Enabled bool, isAura bool, stateWriter StateWriter, addr types.Address, stateObject *stateObject, isDirty bool) error { 770 emptyRemoval := EIP161Enabled && stateObject.empty() && (!isAura || addr != SystemAddress) 771 if stateObject.selfdestructed || (isDirty && emptyRemoval) { 772 if err := stateWriter.DeleteAccount(addr, &stateObject.original); err != nil { 773 return err 774 } 775 stateObject.deleted = true 776 } 777 if isDirty && (stateObject.created || !stateObject.selfdestructed) && !emptyRemoval { 778 stateObject.deleted = false 779 // Write any contract code associated with the state object 780 if stateObject.code != nil && stateObject.dirtyCode { 781 if err := stateWriter.UpdateAccountCode(addr, stateObject.data.Incarnation, stateObject.data.CodeHash, stateObject.code); err != nil { 782 return err 783 } 784 } 785 if stateObject.created { 786 if err := stateWriter.CreateContract(addr); err != nil { 787 return err 788 } 789 } 790 if err := stateObject.updateTrie(stateWriter); err != nil { 791 return err 792 } 793 if err := stateWriter.UpdateAccountData(addr, &stateObject.original, &stateObject.data); err != nil { 794 return err 795 } 796 } 797 return nil 798 } 799 800 func printAccount(addr types.Address, stateObject *stateObject, isDirty bool) { 801 emptyRemoval := stateObject.empty() 802 if stateObject.selfdestructed || (isDirty && emptyRemoval) { 803 fmt.Printf("delete: %x\n", addr) 804 } 805 if isDirty && (stateObject.created || !stateObject.selfdestructed) && !emptyRemoval { 806 // Write any contract code associated with the state object 807 if stateObject.code != nil && stateObject.dirtyCode { 808 fmt.Printf("UpdateCode: %x,%x\n", addr, stateObject.CodeHash()) 809 } 810 if stateObject.created { 811 fmt.Printf("CreateContract: %x\n", addr) 812 } 813 stateObject.printTrie() 814 if stateObject.data.Balance.IsUint64() { 815 fmt.Printf("UpdateAccountData: %x, balance=%d, nonce=%d\n", addr, stateObject.data.Balance.Uint64(), stateObject.data.Nonce) 816 } else { 817 div := uint256.NewInt(1_000_000_000) 818 fmt.Printf("UpdateAccountData: %x, balance=%d*%d, nonce=%d\n", addr, uint256.NewInt(0).Div(&stateObject.data.Balance, div).Uint64(), div.Uint64(), stateObject.data.Nonce) 819 } 820 } 821 } 822 823 // FinalizeTx should be called after every transaction. 824 func (sdb *IntraBlockState) FinalizeTx(chainRules *params.Rules, stateWriter StateWriter) error { 825 for addr, bi := range sdb.balanceInc { 826 if !bi.transferred { 827 sdb.getStateObject(addr) 828 } 829 } 830 for addr := range sdb.journal.dirties { 831 so, exist := sdb.stateObjects[addr] 832 if !exist { 833 // ripeMD is 'touched' at block 1714175, in tx 0x1237f737031e40bcde4a8b7e717b2d15e3ecadfe49bb1bbc71ee9deb09c6fcf2 834 // That tx goes out of gas, and although the notion of 'touched' does not exist there, the 835 // touch-event will still be recorded in the journal. Since ripeMD is a special snowflake, 836 // it will persist in the journal even though the journal is reverted. In this special circumstance, 837 // it may exist in `sdb.journal.dirties` but not in `sdb.stateObjects`. 838 // Thus, we can safely ignore it here 839 continue 840 } 841 842 if err := updateAccount(chainRules.IsSpuriousDragon, chainRules.IsAura, stateWriter, addr, so, true); err != nil { 843 return err 844 } 845 846 sdb.stateObjectsDirty[addr] = struct{}{} 847 } 848 // Invalidate journal because reverting across transactions is not allowed. 849 sdb.clearJournalAndRefund() 850 return nil 851 } 852 853 func (sdb *IntraBlockState) SoftFinalise() { 854 for addr := range sdb.journal.dirties { 855 _, exist := sdb.stateObjects[addr] 856 if !exist { 857 // ripeMD is 'touched' at block 1714175, in tx 0x1237f737031e40bcde4a8b7e717b2d15e3ecadfe49bb1bbc71ee9deb09c6fcf2 858 // That tx goes out of gas, and although the notion of 'touched' does not exist there, the 859 // touch-event will still be recorded in the journal. Since ripeMD is a special snowflake, 860 // it will persist in the journal even though the journal is reverted. In this special circumstance, 861 // it may exist in `sdb.journal.dirties` but not in `sdb.stateObjects`. 862 // Thus, we can safely ignore it here 863 continue 864 } 865 sdb.stateObjectsDirty[addr] = struct{}{} 866 } 867 // Invalidate journal because reverting across transactions is not allowed. 868 sdb.clearJournalAndRefund() 869 } 870 871 // CommitBlock finalizes the state by removing the self destructed objects 872 // and clears the journal as well as the refunds. 873 func (sdb *IntraBlockState) CommitBlock(chainRules *params.Rules, stateWriter StateWriter) error { 874 for addr, bi := range sdb.balanceInc { 875 if !bi.transferred { 876 sdb.getStateObject(addr) 877 } 878 } 879 return sdb.MakeWriteSet(chainRules, stateWriter) 880 } 881 882 func (sdb *IntraBlockState) BalanceIncreaseSet() map[types.Address]uint256.Int { 883 s := map[types.Address]uint256.Int{} 884 for addr, bi := range sdb.balanceInc { 885 if !bi.transferred { 886 s[addr] = bi.increase 887 } 888 } 889 return s 890 } 891 892 func (sdb *IntraBlockState) MakeWriteSet(chainRules *params.Rules, stateWriter StateWriter) error { 893 for addr := range sdb.journal.dirties { 894 sdb.stateObjectsDirty[addr] = struct{}{} 895 } 896 for addr, stateObject := range sdb.stateObjects { 897 _, isDirty := sdb.stateObjectsDirty[addr] 898 if err := updateAccount(chainRules.IsSpuriousDragon, chainRules.IsAura, stateWriter, addr, stateObject, isDirty); err != nil { 899 return err 900 } 901 } 902 // Invalidate journal because reverting across transactions is not allowed. 903 sdb.clearJournalAndRefund() 904 return nil 905 } 906 907 func (sdb *IntraBlockState) Print() { 908 for addr, stateObject := range sdb.stateObjects { 909 _, isDirty := sdb.stateObjectsDirty[addr] 910 _, isDirty2 := sdb.journal.dirties[addr] 911 912 printAccount(addr, stateObject, isDirty || isDirty2) 913 } 914 } 915 916 // Prepare sets the current transaction hash and index and block hash which is 917 // used when the EVM emits new state logs. 918 func (sdb *IntraBlockState) Prepare(thash, bhash types.Hash, ti int) { 919 sdb.thash = thash 920 sdb.bhash = bhash 921 sdb.txIndex = ti 922 sdb.accessList = newAccessList() 923 } 924 925 // no not lock 926 func (sdb *IntraBlockState) clearJournalAndRefund() { 927 sdb.journal = newJournal() 928 sdb.validRevisions = sdb.validRevisions[:0] 929 sdb.refund = 0 930 } 931 932 // PrepareAccessList handles the preparatory steps for executing a state transition with 933 // regards to both EIP-2929 and EIP-2930: 934 // 935 // - Add sender to access list (2929) 936 // - Add destination to access list (2929) 937 // - Add precompiles to access list (2929) 938 // - Add the contents of the optional tx access list (2930) 939 // 940 // This method should only be called if Yolov3/Berlin/2929+2930 is applicable at the current number. 941 func (sdb *IntraBlockState) PrepareAccessList(sender types.Address, dst *types.Address, precompiles []types.Address, list transaction.AccessList) { 942 sdb.AddAddressToAccessList(sender) 943 if dst != nil { 944 sdb.AddAddressToAccessList(*dst) 945 // If it's a create-tx, the destination will be added inside evm.create 946 } 947 for _, addr := range precompiles { 948 sdb.AddAddressToAccessList(addr) 949 } 950 for _, el := range list { 951 sdb.AddAddressToAccessList(el.Address) 952 for _, key := range el.StorageKeys { 953 sdb.AddSlotToAccessList(el.Address, key) 954 } 955 } 956 } 957 958 // AddAddressToAccessList adds the given address to the access list 959 func (sdb *IntraBlockState) AddAddressToAccessList(addr types.Address) { 960 if sdb.accessList.AddAddress(addr) { 961 sdb.journal.append(accessListAddAccountChange{&addr}) 962 } 963 } 964 965 // AddSlotToAccessList adds the given (address, slot)-tuple to the access list 966 func (sdb *IntraBlockState) AddSlotToAccessList(addr types.Address, slot types.Hash) { 967 addrMod, slotMod := sdb.accessList.AddSlot(addr, slot) 968 if addrMod { 969 // In practice, this should not happen, since there is no way to enter the 970 // scope of 'address' without having the 'address' become already added 971 // to the access list (via call-variant, create, etc). 972 // Better safe than sorry, though 973 sdb.journal.append(accessListAddAccountChange{&addr}) 974 } 975 if slotMod { 976 sdb.journal.append(accessListAddSlotChange{ 977 address: &addr, 978 slot: &slot, 979 }) 980 } 981 } 982 983 // AddressInAccessList returns true if the given address is in the access list. 984 func (sdb *IntraBlockState) AddressInAccessList(addr types.Address) bool { 985 return sdb.accessList.ContainsAddress(addr) 986 } 987 988 // SlotInAccessList returns true if the given (address, slot)-tuple is in the access list. 989 func (sdb *IntraBlockState) SlotInAccessList(addr types.Address, slot types.Hash) (addressPresent bool, slotPresent bool) { 990 return sdb.accessList.Contains(addr, slot) 991 } 992 993 // GenerateRootHash calculate root hash 994 func (s *IntraBlockState) GenerateRootHash() types.Hash { 995 if len(s.stateObjectsDirty) == 0 { 996 return hash.NilHash 997 } 998 999 sortAds := make(types.Addresses, 0, len(s.stateObjectsDirty)) 1000 for a := range s.stateObjectsDirty { 1001 sortAds = append(sortAds, a) 1002 } 1003 sort.Sort(sortAds) 1004 // 1005 sha := hash.HasherPool.Get().(crypto.KeccakState) 1006 defer hash.HasherPool.Put(sha) 1007 sha.Reset() 1008 1009 for _, address := range sortAds { 1010 stateObject := s.getStateObject(address).data 1011 err := rlp.Encode(sha, []interface{}{ 1012 stateObject.Incarnation, 1013 stateObject.Balance, 1014 stateObject.Nonce, 1015 stateObject.Initialised, 1016 stateObject.CodeHash, 1017 stateObject.Root, 1018 }) 1019 if err != nil { 1020 panic("can't encode: " + err.Error()) 1021 } 1022 //log.Info("GenerateRootHash", "address", address) 1023 } 1024 1025 var root types.Hash 1026 sha.Read(root[:]) 1027 1028 //log.Info("GenerateRootHash ", "root", root.Hex()) 1029 1030 return root 1031 } 1032 1033 // IntermediateRoot root 1034 func (s *IntraBlockState) IntermediateRoot() types.Hash { 1035 return s.GenerateRootHash() 1036 } 1037 1038 func (sdb *IntraBlockState) HasSelfdestructed(addr types.Address) bool { 1039 stateObject := sdb.getStateObject(addr) 1040 if stateObject == nil { 1041 return false 1042 } 1043 if stateObject.deleted { 1044 return false 1045 } 1046 if stateObject.created { 1047 return false 1048 } 1049 return stateObject.selfdestructed 1050 } 1051 1052 // Selfdestruct marks the given account as suicided. 1053 // This clears the account balance. 1054 // 1055 // The account's state object is still available until the state is committed, 1056 // getStateObject will return a non-nil account after Suicide. 1057 func (sdb *IntraBlockState) Selfdestruct(addr types.Address) bool { 1058 stateObject := sdb.getStateObject(addr) 1059 if stateObject == nil || stateObject.deleted { 1060 return false 1061 } 1062 sdb.journal.append(selfdestructChange{ 1063 account: &addr, 1064 prev: stateObject.selfdestructed, 1065 prevbalance: *stateObject.Balance(), 1066 }) 1067 stateObject.markSelfdestructed() 1068 stateObject.created = false 1069 stateObject.data.Balance.Clear() 1070 1071 return true 1072 } 1073 1074 // BeforeStateRoot calculate used state hash 1075 // 1076 // it should be invoked after all txs exec 1077 func (sdb *IntraBlockState) BeforeStateRoot() (hash types.Hash) { 1078 if sdb.snap == nil { 1079 return types.Hash{} 1080 } 1081 sort.Sort(sdb.snap.Items) 1082 ch := sdb.CodeHashes() 1083 hs := make(HashCodes, 0, len(ch)) 1084 for k, v := range ch { 1085 hs = append(hs, &HashCode{Hash: k, Code: v}) 1086 } 1087 sort.Sort(hs) 1088 hasher := sha3.NewLegacyKeccak256() 1089 EncodeBeforeState(hasher, sdb.snap.Items, hs) 1090 hasher.(crypto.KeccakState).Read(hash[:]) 1091 return 1092 }