github.com/iotexproject/iotex-core@v1.14.1-rc1/action/protocol/execution/evm/evmstatedbadapter.go (about) 1 // Copyright (c) 2019 IoTeX Foundation 2 // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability 3 // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed. 4 // This source code is governed by Apache License 2.0 that can be found in the LICENSE file. 5 6 package evm 7 8 import ( 9 "bytes" 10 "encoding/hex" 11 "fmt" 12 "math/big" 13 "sort" 14 15 "github.com/ethereum/go-ethereum/common" 16 "github.com/ethereum/go-ethereum/core/types" 17 "github.com/ethereum/go-ethereum/params" 18 "github.com/pkg/errors" 19 "go.uber.org/zap" 20 21 "github.com/iotexproject/go-pkgs/hash" 22 "github.com/iotexproject/iotex-address/address" 23 "github.com/iotexproject/iotex-proto/golang/iotextypes" 24 25 "github.com/iotexproject/iotex-core/action" 26 "github.com/iotexproject/iotex-core/action/protocol" 27 accountutil "github.com/iotexproject/iotex-core/action/protocol/account/util" 28 "github.com/iotexproject/iotex-core/db/trie" 29 "github.com/iotexproject/iotex-core/pkg/log" 30 "github.com/iotexproject/iotex-core/state" 31 ) 32 33 type ( 34 // deleteAccount records the account/contract to be deleted 35 deleteAccount map[hash.Hash160]struct{} 36 37 // contractMap records the contracts being changed 38 contractMap map[hash.Hash160]Contract 39 40 // preimageMap records the preimage of hash reported by VM 41 preimageMap map[common.Hash]protocol.SerializableBytes 42 43 // StateDBAdapter represents the state db adapter for evm to access iotx blockchain 44 StateDBAdapter struct { 45 sm protocol.StateManager 46 logs []*action.Log 47 transactionLogs []*action.TransactionLog 48 err error 49 blockHeight uint64 50 executionHash hash.Hash256 51 lastAddBalanceAddr string 52 lastAddBalanceAmount *big.Int 53 refund uint64 54 refundSnapshot map[int]uint64 55 cachedContract contractMap 56 contractSnapshot map[int]contractMap // snapshots of contracts 57 suicided deleteAccount // account/contract calling Suicide 58 suicideSnapshot map[int]deleteAccount // snapshots of suicide accounts 59 preimages preimageMap 60 preimageSnapshot map[int]preimageMap 61 accessList *accessList // per-transaction access list 62 accessListSnapshot map[int]*accessList 63 logsSnapshot map[int]int // logs is an array, save len(logs) at time of snapshot suffices 64 txLogsSnapshot map[int]int 65 notFixTopicCopyBug bool 66 asyncContractTrie bool 67 disableSortCachedContracts bool 68 useConfirmedNonce bool 69 legacyNonceAccount bool 70 fixSnapshotOrder bool 71 revertLog bool 72 manualCorrectGasRefund bool 73 suicideTxLogMismatchPanic bool 74 zeroNonceForFreshAccount bool 75 } 76 ) 77 78 // StateDBAdapterOption set StateDBAdapter construction param 79 type StateDBAdapterOption func(*StateDBAdapter) error 80 81 // DisableSortCachedContractsOption set disable sort cached contracts as true 82 func DisableSortCachedContractsOption() StateDBAdapterOption { 83 return func(adapter *StateDBAdapter) error { 84 adapter.disableSortCachedContracts = true 85 return nil 86 } 87 } 88 89 // NotFixTopicCopyBugOption set notFixTopicCopyBug as true 90 func NotFixTopicCopyBugOption() StateDBAdapterOption { 91 return func(adapter *StateDBAdapter) error { 92 adapter.notFixTopicCopyBug = true 93 return nil 94 } 95 } 96 97 // AsyncContractTrieOption set asyncContractTrie as true 98 func AsyncContractTrieOption() StateDBAdapterOption { 99 return func(adapter *StateDBAdapter) error { 100 adapter.asyncContractTrie = true 101 return nil 102 } 103 } 104 105 // UseConfirmedNonceOption set usePendingNonce as true 106 func UseConfirmedNonceOption() StateDBAdapterOption { 107 return func(adapter *StateDBAdapter) error { 108 adapter.useConfirmedNonce = true 109 return nil 110 } 111 } 112 113 // LegacyNonceAccountOption set legacyNonceAccount as true 114 func LegacyNonceAccountOption() StateDBAdapterOption { 115 return func(adapter *StateDBAdapter) error { 116 adapter.legacyNonceAccount = true 117 return nil 118 } 119 } 120 121 // FixSnapshotOrderOption set fixSnapshotOrder as true 122 func FixSnapshotOrderOption() StateDBAdapterOption { 123 return func(adapter *StateDBAdapter) error { 124 adapter.fixSnapshotOrder = true 125 return nil 126 } 127 } 128 129 // RevertLogOption set revertLog as true 130 func RevertLogOption() StateDBAdapterOption { 131 return func(adapter *StateDBAdapter) error { 132 adapter.revertLog = true 133 return nil 134 } 135 } 136 137 // ManualCorrectGasRefundOption set manualCorrectGasRefund as true 138 func ManualCorrectGasRefundOption() StateDBAdapterOption { 139 return func(adapter *StateDBAdapter) error { 140 // before London EVM activation (at Okhotsk height), in certain cases dynamicGas 141 // has caused gas refund to change, which needs to be manually adjusted after 142 // the tx is reverted. After Okhotsk height, it is fixed inside RevertToSnapshot() 143 adapter.manualCorrectGasRefund = true 144 return nil 145 } 146 } 147 148 // SuicideTxLogMismatchPanicOption set suicideTxLogMismatchPanic as true 149 func SuicideTxLogMismatchPanicOption() StateDBAdapterOption { 150 return func(adapter *StateDBAdapter) error { 151 adapter.suicideTxLogMismatchPanic = true 152 return nil 153 } 154 } 155 156 // ZeroNonceForFreshAccountOption set zeroNonceForFreshAccount as true 157 func ZeroNonceForFreshAccountOption() StateDBAdapterOption { 158 return func(adapter *StateDBAdapter) error { 159 adapter.zeroNonceForFreshAccount = true 160 return nil 161 } 162 } 163 164 // NewStateDBAdapter creates a new state db with iotex blockchain 165 func NewStateDBAdapter( 166 sm protocol.StateManager, 167 blockHeight uint64, 168 executionHash hash.Hash256, 169 opts ...StateDBAdapterOption, 170 ) (*StateDBAdapter, error) { 171 s := &StateDBAdapter{ 172 sm: sm, 173 logs: []*action.Log{}, 174 err: nil, 175 blockHeight: blockHeight, 176 executionHash: executionHash, 177 lastAddBalanceAmount: new(big.Int), 178 refundSnapshot: make(map[int]uint64), 179 cachedContract: make(contractMap), 180 contractSnapshot: make(map[int]contractMap), 181 suicided: make(deleteAccount), 182 suicideSnapshot: make(map[int]deleteAccount), 183 preimages: make(preimageMap), 184 preimageSnapshot: make(map[int]preimageMap), 185 accessList: newAccessList(), 186 accessListSnapshot: make(map[int]*accessList), 187 logsSnapshot: make(map[int]int), 188 txLogsSnapshot: make(map[int]int), 189 } 190 for _, opt := range opts { 191 if err := opt(s); err != nil { 192 return nil, errors.Wrap(err, "failed to execute stateDB creation option") 193 } 194 } 195 // TODO: add combination limitation for useZeroNonceForFreshAccount 196 if !s.legacyNonceAccount && s.useConfirmedNonce { 197 return nil, errors.New("invalid parameter combination") 198 } 199 return s, nil 200 } 201 202 func (stateDB *StateDBAdapter) logError(err error) { 203 if stateDB.err == nil { 204 stateDB.err = err 205 } 206 } 207 208 // Error returns the first stored error during evm contract execution 209 func (stateDB *StateDBAdapter) Error() error { 210 return stateDB.err 211 } 212 213 func (stateDB *StateDBAdapter) accountCreationOpts() []state.AccountCreationOption { 214 if stateDB.legacyNonceAccount { 215 return []state.AccountCreationOption{state.LegacyNonceAccountTypeOption()} 216 } 217 return nil 218 } 219 220 // CreateAccount creates an account in iotx blockchain 221 func (stateDB *StateDBAdapter) CreateAccount(evmAddr common.Address) { 222 addr, err := address.FromBytes(evmAddr.Bytes()) 223 if err != nil { 224 log.L().Error("Failed to convert evm address.", zap.Error(err)) 225 return 226 } 227 _, err = accountutil.LoadOrCreateAccount(stateDB.sm, addr, stateDB.accountCreationOpts()...) 228 if err != nil { 229 log.L().Error("Failed to create account.", zap.Error(err)) 230 stateDB.logError(err) 231 return 232 } 233 log.L().Debug("Called CreateAccount.", log.Hex("addrHash", evmAddr[:])) 234 } 235 236 // SubBalance subtracts balance from account 237 func (stateDB *StateDBAdapter) SubBalance(evmAddr common.Address, amount *big.Int) { 238 if amount.Cmp(big.NewInt(int64(0))) == 0 { 239 return 240 } 241 // stateDB.GetBalance(evmAddr) 242 log.L().Debug(fmt.Sprintf("SubBalance %v from %s", amount, evmAddr.Hex())) 243 addr, err := address.FromBytes(evmAddr.Bytes()) 244 if err != nil { 245 log.L().Error("Failed to convert evm address.", zap.Error(err)) 246 return 247 } 248 state, err := stateDB.accountState(evmAddr) 249 if err != nil { 250 log.L().Error("Failed to sub balance.", zap.Error(err)) 251 stateDB.logError(err) 252 return 253 } 254 if err := state.SubBalance(amount); err != nil { 255 log.L().Error("Failed to sub balance.", zap.Error(err)) 256 stateDB.logError(err) 257 return 258 } 259 if err := accountutil.StoreAccount(stateDB.sm, addr, state); err != nil { 260 log.L().Error("Failed to update pending account changes to trie.", zap.Error(err)) 261 stateDB.logError(err) 262 } 263 } 264 265 // AddBalance adds balance to account 266 func (stateDB *StateDBAdapter) AddBalance(evmAddr common.Address, amount *big.Int) { 267 stateDB.lastAddBalanceAmount.SetUint64(0) 268 if amount.Cmp(big.NewInt(int64(0))) == 0 { 269 return 270 } 271 // stateDB.GetBalance(evmAddr) 272 log.L().Debug(fmt.Sprintf("AddBalance %v to %s", amount, evmAddr.Hex())) 273 274 addr, err := address.FromBytes(evmAddr.Bytes()) 275 if err != nil { 276 log.L().Error("Failed to convert evm address.", zap.Error(err)) 277 return 278 } 279 var ( 280 state *state.Account 281 addrHash = hash.BytesToHash160(evmAddr[:]) 282 ) 283 if contract, ok := stateDB.cachedContract[addrHash]; ok { 284 state = contract.SelfState() 285 } else { 286 state, err = accountutil.LoadOrCreateAccount(stateDB.sm, addr, stateDB.accountCreationOpts()...) 287 if err != nil { 288 log.L().Error("Failed to add balance.", log.Hex("addrHash", evmAddr[:])) 289 stateDB.logError(err) 290 return 291 } 292 } 293 if err := state.AddBalance(amount); err != nil { 294 log.L().Error("failed to add balance", zap.Error(err), zap.String("amount", amount.String())) 295 stateDB.logError(err) 296 return 297 } 298 if err := accountutil.StoreAccount(stateDB.sm, addr, state); err != nil { 299 log.L().Error("Failed to update pending account changes to trie.", zap.Error(err)) 300 stateDB.logError(err) 301 } else { 302 // keep a record of latest add balance 303 stateDB.lastAddBalanceAddr = addr.String() 304 stateDB.lastAddBalanceAmount.SetBytes(amount.Bytes()) 305 } 306 } 307 308 // GetBalance gets the balance of account 309 func (stateDB *StateDBAdapter) GetBalance(evmAddr common.Address) *big.Int { 310 state, err := stateDB.accountState(evmAddr) 311 if err != nil { 312 log.L().Error("Failed to get balance.", zap.Error(err)) 313 return big.NewInt(0) 314 } 315 log.L().Debug(fmt.Sprintf("Balance of %s is %v", evmAddr.Hex(), state.Balance)) 316 317 return state.Balance 318 } 319 320 // IsNewAccount returns true if this is a new account 321 func (stateDB *StateDBAdapter) IsNewAccount(evmAddr common.Address) bool { 322 state, err := stateDB.accountState(evmAddr) 323 if err != nil { 324 log.L().Error("failed to load account.", zap.Error(err), zap.String("address", evmAddr.Hex())) 325 return false 326 } 327 328 return state.IsNewbieAccount() 329 } 330 331 // GetNonce gets the nonce of account 332 func (stateDB *StateDBAdapter) GetNonce(evmAddr common.Address) uint64 { 333 var pendingNonce uint64 334 if stateDB.legacyNonceAccount { 335 pendingNonce = uint64(1) 336 } else { 337 pendingNonce = uint64(0) 338 } 339 state, err := stateDB.accountState(evmAddr) 340 if err != nil { 341 log.L().Error("Failed to get nonce.", zap.Error(err)) 342 // stateDB.logError(err) 343 } else { 344 if stateDB.zeroNonceForFreshAccount { 345 pendingNonce = state.PendingNonceConsideringFreshAccount() 346 } else { 347 pendingNonce = state.PendingNonce() 348 } 349 } 350 if stateDB.useConfirmedNonce { 351 if pendingNonce == 0 { 352 panic("invalid pending nonce") 353 } 354 pendingNonce-- 355 } 356 log.L().Debug("Called GetNonce.", 357 zap.String("address", evmAddr.Hex()), 358 zap.Uint64("pendingNonce", pendingNonce)) 359 360 return pendingNonce 361 } 362 363 // SetNonce sets the nonce of account 364 func (stateDB *StateDBAdapter) SetNonce(evmAddr common.Address, nonce uint64) { 365 addr, err := address.FromBytes(evmAddr.Bytes()) 366 if err != nil { 367 log.L().Error("Failed to convert evm address.", zap.Error(err)) 368 return 369 } 370 s, err := stateDB.accountState(evmAddr) 371 if err != nil { 372 log.L().Error("Failed to set nonce.", zap.Error(err)) 373 // stateDB.logError(err) 374 return 375 } 376 if !stateDB.useConfirmedNonce { 377 if nonce == 0 { 378 panic("invalid nonce zero") 379 } 380 nonce-- 381 } 382 log.L().Debug("Called SetNonce.", 383 zap.String("address", addr.String()), 384 zap.Uint64("nonce", nonce)) 385 if !s.IsNewbieAccount() || s.AccountType() != 0 || nonce != 0 || stateDB.zeroNonceForFreshAccount { 386 if err := s.SetPendingNonce(nonce + 1); err != nil { 387 log.L().Panic("Failed to set nonce.", zap.Error(err), zap.String("addr", addr.Hex()), zap.Uint64("pendingNonce", s.PendingNonce()), zap.Uint64("nonce", nonce), zap.String("execution", hex.EncodeToString(stateDB.executionHash[:]))) 388 stateDB.logError(err) 389 } 390 } 391 if err := accountutil.StoreAccount(stateDB.sm, addr, s); err != nil { 392 log.L().Error("Failed to store account.", zap.Error(err)) 393 stateDB.logError(err) 394 } 395 } 396 397 // SubRefund subtracts refund 398 func (stateDB *StateDBAdapter) SubRefund(gas uint64) { 399 log.L().Debug("Called SubRefund.", zap.Uint64("gas", gas)) 400 // stateDB.journal.append(refundChange{prev: self.refund}) 401 if gas > stateDB.refund { 402 panic("Refund counter not enough!") 403 } 404 stateDB.refund -= gas 405 } 406 407 // AddRefund adds refund 408 func (stateDB *StateDBAdapter) AddRefund(gas uint64) { 409 log.L().Debug("Called AddRefund.", zap.Uint64("gas", gas)) 410 // stateDB.journal.append(refundChange{prev: self.refund}) 411 stateDB.refund += gas 412 } 413 414 // GetRefund gets refund 415 func (stateDB *StateDBAdapter) GetRefund() uint64 { 416 log.L().Debug("Called GetRefund.") 417 return stateDB.refund 418 } 419 420 // Suicide kills the contract 421 func (stateDB *StateDBAdapter) Suicide(evmAddr common.Address) bool { 422 if !stateDB.Exist(evmAddr) { 423 log.L().Debug("Account does not exist.", zap.String("address", evmAddr.Hex())) 424 return false 425 } 426 s, err := stateDB.accountState(evmAddr) 427 if err != nil { 428 log.L().Debug("Failed to get account.", zap.String("address", evmAddr.Hex())) 429 return false 430 } 431 // clears the account balance 432 actBalance := new(big.Int).Set(s.Balance) 433 if err := s.SubBalance(s.Balance); err != nil { 434 log.L().Debug("failed to clear balance", zap.Error(err), zap.String("address", evmAddr.Hex())) 435 return false 436 } 437 addrHash := hash.BytesToHash160(evmAddr.Bytes()) 438 if _, err := stateDB.sm.PutState(s, protocol.LegacyKeyOption(addrHash)); err != nil { 439 log.L().Error("Failed to kill contract.", zap.Error(err)) 440 stateDB.logError(err) 441 return false 442 } 443 // To ensure data consistency, generate this log after the hard-fork 444 // a separate patch file will be created later to provide missing logs before the hard-fork 445 // TODO: remove this gating once the hard-fork has passed 446 if stateDB.suicideTxLogMismatchPanic { 447 // before calling Suicide, EVM will transfer the contract's balance to beneficiary 448 // need to create a transaction log on successful suicide 449 if stateDB.lastAddBalanceAmount.Cmp(actBalance) == 0 { 450 if stateDB.lastAddBalanceAmount.Cmp(big.NewInt(0)) > 0 { 451 from, _ := address.FromBytes(evmAddr[:]) 452 stateDB.addTransactionLogs(&action.TransactionLog{ 453 Type: iotextypes.TransactionLogType_IN_CONTRACT_TRANSFER, 454 Sender: from.String(), 455 Recipient: stateDB.lastAddBalanceAddr, 456 Amount: stateDB.lastAddBalanceAmount, 457 }) 458 } 459 } else { 460 log.L().Panic("suicide contract's balance does not match", 461 zap.String("suicide", actBalance.String()), 462 zap.String("beneficiary", stateDB.lastAddBalanceAmount.String())) 463 } 464 } 465 // mark it as deleted 466 stateDB.suicided[addrHash] = struct{}{} 467 return true 468 } 469 470 // HasSuicided returns whether the contract has been killed 471 func (stateDB *StateDBAdapter) HasSuicided(evmAddr common.Address) bool { 472 addrHash := hash.BytesToHash160(evmAddr.Bytes()) 473 _, ok := stateDB.suicided[addrHash] 474 return ok 475 } 476 477 // SetTransientState sets transient storage for a given account 478 func (stateDB *StateDBAdapter) SetTransientState(addr common.Address, key, value common.Hash) { 479 log.S().Panic("SetTransientState not implemented") 480 } 481 482 // GetTransientState gets transient storage for a given account. 483 func (stateDB *StateDBAdapter) GetTransientState(addr common.Address, key common.Hash) common.Hash { 484 log.S().Panic("GetTransientState not implemented") 485 return common.Hash{} 486 } 487 488 // Exist checks the existence of an address 489 func (stateDB *StateDBAdapter) Exist(evmAddr common.Address) bool { 490 addr, err := address.FromBytes(evmAddr.Bytes()) 491 if err != nil { 492 log.L().Error("Failed to convert evm address.", zap.Error(err)) 493 return false 494 } 495 log.L().Debug("Check existence.", zap.String("address", addr.String()), log.Hex("addrHash", evmAddr[:])) 496 addrHash := hash.BytesToHash160(addr.Bytes()) 497 if _, ok := stateDB.cachedContract[addrHash]; ok { 498 return true 499 } 500 recorded, err := accountutil.Recorded(stateDB.sm, addr) 501 if !recorded || err != nil { 502 log.L().Debug("Account does not exist.", zap.String("address", addr.String())) 503 return false 504 } 505 return true 506 } 507 508 // Prepare handles the preparatory steps for executing a state transition with. 509 // This method must be invoked before state transition. 510 // 511 // Berlin fork: 512 // - Add sender to access list (2929) 513 // - Add destination to access list (2929) 514 // - Add precompiles to access list (2929) 515 // - Add the contents of the optional tx access list (2930) 516 // 517 // Potential EIPs: 518 // - Reset access list (Berlin) 519 // - Add coinbase to access list (EIP-3651) 520 // - Reset transient storage (EIP-1153) 521 func (stateDB *StateDBAdapter) Prepare(rules params.Rules, sender, coinbase common.Address, dst *common.Address, precompiles []common.Address, list types.AccessList) { 522 if !rules.IsBerlin { 523 return 524 } 525 stateDB.AddAddressToAccessList(sender) 526 if dst != nil { 527 stateDB.AddAddressToAccessList(*dst) 528 // If it's a create-tx, the destination will be added inside evm.create 529 } 530 for _, addr := range precompiles { 531 stateDB.AddAddressToAccessList(addr) 532 } 533 for _, el := range list { 534 stateDB.AddAddressToAccessList(el.Address) 535 for _, key := range el.StorageKeys { 536 stateDB.AddSlotToAccessList(el.Address, key) 537 } 538 } 539 if rules.IsShanghai { // EIP-3651: warm coinbase 540 stateDB.AddAddressToAccessList(coinbase) 541 } 542 } 543 544 // AddressInAccessList returns true if the given address is in the access list 545 func (stateDB *StateDBAdapter) AddressInAccessList(addr common.Address) bool { 546 return stateDB.accessList.ContainsAddress(addr) 547 } 548 549 // SlotInAccessList returns true if the given (address, slot)-tuple is in the access list 550 func (stateDB *StateDBAdapter) SlotInAccessList(addr common.Address, slot common.Hash) (addressOk bool, slotOk bool) { 551 return stateDB.accessList.Contains(addr, slot) 552 } 553 554 // AddAddressToAccessList adds the given address to the access list. This operation is safe to perform 555 // even if the feature/fork is not active yet 556 func (stateDB *StateDBAdapter) AddAddressToAccessList(addr common.Address) { 557 stateDB.accessList.AddAddress(addr) 558 } 559 560 // AddSlotToAccessList adds the given (address,slot) to the access list. This operation is safe to perform 561 // even if the feature/fork is not active yet 562 func (stateDB *StateDBAdapter) AddSlotToAccessList(addr common.Address, slot common.Hash) { 563 stateDB.accessList.AddSlot(addr, slot) 564 } 565 566 // Empty returns true if the the contract is empty 567 func (stateDB *StateDBAdapter) Empty(evmAddr common.Address) bool { 568 log.L().Debug("Check whether the contract is empty.") 569 s, err := stateDB.accountState(evmAddr) 570 if err != nil { 571 return true 572 } 573 // TODO: delete hash.ZeroHash256 574 return s.IsNewbieAccount() && 575 s.Balance.Sign() == 0 && 576 (len(s.CodeHash) == 0 || bytes.Equal(s.CodeHash, hash.ZeroHash256[:])) 577 } 578 579 // RevertToSnapshot reverts the state factory to the state at a given snapshot 580 func (stateDB *StateDBAdapter) RevertToSnapshot(snapshot int) { 581 if err := stateDB.sm.Revert(snapshot); err != nil { 582 err := errors.New("unexpected error: state manager's Revert() failed") 583 log.L().Error("Failed to revert to snapshot.", zap.Error(err)) 584 stateDB.logError(err) 585 return 586 } 587 ds, ok := stateDB.suicideSnapshot[snapshot] 588 if !ok { 589 // this should not happen, b/c we save the suicide accounts on a successful return of Snapshot(), but check anyway 590 log.L().Error("Failed to get snapshot.", zap.Int("snapshot", snapshot)) 591 return 592 } 593 // restore gas refund 594 if !stateDB.manualCorrectGasRefund { 595 stateDB.refund = stateDB.refundSnapshot[snapshot] 596 delete(stateDB.refundSnapshot, snapshot) 597 for i := snapshot + 1; ; i++ { 598 if _, ok := stateDB.refundSnapshot[i]; ok { 599 delete(stateDB.refundSnapshot, i) 600 } else { 601 break 602 } 603 } 604 } 605 // restore access list 606 stateDB.accessList = nil 607 stateDB.accessList = stateDB.accessListSnapshot[snapshot] 608 { 609 delete(stateDB.accessListSnapshot, snapshot) 610 for i := snapshot + 1; ; i++ { 611 if _, ok := stateDB.accessListSnapshot[i]; ok { 612 delete(stateDB.accessListSnapshot, i) 613 } else { 614 break 615 } 616 } 617 } 618 // restore logs and txLogs 619 if stateDB.revertLog { 620 stateDB.logs = stateDB.logs[:stateDB.logsSnapshot[snapshot]] 621 delete(stateDB.logsSnapshot, snapshot) 622 for i := snapshot + 1; ; i++ { 623 if _, ok := stateDB.logsSnapshot[i]; ok { 624 delete(stateDB.logsSnapshot, i) 625 } else { 626 break 627 } 628 } 629 stateDB.transactionLogs = stateDB.transactionLogs[:stateDB.txLogsSnapshot[snapshot]] 630 delete(stateDB.txLogsSnapshot, snapshot) 631 for i := snapshot + 1; ; i++ { 632 if _, ok := stateDB.txLogsSnapshot[i]; ok { 633 delete(stateDB.txLogsSnapshot, i) 634 } else { 635 break 636 } 637 } 638 } 639 // restore the suicide accounts 640 stateDB.suicided = nil 641 stateDB.suicided = ds 642 if stateDB.fixSnapshotOrder { 643 delete(stateDB.suicideSnapshot, snapshot) 644 for i := snapshot + 1; ; i++ { 645 if _, ok := stateDB.suicideSnapshot[i]; ok { 646 delete(stateDB.suicideSnapshot, i) 647 } else { 648 break 649 } 650 } 651 } 652 // restore modified contracts 653 stateDB.cachedContract = nil 654 stateDB.cachedContract = stateDB.contractSnapshot[snapshot] 655 for _, addr := range stateDB.cachedContractAddrs() { 656 c := stateDB.cachedContract[addr] 657 if err := c.LoadRoot(); err != nil { 658 log.L().Error("Failed to load root for contract.", zap.Error(err), log.Hex("addrHash", addr[:])) 659 return 660 } 661 } 662 if stateDB.fixSnapshotOrder { 663 delete(stateDB.contractSnapshot, snapshot) 664 for i := snapshot + 1; ; i++ { 665 if _, ok := stateDB.contractSnapshot[i]; ok { 666 delete(stateDB.contractSnapshot, i) 667 } else { 668 break 669 } 670 } 671 } 672 // restore preimages 673 stateDB.preimages = nil 674 stateDB.preimages = stateDB.preimageSnapshot[snapshot] 675 if stateDB.fixSnapshotOrder { 676 delete(stateDB.preimageSnapshot, snapshot) 677 for i := snapshot + 1; ; i++ { 678 if _, ok := stateDB.preimageSnapshot[i]; ok { 679 delete(stateDB.preimageSnapshot, i) 680 } else { 681 break 682 } 683 } 684 } 685 } 686 687 func (stateDB *StateDBAdapter) cachedContractAddrs() []hash.Hash160 { 688 addrs := make([]hash.Hash160, 0, len(stateDB.cachedContract)) 689 for addr := range stateDB.cachedContract { 690 addrs = append(addrs, addr) 691 } 692 if !stateDB.disableSortCachedContracts { 693 sort.Slice(addrs, func(i, j int) bool { return bytes.Compare(addrs[i][:], addrs[j][:]) < 0 }) 694 } 695 return addrs 696 } 697 698 // Snapshot returns the snapshot id 699 func (stateDB *StateDBAdapter) Snapshot() int { 700 // save a copy of modified contracts 701 c := make(contractMap) 702 if stateDB.fixSnapshotOrder { 703 for _, addr := range stateDB.cachedContractAddrs() { 704 c[addr] = stateDB.cachedContract[addr].Snapshot() 705 } 706 } 707 sn := stateDB.sm.Snapshot() 708 if _, ok := stateDB.suicideSnapshot[sn]; ok { 709 err := errors.New("unexpected error: duplicate snapshot version") 710 if stateDB.fixSnapshotOrder { 711 log.L().Panic("Failed to snapshot.", zap.Error(err)) 712 } else { 713 log.L().Error("Failed to snapshot.", zap.Error(err)) 714 } 715 // stateDB.err = err 716 return sn 717 } 718 // record the current gas refund 719 stateDB.refundSnapshot[sn] = stateDB.refund 720 // record the current log size 721 if stateDB.revertLog { 722 stateDB.logsSnapshot[sn] = len(stateDB.logs) 723 stateDB.txLogsSnapshot[sn] = len(stateDB.transactionLogs) 724 } 725 // save a copy of current suicide accounts 726 sa := make(deleteAccount) 727 for k, v := range stateDB.suicided { 728 sa[k] = v 729 } 730 stateDB.suicideSnapshot[sn] = sa 731 if !stateDB.fixSnapshotOrder { 732 for _, addr := range stateDB.cachedContractAddrs() { 733 c[addr] = stateDB.cachedContract[addr].Snapshot() 734 } 735 } 736 stateDB.contractSnapshot[sn] = c 737 // save a copy of preimages 738 p := make(preimageMap) 739 for k, v := range stateDB.preimages { 740 p[k] = v 741 } 742 stateDB.preimageSnapshot[sn] = p 743 // save a copy of access list 744 stateDB.accessListSnapshot[sn] = stateDB.accessList.Copy() 745 return sn 746 } 747 748 // AddLog adds log whose transaction amount is larger than 0 749 func (stateDB *StateDBAdapter) AddLog(evmLog *types.Log) { 750 log.L().Debug("Called AddLog.", zap.Any("log", evmLog)) 751 addr, err := address.FromBytes(evmLog.Address.Bytes()) 752 if err != nil { 753 log.L().Error("Failed to convert evm address.", zap.Error(err)) 754 return 755 } 756 var topics []hash.Hash256 757 for _, evmTopic := range evmLog.Topics { 758 var topic hash.Hash256 759 copy(topic[:], evmTopic.Bytes()) 760 topics = append(topics, topic) 761 } 762 if topics[0] == _inContractTransfer { 763 if len(topics) != 3 { 764 panic("Invalid in contract transfer topics") 765 } 766 if amount, zero := new(big.Int).SetBytes(evmLog.Data), big.NewInt(0); amount.Cmp(zero) == 1 { 767 from, _ := address.FromBytes(topics[1][12:]) 768 to, _ := address.FromBytes(topics[2][12:]) 769 stateDB.addTransactionLogs(&action.TransactionLog{ 770 Type: iotextypes.TransactionLogType_IN_CONTRACT_TRANSFER, 771 Sender: from.String(), 772 Recipient: to.String(), 773 Amount: amount, 774 }) 775 } 776 return 777 } 778 779 stateDB.logs = append(stateDB.logs, &action.Log{ 780 Address: addr.String(), 781 Topics: topics, 782 Data: evmLog.Data, 783 BlockHeight: stateDB.blockHeight, 784 ActionHash: stateDB.executionHash, 785 NotFixTopicCopyBug: stateDB.notFixTopicCopyBug, 786 }) 787 } 788 789 // Logs returns the logs 790 func (stateDB *StateDBAdapter) Logs() []*action.Log { 791 return stateDB.logs 792 } 793 794 // TransactionLogs returns the transaction logs 795 func (stateDB *StateDBAdapter) TransactionLogs() []*action.TransactionLog { 796 return stateDB.transactionLogs 797 } 798 799 // AddPreimage adds the preimage of a hash 800 func (stateDB *StateDBAdapter) AddPreimage(hash common.Hash, preimage []byte) { 801 if _, ok := stateDB.preimages[hash]; !ok { 802 b := make([]byte, len(preimage)) 803 copy(b, preimage) 804 stateDB.preimages[hash] = b 805 } 806 } 807 808 // ForEachStorage loops each storage 809 func (stateDB *StateDBAdapter) ForEachStorage(addr common.Address, cb func(common.Hash, common.Hash) bool) error { 810 ctt, err := stateDB.getContract(hash.BytesToHash160(addr[:])) 811 if err != nil { 812 // stateDB.err = err 813 return err 814 } 815 iter, err := ctt.Iterator() 816 if err != nil { 817 // stateDB.err = err 818 return err 819 } 820 821 for { 822 key, value, err := iter.Next() 823 if err == trie.ErrEndOfIterator { 824 // hit the end of the iterator, exit now 825 return nil 826 } 827 if err != nil { 828 return err 829 } 830 ckey := common.Hash{} 831 copy(ckey[:], key[:]) 832 cvalue := common.Hash{} 833 copy(cvalue[:], value[:]) 834 if !cb(ckey, cvalue) { 835 return nil 836 } 837 } 838 } 839 840 // accountState returns an account state 841 func (stateDB *StateDBAdapter) accountState(evmAddr common.Address) (*state.Account, error) { 842 addrHash := hash.BytesToHash160(evmAddr.Bytes()) 843 if contract, ok := stateDB.cachedContract[addrHash]; ok { 844 return contract.SelfState(), nil 845 } 846 return accountutil.LoadAccountByHash160(stateDB.sm, addrHash, stateDB.accountCreationOpts()...) 847 } 848 849 func (stateDB *StateDBAdapter) addTransactionLogs(tlog *action.TransactionLog) { 850 stateDB.transactionLogs = append(stateDB.transactionLogs, tlog) 851 } 852 853 //====================================== 854 // Contract functions 855 //====================================== 856 857 // GetCodeHash returns contract's code hash 858 func (stateDB *StateDBAdapter) GetCodeHash(evmAddr common.Address) common.Hash { 859 addr := hash.BytesToHash160(evmAddr[:]) 860 codeHash := common.Hash{} 861 if contract, ok := stateDB.cachedContract[addr]; ok { 862 copy(codeHash[:], contract.SelfState().CodeHash) 863 return codeHash 864 } 865 account, err := accountutil.LoadAccountByHash160(stateDB.sm, addr, stateDB.accountCreationOpts()...) 866 if err != nil { 867 log.L().Error("Failed to get code hash.", zap.Error(err)) 868 // TODO (zhi) not all err should be logged 869 // stateDB.logError(err) 870 return codeHash 871 } 872 copy(codeHash[:], account.CodeHash) 873 return codeHash 874 } 875 876 // GetCode returns contract's code 877 func (stateDB *StateDBAdapter) GetCode(evmAddr common.Address) []byte { 878 addr := hash.BytesToHash160(evmAddr[:]) 879 if contract, ok := stateDB.cachedContract[addr]; ok { 880 code, err := contract.GetCode() 881 if err != nil { 882 log.L().Error("Failed to get code hash.", zap.Error(err)) 883 return nil 884 } 885 return code 886 } 887 account, err := accountutil.LoadAccountByHash160(stateDB.sm, addr, stateDB.accountCreationOpts()...) 888 if err != nil { 889 log.L().Error("Failed to load account state for address.", log.Hex("addrHash", addr[:])) 890 return nil 891 } 892 var code protocol.SerializableBytes 893 if _, err = stateDB.sm.State(&code, protocol.NamespaceOption(CodeKVNameSpace), protocol.KeyOption(account.CodeHash[:])); err != nil { 894 // TODO: Suppress the as it's too much now 895 //log.L().Error("Failed to get code from trie.", zap.Error(err)) 896 return nil 897 } 898 return code[:] 899 } 900 901 // GetCodeSize gets the code size saved in hash 902 func (stateDB *StateDBAdapter) GetCodeSize(evmAddr common.Address) int { 903 code := stateDB.GetCode(evmAddr) 904 if code == nil { 905 return 0 906 } 907 log.L().Debug("Called GetCodeSize.", log.Hex("addrHash", evmAddr[:])) 908 return len(code) 909 } 910 911 // SetCode sets contract's code 912 func (stateDB *StateDBAdapter) SetCode(evmAddr common.Address, code []byte) { 913 addr := hash.BytesToHash160(evmAddr[:]) 914 contract, err := stateDB.getContract(addr) 915 if err != nil { 916 log.L().Error("Failed to get contract.", zap.Error(err), log.Hex("addrHash", addr[:])) 917 stateDB.logError(err) 918 return 919 } 920 contract.SetCode(hash.Hash256b(code), code) 921 } 922 923 // GetCommittedState gets committed state 924 func (stateDB *StateDBAdapter) GetCommittedState(evmAddr common.Address, k common.Hash) common.Hash { 925 addr := hash.BytesToHash160(evmAddr[:]) 926 contract, err := stateDB.getContract(addr) 927 if err != nil { 928 log.L().Error("Failed to get contract.", zap.Error(err), log.Hex("addrHash", addr[:])) 929 stateDB.logError(err) 930 return common.Hash{} 931 } 932 v, err := contract.GetCommittedState(hash.BytesToHash256(k[:])) 933 if err != nil { 934 log.L().Debug("Failed to get committed state.", zap.Error(err)) 935 stateDB.logError(err) 936 return common.Hash{} 937 } 938 return common.BytesToHash(v) 939 } 940 941 // GetState gets state 942 func (stateDB *StateDBAdapter) GetState(evmAddr common.Address, k common.Hash) common.Hash { 943 addr := hash.BytesToHash160(evmAddr[:]) 944 contract, err := stateDB.getContract(addr) 945 if err != nil { 946 log.L().Error("Failed to get contract.", zap.Error(err), log.Hex("addrHash", addr[:])) 947 stateDB.logError(err) 948 return common.Hash{} 949 } 950 v, err := contract.GetState(hash.BytesToHash256(k[:])) 951 if err != nil { 952 log.L().Debug("Failed to get state.", zap.Error(err)) 953 stateDB.logError(err) 954 return common.Hash{} 955 } 956 return common.BytesToHash(v) 957 } 958 959 // SetState sets state 960 func (stateDB *StateDBAdapter) SetState(evmAddr common.Address, k, v common.Hash) { 961 addr := hash.BytesToHash160(evmAddr[:]) 962 contract, err := stateDB.getContract(addr) 963 if err != nil { 964 log.L().Error("Failed to get contract.", zap.Error(err), log.Hex("addrHash", addr[:])) 965 stateDB.logError(err) 966 return 967 } 968 log.L().Debug("Called SetState", log.Hex("addrHash", evmAddr[:]), log.Hex("k", k[:])) 969 if err := contract.SetState(hash.BytesToHash256(k[:]), v[:]); err != nil { 970 log.L().Error("Failed to set state.", zap.Error(err), log.Hex("addrHash", addr[:])) 971 stateDB.logError(err) 972 return 973 } 974 } 975 976 // CommitContracts commits contract code to db and update pending contract account changes to trie 977 func (stateDB *StateDBAdapter) CommitContracts() error { 978 addrStrs := make([]string, 0) 979 for addr := range stateDB.cachedContract { 980 addrStrs = append(addrStrs, hex.EncodeToString(addr[:])) 981 } 982 sort.Strings(addrStrs) 983 984 for _, addrStr := range addrStrs { 985 var addr hash.Hash160 986 addrBytes, err := hex.DecodeString(addrStr) 987 if err != nil { 988 return errors.Wrap(err, "failed to decode address hash") 989 } 990 copy(addr[:], addrBytes) 991 if _, ok := stateDB.suicided[addr]; ok { 992 // no need to update a suicide account/contract 993 continue 994 } 995 contract := stateDB.cachedContract[addr] 996 if err := contract.Commit(); err != nil { 997 stateDB.logError(err) 998 return errors.Wrap(err, "failed to commit contract") 999 } 1000 state := contract.SelfState() 1001 // store the account (with new storage trie root) into account trie 1002 if _, err := stateDB.sm.PutState(state, protocol.LegacyKeyOption(addr)); err != nil { 1003 stateDB.logError(err) 1004 return errors.Wrap(err, "failed to update pending account changes to trie") 1005 } 1006 } 1007 // delete suicided accounts/contract 1008 addrStrs = make([]string, 0) 1009 for addr := range stateDB.suicided { 1010 addrStrs = append(addrStrs, hex.EncodeToString(addr[:])) 1011 } 1012 sort.Strings(addrStrs) 1013 1014 for _, addrStr := range addrStrs { 1015 var addr hash.Hash160 1016 addrBytes, err := hex.DecodeString(addrStr) 1017 if err != nil { 1018 return errors.Wrap(err, "failed to decode address hash") 1019 } 1020 copy(addr[:], addrBytes) 1021 if _, err := stateDB.sm.DelState(protocol.LegacyKeyOption(addr)); err != nil { 1022 stateDB.logError(err) 1023 return errors.Wrapf(err, "failed to delete suicide account/contract %x", addr[:]) 1024 } 1025 } 1026 // write preimages to DB 1027 addrStrs = make([]string, 0) 1028 for addr := range stateDB.preimages { 1029 addrStrs = append(addrStrs, hex.EncodeToString(addr[:])) 1030 } 1031 sort.Strings(addrStrs) 1032 1033 for _, addrStr := range addrStrs { 1034 var k common.Hash 1035 addrBytes, err := hex.DecodeString(addrStr) 1036 if err != nil { 1037 return errors.Wrap(err, "failed to decode address hash") 1038 } 1039 copy(k[:], addrBytes) 1040 v := stateDB.preimages[k] 1041 h := make([]byte, len(k)) 1042 copy(h, k[:]) 1043 if _, err = stateDB.sm.PutState(v, protocol.NamespaceOption(PreimageKVNameSpace), protocol.KeyOption(h)); err != nil { 1044 stateDB.logError(err) 1045 return errors.Wrap(err, "failed to update preimage to db") 1046 } 1047 } 1048 return nil 1049 } 1050 1051 // getContract returns the contract of addr 1052 func (stateDB *StateDBAdapter) getContract(addr hash.Hash160) (Contract, error) { 1053 if contract, ok := stateDB.cachedContract[addr]; ok { 1054 return contract, nil 1055 } 1056 return stateDB.getNewContract(addr) 1057 } 1058 1059 func (stateDB *StateDBAdapter) getNewContract(addr hash.Hash160) (Contract, error) { 1060 account, err := accountutil.LoadAccountByHash160(stateDB.sm, addr, stateDB.accountCreationOpts()...) 1061 if err != nil { 1062 return nil, errors.Wrapf(err, "failed to load account state for address %x", addr) 1063 } 1064 contract, err := newContract(addr, account, stateDB.sm, stateDB.asyncContractTrie) 1065 if err != nil { 1066 return nil, errors.Wrapf(err, "failed to create storage trie for new contract %x", addr) 1067 } 1068 // add to contract cache 1069 stateDB.cachedContract[addr] = contract 1070 return contract, nil 1071 } 1072 1073 // clear clears local changes 1074 func (stateDB *StateDBAdapter) clear() { 1075 stateDB.refundSnapshot = make(map[int]uint64) 1076 stateDB.cachedContract = make(contractMap) 1077 stateDB.contractSnapshot = make(map[int]contractMap) 1078 stateDB.suicided = make(deleteAccount) 1079 stateDB.suicideSnapshot = make(map[int]deleteAccount) 1080 stateDB.preimages = make(preimageMap) 1081 stateDB.preimageSnapshot = make(map[int]preimageMap) 1082 stateDB.accessList = newAccessList() 1083 stateDB.accessListSnapshot = make(map[int]*accessList) 1084 stateDB.logsSnapshot = make(map[int]int) 1085 stateDB.txLogsSnapshot = make(map[int]int) 1086 stateDB.logs = []*action.Log{} 1087 stateDB.transactionLogs = []*action.TransactionLog{} 1088 }