github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/evm/types/statedb.go (about)

     1  package types
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	"fmt"
     7  	ethermint "github.com/fibonacci-chain/fbc/app/types"
     8  	"github.com/tendermint/go-amino"
     9  	"math/big"
    10  	"sort"
    11  	"sync"
    12  
    13  	"github.com/fibonacci-chain/fbc/libs/system/trace"
    14  
    15  	"github.com/ethereum/go-ethereum/common"
    16  	ethcmn "github.com/ethereum/go-ethereum/common"
    17  	"github.com/ethereum/go-ethereum/core/rawdb"
    18  	ethstate "github.com/ethereum/go-ethereum/core/state"
    19  	ethtypes "github.com/ethereum/go-ethereum/core/types"
    20  	ethvm "github.com/ethereum/go-ethereum/core/vm"
    21  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec"
    22  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/mpt"
    23  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/prefix"
    24  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/types"
    25  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    26  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth"
    27  	tmtypes "github.com/fibonacci-chain/fbc/libs/tendermint/types"
    28  )
    29  
    30  var (
    31  	_ ethvm.StateDB = (*CommitStateDB)(nil)
    32  
    33  	zeroBalance = sdk.ZeroInt().BigInt()
    34  )
    35  
    36  type revision struct {
    37  	id           int
    38  	journalIndex int
    39  }
    40  
    41  type CommitStateDBParams struct {
    42  	StoreKey      sdk.StoreKey
    43  	ParamSpace    Subspace
    44  	AccountKeeper AccountKeeper
    45  	SupplyKeeper  SupplyKeeper
    46  	BankKeeper    BankKeeper
    47  	Ada           DbAdapter
    48  	// Amino codec
    49  	Cdc *codec.Codec
    50  
    51  	DB       ethstate.Database
    52  	Trie     ethstate.Trie
    53  	RootHash ethcmn.Hash
    54  }
    55  
    56  type Watcher interface {
    57  	SaveAccount(account auth.Account, isDirectly bool)
    58  	AddDelAccMsg(account auth.Account, isDirectly bool)
    59  	SaveState(addr ethcmn.Address, key, value []byte)
    60  	Enabled() bool
    61  	SaveContractBlockedListItem(addr sdk.AccAddress)
    62  	SaveContractDeploymentWhitelistItem(addr sdk.AccAddress)
    63  	DeleteContractBlockedList(addr sdk.AccAddress)
    64  	DeleteContractDeploymentWhitelist(addr sdk.AccAddress)
    65  	SaveContractMethodBlockedListItem(addr sdk.AccAddress, methods []byte)
    66  }
    67  
    68  type CacheCode struct {
    69  	CodeHash []byte
    70  	Code     []byte
    71  }
    72  
    73  // CommitStateDB implements the Geth state.StateDB interface. Instead of using
    74  // a trie and database for querying and persistence, the Keeper uses KVStores
    75  // and an account mapper is used to facilitate state transitions.
    76  //
    77  // TODO: This implementation is subject to change in regards to its statefull
    78  // manner. In otherwords, how this relates to the keeper in this module.
    79  // Warning!!! If you change CommitStateDB.member you must be careful ResetCommitStateDB contract BananaLF.
    80  type CommitStateDB struct {
    81  	db           ethstate.Database
    82  	trie         ethstate.Trie // only storage addr -> storageMptRoot in this mpt tree
    83  	prefetcher   *mpt.TriePrefetcher
    84  	originalRoot ethcmn.Hash
    85  
    86  	// TODO: We need to store the context as part of the structure itself opposed
    87  	// to being passed as a parameter (as it should be) in order to implement the
    88  	// StateDB interface. Perhaps there is a better way.
    89  	ctx sdk.Context
    90  
    91  	storeKey      sdk.StoreKey
    92  	paramSpace    Subspace
    93  	accountKeeper AccountKeeper
    94  	supplyKeeper  SupplyKeeper
    95  	bankKeeper    BankKeeper
    96  
    97  	// array that hold 'live' objects, which will get modified while processing a
    98  	// state transition
    99  	stateObjects        map[ethcmn.Address]*stateObject
   100  	stateObjectsPending map[ethcmn.Address]struct{} // State objects finalized but not yet written to the mpt tree
   101  	stateObjectsDirty   map[ethcmn.Address]struct{} // State objects modified in the current execution
   102  
   103  	// The refund counter, also used by state transitioning.
   104  	refund uint64
   105  
   106  	thash, bhash ethcmn.Hash
   107  	txIndex      int
   108  	logSize      uint
   109  	logs         map[ethcmn.Hash][]*ethtypes.Log
   110  
   111  	preimages map[ethcmn.Hash][]byte
   112  
   113  	// DB error.
   114  	// State objects are used by the consensus core and VM which are
   115  	// unable to deal with database-level errors. Any error that occurs
   116  	// during a database read is memo-ized here and will eventually be returned
   117  	// by StateDB.Commit.
   118  	dbErr error
   119  
   120  	// Journal of state modifications. This is the backbone of
   121  	// Snapshot and RevertToSnapshot.
   122  	journal        *journal
   123  	validRevisions []revision
   124  	nextRevisionID int
   125  
   126  	// Per-transaction access list
   127  	accessList *accessList
   128  
   129  	// mutex for state deep copying
   130  	lock sync.Mutex
   131  
   132  	params    *Params
   133  	codeCache map[ethcmn.Address]CacheCode
   134  	dbAdapter DbAdapter
   135  
   136  	// Amino codec
   137  	cdc *codec.Codec
   138  
   139  	updatedAccount map[ethcmn.Address]struct{} // will destroy every block
   140  
   141  	GuFactor sdk.Dec
   142  }
   143  
   144  // Warning!!! If you change CommitStateDB.member you must be careful ResetCommitStateDB contract BananaLF.
   145  
   146  type StoreProxy interface {
   147  	Set(key, value []byte)
   148  	Get(key []byte) []byte
   149  	Delete(key []byte)
   150  	Has(key []byte) bool
   151  }
   152  
   153  type DbAdapter interface {
   154  	NewStore(parent types.KVStore, prefix []byte) StoreProxy
   155  }
   156  
   157  type DefaultPrefixDb struct {
   158  }
   159  
   160  func (d DefaultPrefixDb) NewStore(parent types.KVStore, Prefix []byte) StoreProxy {
   161  	return prefix.NewStore(parent, Prefix)
   162  }
   163  
   164  // NewCommitStateDB returns a reference to a newly initialized CommitStateDB
   165  // which implements Geth's state.StateDB interface.
   166  //
   167  // CONTRACT: Stores used for state must be cache-wrapped as the ordering of the
   168  // key/value space matters in determining the merkle root.
   169  func NewCommitStateDB(csdbParams CommitStateDBParams) *CommitStateDB {
   170  	csdb := &CommitStateDB{
   171  		db:           csdbParams.DB,
   172  		trie:         csdbParams.Trie,
   173  		originalRoot: csdbParams.RootHash,
   174  
   175  		storeKey:      csdbParams.StoreKey,
   176  		paramSpace:    csdbParams.ParamSpace,
   177  		accountKeeper: csdbParams.AccountKeeper,
   178  		supplyKeeper:  csdbParams.SupplyKeeper,
   179  		bankKeeper:    csdbParams.BankKeeper,
   180  		cdc:           csdbParams.Cdc,
   181  
   182  		stateObjects:        make(map[ethcmn.Address]*stateObject),
   183  		stateObjectsPending: make(map[ethcmn.Address]struct{}),
   184  		stateObjectsDirty:   make(map[ethcmn.Address]struct{}),
   185  		preimages:           make(map[ethcmn.Hash][]byte),
   186  		journal:             newJournal(),
   187  		validRevisions:      []revision{},
   188  		accessList:          newAccessList(),
   189  		logSize:             0,
   190  		logs:                make(map[ethcmn.Hash][]*ethtypes.Log),
   191  		codeCache:           make(map[ethcmn.Address]CacheCode, 0),
   192  		dbAdapter:           csdbParams.Ada,
   193  		updatedAccount:      make(map[ethcmn.Address]struct{}),
   194  		GuFactor:            DefaultGuFactor,
   195  	}
   196  
   197  	return csdb
   198  }
   199  
   200  func ResetCommitStateDB(csdb *CommitStateDB, csdbParams CommitStateDBParams, ctx *sdk.Context) {
   201  	csdb.db = csdbParams.DB
   202  	csdb.trie = csdbParams.Trie
   203  	csdb.originalRoot = csdbParams.RootHash
   204  
   205  	csdb.storeKey = csdbParams.StoreKey
   206  	csdb.paramSpace = csdbParams.ParamSpace
   207  	csdb.accountKeeper = csdbParams.AccountKeeper
   208  	csdb.supplyKeeper = csdbParams.SupplyKeeper
   209  	csdb.bankKeeper = csdbParams.BankKeeper
   210  	csdb.cdc = csdbParams.Cdc
   211  
   212  	if csdb.stateObjects != nil {
   213  		for k := range csdb.stateObjects {
   214  			delete(csdb.stateObjects, k)
   215  		}
   216  	} else {
   217  		csdb.stateObjects = make(map[ethcmn.Address]*stateObject)
   218  	}
   219  
   220  	if csdb.stateObjectsPending != nil {
   221  		for k := range csdb.stateObjectsPending {
   222  			delete(csdb.stateObjectsPending, k)
   223  		}
   224  	} else {
   225  		csdb.stateObjectsPending = make(map[ethcmn.Address]struct{})
   226  	}
   227  
   228  	if csdb.stateObjectsDirty != nil {
   229  		for k := range csdb.stateObjectsDirty {
   230  			delete(csdb.stateObjectsDirty, k)
   231  		}
   232  	} else {
   233  		csdb.stateObjectsDirty = make(map[ethcmn.Address]struct{})
   234  	}
   235  
   236  	if csdb.preimages != nil {
   237  		for k := range csdb.preimages {
   238  			delete(csdb.preimages, k)
   239  		}
   240  	} else {
   241  		csdb.preimages = make(map[ethcmn.Hash][]byte)
   242  	}
   243  
   244  	if csdb.journal != nil {
   245  		csdb.journal.entries = nil
   246  		if csdb.journal.dirties != nil {
   247  			for k := range csdb.journal.dirties {
   248  				delete(csdb.journal.dirties, k)
   249  			}
   250  		} else {
   251  			csdb.journal.dirties = make(map[ethcmn.Address]int)
   252  		}
   253  	} else {
   254  		csdb.journal = newJournal()
   255  	}
   256  
   257  	if csdb.validRevisions != nil {
   258  		csdb.validRevisions = csdb.validRevisions[:0]
   259  	} else {
   260  		csdb.validRevisions = []revision{}
   261  	}
   262  
   263  	if csdb.accessList != nil {
   264  		if csdb.accessList.addresses != nil {
   265  			for k := range csdb.accessList.addresses {
   266  				delete(csdb.accessList.addresses, k)
   267  			}
   268  		} else {
   269  			csdb.accessList.addresses = make(map[ethcmn.Address]int)
   270  		}
   271  		csdb.accessList.slots = nil
   272  	} else {
   273  		csdb.accessList = newAccessList()
   274  	}
   275  
   276  	csdb.logSize = 0
   277  
   278  	if csdb.logs != nil {
   279  		for k := range csdb.logs {
   280  			delete(csdb.logs, k)
   281  		}
   282  	} else {
   283  		csdb.logs = make(map[ethcmn.Hash][]*ethtypes.Log)
   284  	}
   285  
   286  	if csdb.codeCache != nil {
   287  		for k := range csdb.codeCache {
   288  			delete(csdb.codeCache, k)
   289  		}
   290  	} else {
   291  		csdb.codeCache = make(map[ethcmn.Address]CacheCode, 0)
   292  	}
   293  
   294  	csdb.dbAdapter = csdbParams.Ada
   295  
   296  	if csdb.updatedAccount != nil {
   297  		for k := range csdb.updatedAccount {
   298  			delete(csdb.updatedAccount, k)
   299  		}
   300  	} else {
   301  		csdb.updatedAccount = make(map[ethcmn.Address]struct{})
   302  	}
   303  
   304  	csdb.prefetcher = nil
   305  	csdb.ctx = *ctx
   306  	csdb.refund = 0
   307  	csdb.thash = ethcmn.Hash{}
   308  	csdb.bhash = ethcmn.Hash{}
   309  	csdb.txIndex = 0
   310  	csdb.dbErr = nil
   311  	csdb.nextRevisionID = 0
   312  	csdb.params = nil
   313  	csdb.GuFactor = DefaultGuFactor
   314  }
   315  
   316  func CreateEmptyCommitStateDB(csdbParams CommitStateDBParams, ctx sdk.Context) *CommitStateDB {
   317  	csdb := NewCommitStateDB(csdbParams).WithContext(ctx)
   318  	return csdb
   319  }
   320  
   321  func (csdb *CommitStateDB) WithHistoricalTrie() *CommitStateDB {
   322  	heightBytes := sdk.Uint64ToBigEndian(uint64(csdb.ctx.BlockHeight()))
   323  	rst, err := csdb.db.TrieDB().DiskDB().Get(append(mpt.KeyPrefixEvmRootMptHash, heightBytes...))
   324  	if err != nil || len(rst) == 0 {
   325  		return csdb
   326  	}
   327  	rootHash := ethcmn.BytesToHash(rst)
   328  	tire, err := csdb.db.OpenTrie(rootHash)
   329  	if err != nil {
   330  		return csdb
   331  	}
   332  	csdb.originalRoot = rootHash
   333  	csdb.trie = tire
   334  	return csdb
   335  }
   336  
   337  func (csdb *CommitStateDB) SetInternalDb(dba DbAdapter) {
   338  	csdb.dbAdapter = dba
   339  }
   340  
   341  // WithContext returns a Database with an updated SDK context
   342  func (csdb *CommitStateDB) WithContext(ctx sdk.Context) *CommitStateDB {
   343  	csdb.ctx = ctx
   344  	return csdb
   345  }
   346  
   347  func (csdb *CommitStateDB) GetCacheCode(addr ethcmn.Address) *CacheCode {
   348  	if !csdb.ctx.IsCheckTx() {
   349  		funcName := "GetCacheCode"
   350  		trace.StartTxLog(funcName)
   351  		defer trace.StopTxLog(funcName)
   352  	}
   353  
   354  	code, ok := csdb.codeCache[addr]
   355  	if ok {
   356  		return &code
   357  	}
   358  
   359  	return nil
   360  }
   361  
   362  func (csdb *CommitStateDB) IteratorCode(cb func(addr ethcmn.Address, c CacheCode) bool) {
   363  	for addr, v := range csdb.codeCache {
   364  		cb(addr, v)
   365  	}
   366  }
   367  
   368  // ----------------------------------------------------------------------------
   369  // Setters
   370  // ----------------------------------------------------------------------------
   371  
   372  // SetHeightHash sets the block header hash associated with a given height.
   373  func (csdb *CommitStateDB) SetHeightHash(height uint64, hash ethcmn.Hash) {
   374  	if !csdb.ctx.IsCheckTx() {
   375  		funcName := "SetHeightHash"
   376  		trace.StartTxLog(funcName)
   377  		defer trace.StopTxLog(funcName)
   378  	}
   379  
   380  	if tmtypes.HigherThanMars(csdb.ctx.BlockHeight()) {
   381  		csdb.setHeightHashInRawDB(height, hash)
   382  		return
   383  	}
   384  
   385  	store := csdb.dbAdapter.NewStore(csdb.ctx.KVStore(csdb.storeKey), KeyPrefixHeightHash)
   386  	key := HeightHashKey(height)
   387  	store.Set(key, hash.Bytes())
   388  	if mpt.TrieWriteAhead {
   389  		csdb.setHeightHashInRawDB(height, hash)
   390  	}
   391  }
   392  
   393  // SetParams sets the evm parameters to the param space.
   394  func (csdb *CommitStateDB) SetParams(params Params) {
   395  	csdb.params = &params
   396  	csdb.paramSpace.SetParamSet(csdb.ctx, &params)
   397  	GetEvmParamsCache().SetNeedParamsUpdate()
   398  }
   399  
   400  // SetStorage replaces the entire storage for the specified account with given
   401  // storage. This function should only be used for debugging.
   402  func (csdb *CommitStateDB) SetStorage(addr common.Address, storage map[common.Hash]common.Hash) {
   403  	stateObject := csdb.GetOrNewStateObject(addr)
   404  	if stateObject != nil {
   405  		stateObject.SetStorage(storage)
   406  	}
   407  }
   408  
   409  // SetBalance sets the balance of an account.
   410  func (csdb *CommitStateDB) SetBalance(addr ethcmn.Address, amount *big.Int) {
   411  	so := csdb.GetOrNewStateObject(addr)
   412  	if so != nil {
   413  		so.SetBalance(amount)
   414  	}
   415  }
   416  
   417  // AddBalance adds amount to the account associated with addr.
   418  func (csdb *CommitStateDB) AddBalance(addr ethcmn.Address, amount *big.Int) {
   419  	if !csdb.ctx.IsCheckTx() {
   420  		funcName := "AddBalance"
   421  		trace.StartTxLog(funcName)
   422  		defer trace.StopTxLog(funcName)
   423  	}
   424  
   425  	so := csdb.GetOrNewStateObject(addr)
   426  	if so != nil {
   427  		so.AddBalance(amount)
   428  	}
   429  }
   430  
   431  // SubBalance subtracts amount from the account associated with addr.
   432  func (csdb *CommitStateDB) SubBalance(addr ethcmn.Address, amount *big.Int) {
   433  	if !csdb.ctx.IsCheckTx() {
   434  		funcName := "SubBalance"
   435  		trace.StartTxLog(funcName)
   436  		defer trace.StopTxLog(funcName)
   437  	}
   438  
   439  	so := csdb.GetOrNewStateObject(addr)
   440  	if so != nil {
   441  		so.SubBalance(amount)
   442  	}
   443  }
   444  
   445  // SetNonce sets the nonce (sequence number) of an account.
   446  func (csdb *CommitStateDB) SetNonce(addr ethcmn.Address, nonce uint64) {
   447  	if !csdb.ctx.IsCheckTx() {
   448  		funcName := "SetNonce"
   449  		trace.StartTxLog(funcName)
   450  		defer trace.StopTxLog(funcName)
   451  	}
   452  
   453  	so := csdb.GetOrNewStateObject(addr)
   454  	if so != nil {
   455  		so.SetNonce(nonce)
   456  	}
   457  }
   458  
   459  // SetState sets the storage state with a key, value pair for an account.
   460  func (csdb *CommitStateDB) SetState(addr ethcmn.Address, key, value ethcmn.Hash) {
   461  	if !csdb.ctx.IsCheckTx() {
   462  		funcName := "SetState"
   463  		trace.StartTxLog(funcName)
   464  		defer trace.StopTxLog(funcName)
   465  	}
   466  
   467  	so := csdb.GetOrNewStateObject(addr)
   468  	if so != nil {
   469  		so.SetState(csdb.db, key, value)
   470  	}
   471  }
   472  
   473  // SetCode sets the code for a given account.
   474  func (csdb *CommitStateDB) SetCode(addr ethcmn.Address, code []byte) {
   475  	if !csdb.ctx.IsCheckTx() {
   476  		funcName := "SetCode"
   477  		trace.StartTxLog(funcName)
   478  		defer trace.StopTxLog(funcName)
   479  	}
   480  
   481  	so := csdb.GetOrNewStateObject(addr)
   482  	if so != nil {
   483  		hash := Keccak256HashWithCache(code)
   484  		so.SetCode(hash, code)
   485  		csdb.codeCache[addr] = CacheCode{
   486  			CodeHash: hash.Bytes(),
   487  			Code:     code,
   488  		}
   489  	}
   490  }
   491  
   492  // ----------------------------------------------------------------------------
   493  // Transaction logs
   494  // Required for upgrade logic or ease of querying.
   495  // NOTE: we use BinaryLengthPrefixed since the tx logs are also included on Result data,
   496  // which can't use BinaryBare.
   497  // ----------------------------------------------------------------------------
   498  
   499  // SetLogs sets the logs for a transaction in the KVStore.
   500  func (csdb *CommitStateDB) SetLogs(hash ethcmn.Hash, logs []*ethtypes.Log) error {
   501  	csdb.logs[hash] = logs
   502  	return nil
   503  }
   504  
   505  // DeleteLogs removes the logs from the KVStore. It is used during journal.Revert.
   506  func (csdb *CommitStateDB) DeleteLogs(hash ethcmn.Hash) {
   507  	delete(csdb.logs, hash)
   508  }
   509  
   510  // AddLog adds a new log to the state and sets the log metadata from the state.
   511  func (csdb *CommitStateDB) AddLog(log *ethtypes.Log) {
   512  	if !csdb.ctx.IsCheckTx() {
   513  		funcName := "AddLog"
   514  		trace.StartTxLog(funcName)
   515  		defer trace.StopTxLog(funcName)
   516  	}
   517  
   518  	csdb.journal.append(addLogChange{txhash: csdb.thash})
   519  
   520  	log.TxHash = csdb.thash
   521  	log.BlockHash = csdb.bhash
   522  	log.TxIndex = uint(csdb.txIndex)
   523  	log.Index = csdb.logSize
   524  
   525  	csdb.logSize = csdb.logSize + 1
   526  	csdb.logs[csdb.thash] = append(csdb.logs[csdb.thash], log)
   527  }
   528  
   529  // AddPreimage records a SHA3 preimage seen by the VM.
   530  func (csdb *CommitStateDB) AddPreimage(hash ethcmn.Hash, preimage []byte) {
   531  	if !csdb.ctx.IsCheckTx() {
   532  		funcName := "AddPreimage"
   533  		trace.StartTxLog(funcName)
   534  		defer trace.StopTxLog(funcName)
   535  	}
   536  
   537  	if _, ok := csdb.preimages[hash]; !ok {
   538  		csdb.journal.append(addPreimageChange{hash: hash})
   539  		pi := make([]byte, len(preimage))
   540  		copy(pi, preimage)
   541  		csdb.preimages[hash] = pi
   542  	}
   543  }
   544  
   545  // AddRefund adds gas to the refund counter.
   546  func (csdb *CommitStateDB) AddRefund(gas uint64) {
   547  	if !csdb.ctx.IsCheckTx() {
   548  		funcName := "AddRefund"
   549  		trace.StartTxLog(funcName)
   550  		defer trace.StopTxLog(funcName)
   551  	}
   552  
   553  	csdb.journal.append(refundChange{prev: csdb.refund})
   554  	csdb.refund += gas
   555  }
   556  
   557  // SubRefund removes gas from the refund counter. It will panic if the refund
   558  // counter goes below zero.
   559  func (csdb *CommitStateDB) SubRefund(gas uint64) {
   560  	if !csdb.ctx.IsCheckTx() {
   561  		funcName := "SubRefund"
   562  		trace.StartTxLog(funcName)
   563  		defer trace.StopTxLog(funcName)
   564  	}
   565  
   566  	csdb.journal.append(refundChange{prev: csdb.refund})
   567  	if gas > csdb.refund {
   568  		panic("refund counter below zero")
   569  	}
   570  
   571  	csdb.refund -= gas
   572  }
   573  
   574  // AddAddressToAccessList adds the given address to the access list
   575  func (csdb *CommitStateDB) AddAddressToAccessList(addr ethcmn.Address) {
   576  	if !csdb.ctx.IsCheckTx() {
   577  		funcName := "AddAddressToAccessList"
   578  		trace.StartTxLog(funcName)
   579  		defer trace.StopTxLog(funcName)
   580  	}
   581  
   582  	if csdb.accessList.AddAddress(addr) {
   583  		csdb.journal.append(accessListAddAccountChange{&addr})
   584  	}
   585  }
   586  
   587  // AddSlotToAccessList adds the given (address, slot)-tuple to the access list
   588  func (csdb *CommitStateDB) AddSlotToAccessList(addr ethcmn.Address, slot ethcmn.Hash) {
   589  	if !csdb.ctx.IsCheckTx() {
   590  		funcName := "AddSlotToAccessList"
   591  		trace.StartTxLog(funcName)
   592  		defer trace.StopTxLog(funcName)
   593  	}
   594  
   595  	addrMod, slotMod := csdb.accessList.AddSlot(addr, slot)
   596  	if addrMod {
   597  		// In practice, this should not happen, since there is no way to enter the
   598  		// scope of 'address' without having the 'address' become already added
   599  		// to the access list (via call-variant, create, etc).
   600  		// Better safe than sorry, though
   601  		csdb.journal.append(accessListAddAccountChange{&addr})
   602  	}
   603  	if slotMod {
   604  		csdb.journal.append(accessListAddSlotChange{
   605  			address: &addr,
   606  			slot:    &slot,
   607  		})
   608  	}
   609  }
   610  func (csdb *CommitStateDB) PrepareAccessList(sender ethcmn.Address, dest *ethcmn.Address, precompiles []ethcmn.Address, txAccesses ethtypes.AccessList) {
   611  	if !csdb.ctx.IsCheckTx() {
   612  		funcName := "PrepareAccessList"
   613  		trace.StartTxLog(funcName)
   614  		defer trace.StopTxLog(funcName)
   615  	}
   616  
   617  	csdb.AddAddressToAccessList(sender)
   618  	if csdb != nil {
   619  		csdb.AddAddressToAccessList(*dest)
   620  		// If it's a create-tx, the destination will be added inside evm.create
   621  	}
   622  	for _, addr := range precompiles {
   623  		csdb.AddAddressToAccessList(addr)
   624  	}
   625  	for _, el := range txAccesses {
   626  		csdb.AddAddressToAccessList(el.Address)
   627  		for _, key := range el.StorageKeys {
   628  			csdb.AddSlotToAccessList(el.Address, key)
   629  		}
   630  	}
   631  }
   632  
   633  // AddressInAccessList returns true if the given address is in the access list.
   634  func (csdb *CommitStateDB) AddressInAccessList(addr ethcmn.Address) bool {
   635  	if !csdb.ctx.IsCheckTx() {
   636  		funcName := "AddressInAccessList"
   637  		trace.StartTxLog(funcName)
   638  		defer trace.StopTxLog(funcName)
   639  	}
   640  
   641  	return csdb.accessList.ContainsAddress(addr)
   642  }
   643  
   644  // SlotInAccessList returns true if the given (address, slot)-tuple is in the access list.
   645  func (csdb *CommitStateDB) SlotInAccessList(addr ethcmn.Address, slot ethcmn.Hash) (bool, bool) {
   646  	if !csdb.ctx.IsCheckTx() {
   647  		funcName := "SlotInAccessList"
   648  		trace.StartTxLog(funcName)
   649  		defer trace.StopTxLog(funcName)
   650  	}
   651  
   652  	return csdb.accessList.Contains(addr, slot)
   653  }
   654  
   655  // ----------------------------------------------------------------------------
   656  // Getters
   657  // ----------------------------------------------------------------------------
   658  
   659  // GetHeightHash returns the block header hash associated with a given block height and chain epoch number.
   660  func (csdb *CommitStateDB) GetHeightHash(height uint64) ethcmn.Hash {
   661  	if tmtypes.HigherThanMars(csdb.ctx.BlockHeight()) {
   662  		return csdb.getHeightHashInRawDB(height)
   663  	}
   664  
   665  	store := csdb.dbAdapter.NewStore(csdb.ctx.KVStore(csdb.storeKey), KeyPrefixHeightHash)
   666  	key := HeightHashKey(height)
   667  	bz := store.Get(key)
   668  	if len(bz) == 0 {
   669  		return ethcmn.Hash{}
   670  	}
   671  
   672  	return ethcmn.BytesToHash(bz)
   673  }
   674  
   675  // GetParams returns the total set of evm parameters.
   676  func (csdb *CommitStateDB) GetParams() Params {
   677  	if csdb.params == nil {
   678  		var params Params
   679  		if csdb.ctx.UseParamCache() {
   680  			if GetEvmParamsCache().IsNeedParamsUpdate() {
   681  				csdb.paramSpace.GetParamSet(csdb.ctx, &params)
   682  				GetEvmParamsCache().UpdateParams(params, csdb.ctx.IsCheckTx())
   683  			} else {
   684  				params = GetEvmParamsCache().GetParams()
   685  			}
   686  		} else {
   687  			csdb.paramSpace.GetParamSet(csdb.ctx, &params)
   688  		}
   689  		csdb.params = &params
   690  	}
   691  	return *csdb.params
   692  }
   693  
   694  // GetBalance retrieves the balance from the given address or 0 if object not
   695  // found.
   696  func (csdb *CommitStateDB) GetBalance(addr ethcmn.Address) *big.Int {
   697  	if !csdb.ctx.IsCheckTx() {
   698  		funcName := "GetBalance"
   699  		trace.StartTxLog(funcName)
   700  		defer trace.StopTxLog(funcName)
   701  	}
   702  
   703  	so := csdb.getStateObject(addr)
   704  	if so != nil {
   705  		return so.Balance()
   706  	}
   707  
   708  	return zeroBalance
   709  }
   710  
   711  // GetNonce returns the nonce (sequence number) for a given account.
   712  func (csdb *CommitStateDB) GetNonce(addr ethcmn.Address) uint64 {
   713  	if !csdb.ctx.IsCheckTx() {
   714  		funcName := "GetNonce"
   715  		trace.StartTxLog(funcName)
   716  		defer trace.StopTxLog(funcName)
   717  	}
   718  
   719  	so := csdb.getStateObject(addr)
   720  	if so != nil {
   721  		return so.Nonce()
   722  	}
   723  
   724  	return 0
   725  }
   726  
   727  // TxIndex returns the current transaction index set by Prepare.
   728  func (csdb *CommitStateDB) TxIndex() int {
   729  	return csdb.txIndex
   730  }
   731  
   732  // BlockHash returns the current block hash set by Prepare.
   733  func (csdb *CommitStateDB) BlockHash() ethcmn.Hash {
   734  	return csdb.bhash
   735  }
   736  
   737  func (csdb *CommitStateDB) SetBlockHash(hash ethcmn.Hash) {
   738  	csdb.bhash = hash
   739  }
   740  
   741  // GetCode returns the code for a given account.
   742  func (csdb *CommitStateDB) GetCode(addr ethcmn.Address) []byte {
   743  	if !csdb.ctx.IsCheckTx() {
   744  		funcName := "GetCode"
   745  		trace.StartTxLog(funcName)
   746  		defer trace.StopTxLog(funcName)
   747  	}
   748  
   749  	// check for the contract calling from blocked list if contract blocked list is enabled
   750  	if csdb.GetParams().EnableContractBlockedList && csdb.IsContractInBlockedList(addr.Bytes()) {
   751  		err := ErrContractBlockedVerify{fmt.Sprintf("failed. the contract %s is not allowed to invoke", addr.Hex())}
   752  		panic(err)
   753  	}
   754  
   755  	so := csdb.getStateObject(addr)
   756  	if so != nil {
   757  		return so.Code(csdb.db)
   758  	}
   759  	return nil
   760  }
   761  
   762  // GetCode returns the code for a given code hash.
   763  func (csdb *CommitStateDB) GetCodeByHash(hash ethcmn.Hash) []byte {
   764  	if tmtypes.HigherThanMars(csdb.ctx.BlockHeight()) {
   765  		return csdb.GetCodeByHashInRawDB(hash)
   766  	}
   767  
   768  	ctx := csdb.ctx
   769  	store := csdb.dbAdapter.NewStore(ctx.KVStore(csdb.storeKey), KeyPrefixCode)
   770  	code := store.Get(hash.Bytes())
   771  	return code
   772  }
   773  
   774  // GetCodeSize returns the code size for a given account.
   775  func (csdb *CommitStateDB) GetCodeSize(addr ethcmn.Address) int {
   776  	if !csdb.ctx.IsCheckTx() {
   777  		funcName := "GetCodeSize"
   778  		trace.StartTxLog(funcName)
   779  		defer trace.StopTxLog(funcName)
   780  	}
   781  
   782  	so := csdb.getStateObject(addr)
   783  	if so != nil {
   784  		return so.CodeSize(csdb.db)
   785  	}
   786  	return 0
   787  }
   788  
   789  // GetCodeHash returns the code hash for a given account.
   790  func (csdb *CommitStateDB) GetCodeHash(addr ethcmn.Address) ethcmn.Hash {
   791  	if !csdb.ctx.IsCheckTx() {
   792  		funcName := "GetCodeHash"
   793  		trace.StartTxLog(funcName)
   794  		defer trace.StopTxLog(funcName)
   795  	}
   796  
   797  	so := csdb.getStateObject(addr)
   798  	if so == nil {
   799  		return ethcmn.Hash{}
   800  	}
   801  
   802  	return ethcmn.BytesToHash(so.CodeHash())
   803  }
   804  
   805  // GetState retrieves a value from the given account's storage store.
   806  func (csdb *CommitStateDB) GetState(addr ethcmn.Address, hash ethcmn.Hash) ethcmn.Hash {
   807  	if !csdb.ctx.IsCheckTx() {
   808  		funcName := "GetState"
   809  		trace.StartTxLog(funcName)
   810  		defer trace.StopTxLog(funcName)
   811  	}
   812  
   813  	so := csdb.getStateObject(addr)
   814  	if so != nil {
   815  		return so.GetState(csdb.db, hash)
   816  	}
   817  
   818  	return ethcmn.Hash{}
   819  }
   820  
   821  // GetStateByKey retrieves a value from the given account's storage store.
   822  func (csdb *CommitStateDB) GetStateByKey(addr ethcmn.Address, key ethcmn.Hash) ethcmn.Hash {
   823  	if tmtypes.HigherThanMars(csdb.ctx.BlockHeight()) {
   824  		return csdb.GetStateByKeyMpt(addr, key)
   825  	}
   826  
   827  	ctx := csdb.ctx
   828  	store := csdb.dbAdapter.NewStore(ctx.KVStore(csdb.storeKey), AddressStoragePrefix(addr))
   829  	data := store.Get(key.Bytes())
   830  
   831  	return ethcmn.BytesToHash(data)
   832  }
   833  
   834  // GetCommittedState retrieves a value from the given account's committed
   835  // storage.
   836  func (csdb *CommitStateDB) GetCommittedState(addr ethcmn.Address, hash ethcmn.Hash) ethcmn.Hash {
   837  	if !csdb.ctx.IsCheckTx() {
   838  		funcName := "GetCommittedState"
   839  		trace.StartTxLog(funcName)
   840  		defer trace.StopTxLog(funcName)
   841  	}
   842  
   843  	so := csdb.getStateObject(addr)
   844  	if so != nil {
   845  		return so.GetCommittedState(csdb.db, hash)
   846  	}
   847  
   848  	return ethcmn.Hash{}
   849  }
   850  
   851  // GetLogs returns the current logs for a given transaction hash from the KVStore.
   852  func (csdb *CommitStateDB) GetLogs(hash ethcmn.Hash) ([]*ethtypes.Log, error) {
   853  	return csdb.logs[hash], nil
   854  }
   855  
   856  // GetRefund returns the current value of the refund counter.
   857  func (csdb *CommitStateDB) GetRefund() uint64 {
   858  	if !csdb.ctx.IsCheckTx() {
   859  		funcName := "GetRefund"
   860  		trace.StartTxLog(funcName)
   861  		defer trace.StopTxLog(funcName)
   862  	}
   863  
   864  	return csdb.refund
   865  }
   866  
   867  // Preimages returns a list of SHA3 preimages that have been submitted.
   868  func (csdb *CommitStateDB) Preimages() map[ethcmn.Hash][]byte {
   869  	return csdb.preimages
   870  }
   871  
   872  // HasSuicided returns if the given account for the specified address has been
   873  // killed.
   874  func (csdb *CommitStateDB) HasSuicided(addr ethcmn.Address) bool {
   875  	if !csdb.ctx.IsCheckTx() {
   876  		funcName := "HasSuicided"
   877  		trace.StartTxLog(funcName)
   878  		defer trace.StopTxLog(funcName)
   879  	}
   880  
   881  	so := csdb.getStateObject(addr)
   882  	if so != nil {
   883  		return so.suicided
   884  	}
   885  
   886  	return false
   887  }
   888  
   889  // StorageTrie returns nil as the state in Ethermint does not use a direct
   890  // storage trie.
   891  func (csdb *CommitStateDB) StorageTrie(addr ethcmn.Address) ethstate.Trie {
   892  	stateObject := csdb.getStateObject(addr)
   893  	if stateObject == nil {
   894  		return nil
   895  	}
   896  	cpy := stateObject.deepCopy(csdb)
   897  	cpy.updateTrie(csdb.db)
   898  	return cpy.getTrie(csdb.db)
   899  }
   900  
   901  // ----------------------------------------------------------------------------
   902  // Persistence
   903  // ----------------------------------------------------------------------------
   904  
   905  // Commit writes the state to the appropriate KVStores. For each state object
   906  // in the cache, it will either be removed, or have it's code set and/or it's
   907  // state (storage) updated. In addition, the state object (account) itself will
   908  // be written. Finally, the root hash (version) will be returned.
   909  func (csdb *CommitStateDB) Commit(deleteEmptyObjects bool) (ethcmn.Hash, error) {
   910  	// Finalize any pending changes and merge everything into the tries
   911  	csdb.IntermediateRoot(deleteEmptyObjects)
   912  
   913  	// If there was a trie prefetcher operating, it gets aborted and irrevocably
   914  	// modified after we start retrieving tries. Remove it from the statedb after
   915  	// this round of use.
   916  	//
   917  	// This is weird pre-byzantium since the first tx runs with a prefetcher and
   918  	// the remainder without, but pre-byzantium even the initial prefetcher is
   919  	// useless, so no sleep lost.
   920  	prefetcher := csdb.prefetcher
   921  	if csdb.prefetcher != nil {
   922  		defer func() {
   923  			csdb.prefetcher.Close()
   924  			csdb.prefetcher = nil
   925  		}()
   926  	}
   927  
   928  	// Now we're about to start to write changes to the trie. The trie is so far
   929  	// _untouched_. We can check with the prefetcher, if it can give us a trie
   930  	// which has the same root, but also has some content loaded into it.
   931  	if prefetcher != nil {
   932  		if trie := prefetcher.Trie(csdb.originalRoot); trie != nil {
   933  			csdb.trie = trie
   934  		}
   935  	}
   936  
   937  	if !tmtypes.HigherThanMars(csdb.ctx.BlockHeight()) {
   938  		if mpt.TrieWriteAhead {
   939  			// Commit objects to the trie, measuring the elapsed time
   940  			codeWriter := csdb.db.TrieDB().DiskDB().NewBatch()
   941  			usedAddrs := make([][]byte, 0, len(csdb.stateObjectsPending))
   942  
   943  			for addr := range csdb.stateObjectsDirty {
   944  				if obj := csdb.stateObjects[addr]; !obj.deleted {
   945  					// Write any contract code associated with the state object
   946  					if obj.code != nil && obj.dirtyCode {
   947  						obj.commitCode()
   948  
   949  						rawdb.WriteCode(codeWriter, ethcmn.BytesToHash(obj.CodeHash()), obj.code)
   950  						obj.dirtyCode = false
   951  					}
   952  
   953  					// Write any storage changes in the state object to its storage trie
   954  					if err := obj.CommitTrie(csdb.db); err != nil {
   955  						return ethcmn.Hash{}, err
   956  					}
   957  
   958  					csdb.UpdateAccountStorageInfo(obj)
   959  				} else {
   960  					csdb.DeleteAccountStorageInfo(obj)
   961  				}
   962  
   963  				usedAddrs = append(usedAddrs, ethcmn.CopyBytes(addr[:])) // Copy needed for closure
   964  			}
   965  			if prefetcher != nil {
   966  				prefetcher.Used(csdb.originalRoot, usedAddrs)
   967  			}
   968  
   969  			if codeWriter.ValueSize() > 0 {
   970  				if err := codeWriter.Write(); err != nil {
   971  					csdb.SetError(fmt.Errorf("failed to commit dirty codes: %s", err.Error()))
   972  				}
   973  			}
   974  		} else {
   975  			// Commit objects to the trie, measuring the elapsed time
   976  			for addr := range csdb.stateObjectsDirty {
   977  				if so := csdb.stateObjects[addr]; !so.deleted {
   978  					// Write any contract code associated with the state object
   979  					if so.code != nil && so.dirtyCode {
   980  						so.commitCode()
   981  						so.dirtyCode = false
   982  					}
   983  				}
   984  			}
   985  		}
   986  
   987  		if len(csdb.stateObjectsDirty) > 0 {
   988  			csdb.stateObjectsDirty = make(map[ethcmn.Address]struct{})
   989  		}
   990  
   991  		return ethcmn.Hash{}, nil
   992  	} else {
   993  		return csdb.CommitMpt(prefetcher)
   994  	}
   995  }
   996  
   997  // Finalise finalizes the state objects (accounts) state by setting their state,
   998  // removing the csdb destructed objects and clearing the journal as well as the
   999  // refunds.
  1000  func (csdb *CommitStateDB) Finalise(deleteEmptyObjects bool) {
  1001  	addressesToPrefetch := make([][]byte, 0, len(csdb.journal.dirties))
  1002  	for addr := range csdb.journal.dirties {
  1003  		obj, exist := csdb.stateObjects[addr]
  1004  		if !exist {
  1005  			// ripeMD is 'touched' at block 1714175, in tx 0x1237f737031e40bcde4a8b7e717b2d15e3ecadfe49bb1bbc71ee9deb09c6fcf2
  1006  			// That tx goes out of gas, and although the notion of 'touched' does not exist there, the
  1007  			// touch-event will still be recorded in the journal. Since ripeMD is a special snowflake,
  1008  			// it will persist in the journal even though the journal is reverted. In this special circumstance,
  1009  			// it may exist in `s.journal.dirties` but not in `s.stateObjects`.
  1010  			// Thus, we can safely ignore it here
  1011  			continue
  1012  		}
  1013  		if obj.suicided || (deleteEmptyObjects && obj.empty()) {
  1014  			obj.deleted = true
  1015  		} else {
  1016  			obj.finalise(true) // Prefetch slots in the background
  1017  		}
  1018  		csdb.stateObjectsPending[addr] = struct{}{}
  1019  		csdb.stateObjectsDirty[addr] = struct{}{}
  1020  
  1021  		// At this point, also ship the address off to the precacher. The precacher
  1022  		// will start loading tries, and when the change is eventually committed,
  1023  		// the commit-phase will be a lot faster
  1024  		addressesToPrefetch = append(addressesToPrefetch, ethcmn.CopyBytes(addr[:])) // Copy needed for closure
  1025  	}
  1026  	if csdb.prefetcher != nil && len(addressesToPrefetch) > 0 {
  1027  		csdb.prefetcher.Prefetch(csdb.originalRoot, addressesToPrefetch)
  1028  	}
  1029  
  1030  	// Invalidate journal because reverting across transactions is not allowed.
  1031  	csdb.clearJournalAndRefund()
  1032  }
  1033  
  1034  // IntermediateRoot returns the current root hash of the state. It is called in
  1035  // between transactions to get the root hash that goes into transaction
  1036  // receipts.
  1037  //
  1038  // NOTE: The SDK has not concept or method of getting any intermediate merkle
  1039  // root as commitment of the merkle-ized tree doesn't happen until the
  1040  // BaseApps' EndBlocker.
  1041  func (csdb *CommitStateDB) IntermediateRoot(deleteEmptyObjects bool) ethcmn.Hash {
  1042  	// Finalise all the dirty storage states and write them into the tries
  1043  	csdb.Finalise(deleteEmptyObjects)
  1044  
  1045  	if !tmtypes.HigherThanMars(csdb.ctx.BlockHeight()) {
  1046  		for addr := range csdb.stateObjectsPending {
  1047  			if obj := csdb.stateObjects[addr]; !obj.deleted {
  1048  				obj.commitState(csdb.db)
  1049  			}
  1050  		}
  1051  	} else {
  1052  		// Although naively it makes sense to retrieve the account trie and then do
  1053  		// the contract storage and account updates sequentially, that short circuits
  1054  		// the account prefetcher. Instead, let's process all the storage updates
  1055  		// first, giving the account prefeches just a few more milliseconds of time
  1056  		// to pull useful data from disk.
  1057  		for addr := range csdb.stateObjectsPending {
  1058  			if obj := csdb.stateObjects[addr]; !obj.deleted {
  1059  				obj.updateRoot(csdb.db)
  1060  			}
  1061  		}
  1062  	}
  1063  
  1064  	//usedAddrs := make([][]byte, 0, len(csdb.stateObjectsPending))
  1065  	for addr := range csdb.stateObjectsPending {
  1066  		if obj := csdb.stateObjects[addr]; obj.deleted {
  1067  			csdb.deleteStateObject(obj)
  1068  		} else {
  1069  			csdb.updateStateObject(obj)
  1070  		}
  1071  		//usedAddrs = append(usedAddrs, ethcmn.CopyBytes(addr[:])) // Copy needed for closure
  1072  	}
  1073  	//if csdb.prefetcher != nil {
  1074  	//	csdb.prefetcher.used(csdb.originalRoot, usedAddrs)
  1075  	//}
  1076  
  1077  	if len(csdb.stateObjectsPending) > 0 {
  1078  		csdb.stateObjectsPending = make(map[ethcmn.Address]struct{})
  1079  	}
  1080  
  1081  	return ethcmn.Hash{}
  1082  }
  1083  
  1084  // updateStateObject writes the given state object to the store.
  1085  func (csdb *CommitStateDB) updateStateObject(so *stateObject) error {
  1086  	// NOTE: we don't use sdk.NewCoin here to avoid panic on test importer's genesis
  1087  	newBalance := sdk.Coin{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDecFromBigIntWithPrec(so.Balance(), sdk.Precision)} // int2dec
  1088  	if !newBalance.IsValid() {
  1089  		return fmt.Errorf("invalid balance %s", newBalance)
  1090  	}
  1091  
  1092  	//checking and reject tx if address in blacklist
  1093  	if csdb.bankKeeper.BlacklistedAddr(so.account.GetAddress()) {
  1094  		return fmt.Errorf("address <%s> in blacklist is not allowed", so.account.GetAddress().String())
  1095  	}
  1096  
  1097  	coins := so.account.GetCoins()
  1098  	balance := coins.AmountOf(newBalance.Denom)
  1099  	if balance.IsZero() || !balance.Equal(newBalance.Amount) {
  1100  		coins = coins.Add(newBalance)
  1101  	}
  1102  
  1103  	if err := so.account.SetCoins(coins); err != nil {
  1104  		return err
  1105  	}
  1106  
  1107  	csdb.accountKeeper.SetAccount(csdb.ctx, so.account)
  1108  	if !csdb.ctx.IsCheckTx() {
  1109  		if csdb.ctx.GetWatcher().Enabled() {
  1110  			csdb.ctx.GetWatcher().SaveAccount(so.account)
  1111  		}
  1112  	}
  1113  
  1114  	return nil
  1115  }
  1116  
  1117  // deleteStateObject removes the given state object from the state store.
  1118  func (csdb *CommitStateDB) deleteStateObject(so *stateObject) {
  1119  	so.deleted = true
  1120  	csdb.accountKeeper.RemoveAccount(csdb.ctx, so.account)
  1121  
  1122  	//if tmtypes.HigherThanMars(csdb.ctx.BlockHeight()) || types2.EnableDoubleWrite {
  1123  	//	csdb.DeleteAccountStorageInfo(so)
  1124  	//}
  1125  }
  1126  
  1127  // ----------------------------------------------------------------------------
  1128  // Snapshotting
  1129  // ----------------------------------------------------------------------------
  1130  
  1131  // Snapshot returns an identifier for the current revision of the state.
  1132  func (csdb *CommitStateDB) Snapshot() int {
  1133  	if !csdb.ctx.IsCheckTx() {
  1134  		funcName := "Snapshot"
  1135  		trace.StartTxLog(funcName)
  1136  		defer trace.StopTxLog(funcName)
  1137  	}
  1138  
  1139  	id := csdb.nextRevisionID
  1140  	csdb.nextRevisionID++
  1141  
  1142  	csdb.validRevisions = append(
  1143  		csdb.validRevisions,
  1144  		revision{
  1145  			id:           id,
  1146  			journalIndex: csdb.journal.length(),
  1147  		},
  1148  	)
  1149  
  1150  	return id
  1151  }
  1152  
  1153  // RevertToSnapshot reverts all state changes made since the given revision.
  1154  func (csdb *CommitStateDB) RevertToSnapshot(revID int) {
  1155  	if !csdb.ctx.IsCheckTx() {
  1156  		funcName := "RevertToSnapshot"
  1157  		trace.StartTxLog(funcName)
  1158  		defer trace.StopTxLog(funcName)
  1159  	}
  1160  
  1161  	// find the snapshot in the stack of valid snapshots
  1162  	idx := sort.Search(len(csdb.validRevisions), func(i int) bool {
  1163  		return csdb.validRevisions[i].id >= revID
  1164  	})
  1165  
  1166  	if idx == len(csdb.validRevisions) || csdb.validRevisions[idx].id != revID {
  1167  		panic(fmt.Errorf("revision ID %v cannot be reverted", revID))
  1168  	}
  1169  
  1170  	snapshot := csdb.validRevisions[idx].journalIndex
  1171  
  1172  	// replay the journal to undo changes and remove invalidated snapshots
  1173  	csdb.journal.revert(csdb, snapshot)
  1174  	csdb.validRevisions = csdb.validRevisions[:idx]
  1175  }
  1176  
  1177  // ----------------------------------------------------------------------------
  1178  // Auxiliary
  1179  // ----------------------------------------------------------------------------
  1180  
  1181  // Database retrieves the low level database supporting the lower level trie
  1182  // ops. It is not used in Ethermint, so it returns nil.
  1183  func (csdb *CommitStateDB) Database() ethstate.Database {
  1184  	return csdb.db
  1185  }
  1186  
  1187  // Empty returns whether the state object is either non-existent or empty
  1188  // according to the EIP161 specification (balance = nonce = code = 0).
  1189  func (csdb *CommitStateDB) Empty(addr ethcmn.Address) bool {
  1190  	if !csdb.ctx.IsCheckTx() {
  1191  		funcName := "Empty"
  1192  		trace.StartTxLog(funcName)
  1193  		defer trace.StopTxLog(funcName)
  1194  	}
  1195  
  1196  	so := csdb.getStateObject(addr)
  1197  	return so == nil || so.empty()
  1198  }
  1199  
  1200  // Exist reports whether the given account address exists in the state. Notably,
  1201  // this also returns true for suicided accounts.
  1202  func (csdb *CommitStateDB) Exist(addr ethcmn.Address) bool {
  1203  	if !csdb.ctx.IsCheckTx() {
  1204  		funcName := "Exist"
  1205  		trace.StartTxLog(funcName)
  1206  		defer trace.StopTxLog(funcName)
  1207  	}
  1208  
  1209  	return csdb.getStateObject(addr) != nil
  1210  }
  1211  
  1212  // Error returns the first non-nil error the StateDB encountered.
  1213  func (csdb *CommitStateDB) Error() error {
  1214  	return csdb.dbErr
  1215  }
  1216  
  1217  // Suicide marks the given account as suicided and clears the account balance.
  1218  //
  1219  // The account's state object is still available until the state is committed,
  1220  // getStateObject will return a non-nil account after Suicide.
  1221  func (csdb *CommitStateDB) Suicide(addr ethcmn.Address) bool {
  1222  	if !csdb.ctx.IsCheckTx() {
  1223  		funcName := "Suicide"
  1224  		trace.StartTxLog(funcName)
  1225  		defer trace.StopTxLog(funcName)
  1226  	}
  1227  
  1228  	so := csdb.getStateObject(addr)
  1229  	if so == nil {
  1230  		return false
  1231  	}
  1232  
  1233  	csdb.journal.append(suicideChange{
  1234  		account:     &addr,
  1235  		prev:        so.suicided,
  1236  		prevBalance: sdk.NewDecFromBigIntWithPrec(so.Balance(), sdk.Precision), // int2dec
  1237  	})
  1238  
  1239  	so.markSuicided()
  1240  	so.SetBalance(new(big.Int))
  1241  
  1242  	return true
  1243  }
  1244  
  1245  // Reset clears out all ephemeral state objects from the state db, but keeps
  1246  // the underlying account mapper and store keys to avoid reloading data for the
  1247  // next operations.
  1248  func (csdb *CommitStateDB) Reset(_ ethcmn.Hash) error {
  1249  	csdb.stateObjects = make(map[ethcmn.Address]*stateObject)
  1250  	csdb.stateObjectsPending = make(map[ethcmn.Address]struct{})
  1251  	csdb.stateObjectsDirty = make(map[ethcmn.Address]struct{})
  1252  	csdb.thash = ethcmn.Hash{}
  1253  	csdb.bhash = ethcmn.Hash{}
  1254  	csdb.txIndex = 0
  1255  	csdb.logSize = 0
  1256  	csdb.preimages = make(map[ethcmn.Hash][]byte)
  1257  	csdb.accessList = newAccessList()
  1258  	csdb.params = nil
  1259  
  1260  	csdb.clearJournalAndRefund()
  1261  	return nil
  1262  }
  1263  
  1264  // ClearStateObjects clears cache of state objects to handle account changes outside of the EVM
  1265  func (csdb *CommitStateDB) ClearStateObjects() {
  1266  	csdb.stateObjects = make(map[ethcmn.Address]*stateObject)
  1267  	csdb.stateObjectsPending = make(map[ethcmn.Address]struct{})
  1268  	csdb.stateObjectsDirty = make(map[ethcmn.Address]struct{})
  1269  }
  1270  
  1271  func (csdb *CommitStateDB) clearJournalAndRefund() {
  1272  	if len(csdb.journal.entries) > 0 {
  1273  		csdb.journal = newJournal()
  1274  		csdb.refund = 0
  1275  	}
  1276  	csdb.validRevisions = csdb.validRevisions[:0] // Snapshots can be created without journal entires
  1277  }
  1278  
  1279  // Prepare sets the current transaction hash and index and block hash which is
  1280  // used when the EVM emits new state logs.
  1281  func (csdb *CommitStateDB) Prepare(thash, bhash ethcmn.Hash, txi int) {
  1282  	csdb.thash = thash
  1283  	csdb.bhash = bhash
  1284  	csdb.txIndex = txi
  1285  }
  1286  
  1287  // CreateAccount explicitly creates a state object. If a state object with the
  1288  // address already exists the balance is carried over to the new account.
  1289  //
  1290  // CreateAccount is called during the EVM CREATE operation. The situation might
  1291  // arise that a contract does the following:
  1292  //
  1293  //  1. sends funds to sha(account ++ (nonce + 1))
  1294  //  2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1)
  1295  //
  1296  // Carrying over the balance ensures that Ether doesn't disappear.
  1297  func (csdb *CommitStateDB) CreateAccount(addr ethcmn.Address) {
  1298  	if !csdb.ctx.IsCheckTx() {
  1299  		funcName := "CreateAccount"
  1300  		trace.StartTxLog(funcName)
  1301  		defer trace.StopTxLog(funcName)
  1302  	}
  1303  
  1304  	newobj, prevobj := csdb.createObject(addr)
  1305  	if prevobj != nil {
  1306  		newobj.setBalance(sdk.DefaultBondDenom, sdk.NewDecFromBigIntWithPrec(prevobj.Balance(), sdk.Precision)) // int2dec
  1307  	}
  1308  }
  1309  
  1310  // ForEachStorage iterates over each storage items, all invoke the provided
  1311  // callback on each key, value pair.
  1312  func (csdb *CommitStateDB) ForEachStorage(addr ethcmn.Address, cb func(key, value ethcmn.Hash) (stop bool)) error {
  1313  	if !csdb.ctx.IsCheckTx() {
  1314  		funcName := "ForEachStorage"
  1315  		trace.StartTxLog(funcName)
  1316  		defer trace.StopTxLog(funcName)
  1317  	}
  1318  
  1319  	so := csdb.getStateObject(addr)
  1320  	if so == nil {
  1321  		return nil
  1322  	}
  1323  
  1324  	if tmtypes.HigherThanMars(csdb.ctx.BlockHeight()) {
  1325  		return csdb.ForEachStorageMpt(so, cb)
  1326  	}
  1327  
  1328  	store := csdb.ctx.KVStore(csdb.storeKey)
  1329  	prefix := AddressStoragePrefix(so.Address())
  1330  	iterator := sdk.KVStorePrefixIterator(store, prefix)
  1331  	defer iterator.Close()
  1332  
  1333  	for ; iterator.Valid(); iterator.Next() {
  1334  		key := ethcmn.BytesToHash(iterator.Key())
  1335  		value := ethcmn.BytesToHash(iterator.Value())
  1336  
  1337  		if value, dirty := so.dirtyStorage[key]; dirty {
  1338  			if cb(key, value) {
  1339  				break
  1340  			}
  1341  			continue
  1342  		}
  1343  
  1344  		// check if iteration stops
  1345  		if cb(key, value) {
  1346  			return nil
  1347  		}
  1348  	}
  1349  
  1350  	return nil
  1351  }
  1352  
  1353  // GetOrNewStateObject retrieves a state object or create a new state object if
  1354  // nil.
  1355  func (csdb *CommitStateDB) GetOrNewStateObject(addr ethcmn.Address) StateObject {
  1356  	so := csdb.getStateObject(addr)
  1357  	if so == nil || so.deleted {
  1358  		so, _ = csdb.createObject(addr)
  1359  	}
  1360  
  1361  	return so
  1362  }
  1363  
  1364  // createObject creates a new state object. If there is an existing account with
  1365  // the given address, it is overwritten and returned as the second return value.
  1366  func (csdb *CommitStateDB) createObject(addr ethcmn.Address) (newObj, prevObj *stateObject) {
  1367  	prevObj = csdb.getStateObject(addr)
  1368  
  1369  	acc := csdb.accountKeeper.NewAccountWithAddress(csdb.ctx, sdk.AccAddress(addr.Bytes()))
  1370  
  1371  	newObj = newStateObject(csdb, acc, ethtypes.EmptyRootHash)
  1372  	newObj.setNonce(0) // sets the object to dirty
  1373  
  1374  	if prevObj == nil {
  1375  		csdb.journal.append(createObjectChange{account: &addr})
  1376  	} else {
  1377  		csdb.journal.append(resetObjectChange{prev: prevObj})
  1378  	}
  1379  	csdb.setStateObject(newObj)
  1380  
  1381  	if prevObj != nil && !prevObj.deleted {
  1382  		return newObj, prevObj
  1383  	}
  1384  	return newObj, nil
  1385  }
  1386  
  1387  // SetError remembers the first non-nil error it is called with.
  1388  func (csdb *CommitStateDB) SetError(err error) {
  1389  	if err != nil {
  1390  		csdb.Logger().Debug("CommitStateDB", "error", err)
  1391  	}
  1392  
  1393  	if csdb.dbErr == nil {
  1394  		csdb.dbErr = err
  1395  	}
  1396  }
  1397  
  1398  // getStateObject attempts to retrieve a state object given by the address.
  1399  // Returns nil and sets an error if not found.
  1400  func (csdb *CommitStateDB) getStateObject(addr ethcmn.Address) (stateObject *stateObject) {
  1401  	if obj := csdb.getDeletedStateObject(addr); obj != nil && !obj.deleted {
  1402  		return obj
  1403  	}
  1404  	return nil
  1405  }
  1406  
  1407  func (csdb *CommitStateDB) setStateObject(so *stateObject) {
  1408  	csdb.stateObjects[so.Address()] = so
  1409  }
  1410  
  1411  // RawDump returns a raw state dump.
  1412  //
  1413  // TODO: Implement if we need it, especially for the RPC API.
  1414  func (csdb *CommitStateDB) RawDump() ethstate.Dump {
  1415  	return ethstate.Dump{}
  1416  }
  1417  
  1418  type preimageEntry struct {
  1419  	// hash key of the preimage entry
  1420  	hash     ethcmn.Hash
  1421  	preimage []byte
  1422  }
  1423  
  1424  func (csdb *CommitStateDB) SetLogSize(logSize uint) {
  1425  	csdb.logSize = logSize
  1426  }
  1427  
  1428  func (csdb *CommitStateDB) GetLogSize() uint {
  1429  	return csdb.logSize
  1430  }
  1431  
  1432  // SetContractDeploymentWhitelistMember sets the target address list into whitelist store
  1433  func (csdb *CommitStateDB) SetContractDeploymentWhitelist(addrList AddressList) {
  1434  	if csdb.ctx.GetWatcher().Enabled() {
  1435  		for i := 0; i < len(addrList); i++ {
  1436  			csdb.ctx.GetWatcher().SaveContractDeploymentWhitelistItem(addrList[i])
  1437  		}
  1438  	}
  1439  
  1440  	var store StoreProxy
  1441  	if tmtypes.HigherThanMars(csdb.ctx.BlockHeight()) {
  1442  		store = csdb.paramSpace.CustomKVStore(csdb.ctx)
  1443  	} else {
  1444  		store = csdb.ctx.KVStore(csdb.storeKey)
  1445  	}
  1446  
  1447  	for i := 0; i < len(addrList); i++ {
  1448  		store.Set(GetContractDeploymentWhitelistMemberKey(addrList[i]), []byte(""))
  1449  	}
  1450  }
  1451  
  1452  // DeleteContractDeploymentWhitelist deletes the target address list from whitelist store
  1453  func (csdb *CommitStateDB) DeleteContractDeploymentWhitelist(addrList AddressList) {
  1454  	if csdb.ctx.GetWatcher().Enabled() {
  1455  		for i := 0; i < len(addrList); i++ {
  1456  			csdb.ctx.GetWatcher().DeleteContractDeploymentWhitelist(addrList[i])
  1457  		}
  1458  	}
  1459  
  1460  	var store StoreProxy
  1461  	if tmtypes.HigherThanMars(csdb.ctx.BlockHeight()) {
  1462  		store = csdb.paramSpace.CustomKVStore(csdb.ctx)
  1463  	} else {
  1464  		store = csdb.ctx.KVStore(csdb.storeKey)
  1465  	}
  1466  
  1467  	for i := 0; i < len(addrList); i++ {
  1468  		store.Delete(GetContractDeploymentWhitelistMemberKey(addrList[i]))
  1469  	}
  1470  }
  1471  
  1472  // GetContractDeploymentWhitelist gets the whole contract deployment whitelist currently
  1473  func (csdb *CommitStateDB) GetContractDeploymentWhitelist() (whitelist AddressList) {
  1474  	var store sdk.KVStore
  1475  	if tmtypes.HigherThanMars(csdb.ctx.BlockHeight()) {
  1476  		store = csdb.paramSpace.CustomKVStore(csdb.ctx)
  1477  	} else {
  1478  		store = csdb.ctx.KVStore(csdb.storeKey)
  1479  	}
  1480  
  1481  	iterator := sdk.KVStorePrefixIterator(store, KeyPrefixContractDeploymentWhitelist)
  1482  	defer iterator.Close()
  1483  
  1484  	for ; iterator.Valid(); iterator.Next() {
  1485  		whitelist = append(whitelist, splitApprovedDeployerAddress(iterator.Key()))
  1486  	}
  1487  
  1488  	return
  1489  }
  1490  
  1491  // IsDeployerInWhitelist checks whether the deployer is in the whitelist as a distributor
  1492  func (csdb *CommitStateDB) IsDeployerInWhitelist(deployerAddr sdk.AccAddress) bool {
  1493  	var bs StoreProxy
  1494  	if tmtypes.HigherThanMars(csdb.ctx.BlockHeight()) {
  1495  		bs = csdb.dbAdapter.NewStore(csdb.paramSpace.CustomKVStore(csdb.ctx), KeyPrefixContractDeploymentWhitelist)
  1496  	} else {
  1497  		bs = csdb.dbAdapter.NewStore(csdb.ctx.KVStore(csdb.storeKey), KeyPrefixContractDeploymentWhitelist)
  1498  	}
  1499  
  1500  	return bs.Has(deployerAddr)
  1501  }
  1502  
  1503  // SetContractBlockedList sets the target address list into blocked list store
  1504  func (csdb *CommitStateDB) SetContractBlockedList(addrList AddressList) {
  1505  	defer GetEvmParamsCache().SetNeedBlockedUpdate()
  1506  	if csdb.ctx.GetWatcher().Enabled() {
  1507  		for i := 0; i < len(addrList); i++ {
  1508  			csdb.ctx.GetWatcher().SaveContractBlockedListItem(addrList[i])
  1509  		}
  1510  	}
  1511  
  1512  	var store sdk.KVStore
  1513  	if tmtypes.HigherThanMars(csdb.ctx.BlockHeight()) {
  1514  		store = csdb.paramSpace.CustomKVStore(csdb.ctx)
  1515  	} else {
  1516  		store = csdb.ctx.KVStore(csdb.storeKey)
  1517  	}
  1518  
  1519  	for i := 0; i < len(addrList); i++ {
  1520  		store.Set(GetContractBlockedListMemberKey(addrList[i]), []byte(""))
  1521  	}
  1522  }
  1523  
  1524  // DeleteContractBlockedList deletes the target address list from blocked list store
  1525  func (csdb *CommitStateDB) DeleteContractBlockedList(addrList AddressList) {
  1526  	defer GetEvmParamsCache().SetNeedBlockedUpdate()
  1527  	if csdb.ctx.GetWatcher().Enabled() {
  1528  		for i := 0; i < len(addrList); i++ {
  1529  			csdb.ctx.GetWatcher().DeleteContractBlockedList(addrList[i])
  1530  		}
  1531  	}
  1532  
  1533  	var store sdk.KVStore
  1534  	if tmtypes.HigherThanMars(csdb.ctx.BlockHeight()) {
  1535  		store = csdb.paramSpace.CustomKVStore(csdb.ctx)
  1536  	} else {
  1537  		store = csdb.ctx.KVStore(csdb.storeKey)
  1538  	}
  1539  
  1540  	for i := 0; i < len(addrList); i++ {
  1541  		store.Delete(GetContractBlockedListMemberKey(addrList[i]))
  1542  	}
  1543  }
  1544  
  1545  // GetContractBlockedList gets the whole contract blocked list currently
  1546  func (csdb *CommitStateDB) GetContractBlockedList() (blockedList AddressList) {
  1547  	var store sdk.KVStore
  1548  	if tmtypes.HigherThanMars(csdb.ctx.BlockHeight()) {
  1549  		store = csdb.paramSpace.CustomKVStore(csdb.ctx)
  1550  	} else {
  1551  		store = csdb.ctx.KVStore(csdb.storeKey)
  1552  	}
  1553  
  1554  	iterator := sdk.KVStorePrefixIterator(store, KeyPrefixContractBlockedList)
  1555  	defer iterator.Close()
  1556  
  1557  	for ; iterator.Valid(); iterator.Next() {
  1558  		if len(iterator.Value()) == 0 {
  1559  			blockedList = append(blockedList, splitBlockedContractAddress(iterator.Key()))
  1560  		}
  1561  	}
  1562  
  1563  	return
  1564  }
  1565  
  1566  // IsContractInBlockedList checks whether the contract address is in the blocked list
  1567  func (csdb *CommitStateDB) IsContractInBlockedList(contractAddr sdk.AccAddress) bool {
  1568  	bc := csdb.GetContractMethodBlockedByAddress(contractAddr)
  1569  	if bc == nil {
  1570  		//contractAddr is not blocked
  1571  		return false
  1572  	}
  1573  	// check contractAddr whether block full-method and special-method
  1574  	return bc.IsAllMethodBlocked()
  1575  }
  1576  
  1577  // GetContractMethodBlockedByAddress gets contract methods blocked by address
  1578  func (csdb *CommitStateDB) GetContractMethodBlockedByAddress(contractAddr sdk.AccAddress) *BlockedContract {
  1579  	if csdb.ctx.UseParamCache() {
  1580  		tempEnableCache := true
  1581  		if GetEvmParamsCache().IsNeedBlockedUpdate() {
  1582  			bcl := csdb.GetContractMethodBlockedList()
  1583  			GetEvmParamsCache().UpdateBlockedContractMethod(bcl, csdb.ctx.IsCheckTx())
  1584  			// Note: when checktx GetEvmParamsCache().UpdateBlockedContractMethod will not be really update, so we must find GetBlockedContract from db.
  1585  			if csdb.ctx.IsCheckTx() {
  1586  				tempEnableCache = false
  1587  			}
  1588  		}
  1589  		if tempEnableCache {
  1590  			return GetEvmParamsCache().GetBlockedContractMethod(amino.BytesToStr(contractAddr))
  1591  		}
  1592  	}
  1593  
  1594  	//use dbAdapter for watchdb or prefixdb
  1595  	var bs StoreProxy
  1596  	if tmtypes.HigherThanMars(csdb.ctx.BlockHeight()) {
  1597  		bs = csdb.dbAdapter.NewStore(csdb.paramSpace.CustomKVStore(csdb.ctx), KeyPrefixContractBlockedList)
  1598  	} else {
  1599  		bs = csdb.dbAdapter.NewStore(csdb.ctx.KVStore(csdb.storeKey), KeyPrefixContractBlockedList)
  1600  	}
  1601  
  1602  	if ok := bs.Has(contractAddr); !ok {
  1603  		// address is not exist
  1604  		return nil
  1605  	} else {
  1606  		value := bs.Get(contractAddr)
  1607  		methods := ContractMethods{}
  1608  		var bc *BlockedContract
  1609  		if len(value) == 0 {
  1610  			//address is exist,but the blocked is old version.
  1611  			bc = NewBlockContract(contractAddr, methods)
  1612  		} else {
  1613  			// get block contract from cache without anmio
  1614  			if contractMethodBlockedCache != nil {
  1615  				if cm, ok := contractMethodBlockedCache.GetContractMethod(value); ok {
  1616  					return NewBlockContract(contractAddr, cm)
  1617  				}
  1618  			}
  1619  			//address is exist,but the blocked is new version.
  1620  			csdb.cdc.MustUnmarshalJSON(value, &methods)
  1621  			bc = NewBlockContract(contractAddr, methods)
  1622  
  1623  			// write block contract into cache
  1624  			if contractMethodBlockedCache != nil {
  1625  				contractMethodBlockedCache.SetContractMethod(value, methods)
  1626  			}
  1627  		}
  1628  		return bc
  1629  	}
  1630  }
  1631  
  1632  // InsertContractMethodBlockedList sets the list of contract method blocked into blocked list store
  1633  func (csdb *CommitStateDB) InsertContractMethodBlockedList(contractList BlockedContractList) sdk.Error {
  1634  	defer GetEvmParamsCache().SetNeedBlockedUpdate()
  1635  	if err := contractList.ValidateExtra(); err != nil {
  1636  		return err
  1637  	}
  1638  	for i := 0; i < len(contractList); i++ {
  1639  		bc := csdb.GetContractMethodBlockedByAddress(contractList[i].Address)
  1640  		if bc != nil {
  1641  			result, err := bc.BlockMethods.InsertContractMethods(contractList[i].BlockMethods)
  1642  			if err != nil {
  1643  				return err
  1644  			}
  1645  			bc.BlockMethods = result
  1646  		} else {
  1647  			bc = &contractList[i]
  1648  		}
  1649  
  1650  		csdb.SetContractMethodBlocked(*bc)
  1651  	}
  1652  	return nil
  1653  }
  1654  
  1655  // DeleteContractMethodBlockedList delete the list of contract method blocked  from blocked list store
  1656  func (csdb *CommitStateDB) DeleteContractMethodBlockedList(contractList BlockedContractList) sdk.Error {
  1657  	defer GetEvmParamsCache().SetNeedBlockedUpdate()
  1658  	for i := 0; i < len(contractList); i++ {
  1659  		bc := csdb.GetContractMethodBlockedByAddress(contractList[i].Address)
  1660  		if bc != nil {
  1661  			result, err := bc.BlockMethods.DeleteContractMethodMap(contractList[i].BlockMethods)
  1662  			if err != nil {
  1663  				return ErrBlockedContractMethodIsNotExist(contractList[i].Address, err)
  1664  			}
  1665  			bc.BlockMethods = result
  1666  			//if block contract method delete empty then remove contract from blocklist.
  1667  			if len(bc.BlockMethods) == 0 {
  1668  				addressList := AddressList{}
  1669  				addressList = append(addressList, bc.Address)
  1670  				//in watchdb contract blocked and contract method blocked use same prefix
  1671  				//so delete contract method blocked is can use function of delete contract blocked
  1672  				csdb.DeleteContractBlockedList(addressList)
  1673  			} else {
  1674  				csdb.SetContractMethodBlocked(*bc)
  1675  			}
  1676  		} else {
  1677  			return ErrBlockedContractMethodIsNotExist(contractList[i].Address, ErrorContractMethodBlockedIsNotExist)
  1678  		}
  1679  	}
  1680  	return nil
  1681  }
  1682  
  1683  // GetContractMethodBlockedList get the list of contract method blocked from blocked list store
  1684  func (csdb *CommitStateDB) GetContractMethodBlockedList() (blockedContractList BlockedContractList) {
  1685  	var store sdk.KVStore
  1686  	if tmtypes.HigherThanMars(csdb.ctx.BlockHeight()) {
  1687  		store = csdb.paramSpace.CustomKVStore(csdb.ctx)
  1688  	} else {
  1689  		store = csdb.ctx.KVStore(csdb.storeKey)
  1690  	}
  1691  
  1692  	iterator := sdk.KVStorePrefixIterator(store, KeyPrefixContractBlockedList)
  1693  	defer iterator.Close()
  1694  
  1695  	for ; iterator.Valid(); iterator.Next() {
  1696  		addr := sdk.AccAddress(splitBlockedContractAddress(iterator.Key()))
  1697  		value := iterator.Value()
  1698  		methods := ContractMethods{}
  1699  		if len(value) != 0 {
  1700  			csdb.cdc.MustUnmarshalJSON(value, &methods)
  1701  		}
  1702  		bc := NewBlockContract(addr, methods)
  1703  		blockedContractList = append(blockedContractList, *bc)
  1704  	}
  1705  	return
  1706  }
  1707  
  1708  // IsContractMethodBlocked checks whether the contract method is blocked
  1709  func (csdb *CommitStateDB) IsContractMethodBlocked(contractAddr sdk.AccAddress, method string) bool {
  1710  	bc := csdb.GetContractMethodBlockedByAddress(contractAddr)
  1711  	if bc == nil {
  1712  		//contractAddr is not blocked
  1713  		return false
  1714  	}
  1715  	// it maybe happens,because ok_verifier verify called before getCode, for executing old logic follow code is return false
  1716  	if bc.IsAllMethodBlocked() {
  1717  		return false
  1718  	}
  1719  	// check contractAddr whether block full-method and special-method
  1720  	return bc.IsMethodBlocked(method)
  1721  }
  1722  
  1723  // SetContractMethodBlocked sets contract method blocked into blocked list store
  1724  func (csdb *CommitStateDB) SetContractMethodBlocked(contract BlockedContract) {
  1725  	SortContractMethods(contract.BlockMethods)
  1726  	value := csdb.cdc.MustMarshalJSON(contract.BlockMethods)
  1727  	value = sdk.MustSortJSON(value)
  1728  	if csdb.ctx.GetWatcher().Enabled() {
  1729  		csdb.ctx.GetWatcher().SaveContractMethodBlockedListItem(contract.Address, value)
  1730  	}
  1731  
  1732  	var store sdk.KVStore
  1733  	if tmtypes.HigherThanMars(csdb.ctx.BlockHeight()) {
  1734  		store = csdb.paramSpace.CustomKVStore(csdb.ctx)
  1735  	} else {
  1736  		store = csdb.ctx.KVStore(csdb.storeKey)
  1737  	}
  1738  
  1739  	key := GetContractBlockedListMemberKey(contract.Address)
  1740  	store.Set(key, value)
  1741  }
  1742  
  1743  func (csdb *CommitStateDB) GetAccount(addr ethcmn.Address) *ethermint.EthAccount {
  1744  	obj := csdb.getStateObject(addr)
  1745  	if obj == nil {
  1746  		return nil
  1747  	}
  1748  	return obj.account
  1749  }
  1750  
  1751  func (csdb *CommitStateDB) UpdateContractBytecode(ctx sdk.Context, p ManageContractByteCodeProposal) sdk.Error {
  1752  	contract := ethcmn.BytesToAddress(p.Contract)
  1753  	substituteContract := ethcmn.BytesToAddress(p.SubstituteContract)
  1754  
  1755  	revertContractByteCode := p.Contract.String() == p.SubstituteContract.String()
  1756  
  1757  	preCode := csdb.GetCode(contract)
  1758  	contractAcc := csdb.GetAccount(contract)
  1759  	if contractAcc == nil {
  1760  		return ErrNotContracAddress(fmt.Errorf("%s", contract.String()))
  1761  	}
  1762  	preCodeHash := contractAcc.CodeHash
  1763  
  1764  	var newCodeHash []byte
  1765  	if revertContractByteCode {
  1766  		newCodeHash = csdb.getInitContractCodeHash(p.Contract)
  1767  		if len(newCodeHash) == 0 || bytes.Equal(preCodeHash, newCodeHash) {
  1768  			return ErrContractCodeNotBeenUpdated(contract.String())
  1769  		}
  1770  	} else {
  1771  		newCodeHash = csdb.GetCodeHash(substituteContract).Bytes()
  1772  	}
  1773  
  1774  	newCode := csdb.GetCodeByHash(ethcmn.BytesToHash(newCodeHash))
  1775  	// update code
  1776  	csdb.SetCode(contract, newCode)
  1777  
  1778  	// store init code
  1779  	csdb.storeInitContractCodeHash(p.Contract, preCodeHash)
  1780  
  1781  	// commit state db
  1782  	csdb.Commit(false)
  1783  	return csdb.afterUpdateContractByteCode(ctx, contract, substituteContract, preCodeHash, preCode, newCode)
  1784  }
  1785  
  1786  var (
  1787  	EventTypeContractUpdateByProposal = "contract-update-by-proposal"
  1788  )
  1789  
  1790  func (csdb *CommitStateDB) afterUpdateContractByteCode(ctx sdk.Context, contract, substituteContract ethcmn.Address, preCodeHash, preCode, newCode []byte) error {
  1791  	contractAfterUpdateCode := csdb.GetAccount(contract)
  1792  	if contractAfterUpdateCode == nil {
  1793  		return ErrNotContracAddress(fmt.Errorf("%s", contractAfterUpdateCode.String()))
  1794  	}
  1795  
  1796  	// log
  1797  	ctx.Logger().Info("updateContractByteCode", "contract", contract, "preCodeHash", hex.EncodeToString(preCodeHash), "preCodeSize", len(preCode),
  1798  		"codeHashAfterUpdateCode", hex.EncodeToString(contractAfterUpdateCode.CodeHash), "codeSizeAfterUpdateCode", len(newCode))
  1799  	// emit event
  1800  	ctx.EventManager().EmitEvent(sdk.NewEvent(
  1801  		EventTypeContractUpdateByProposal,
  1802  		sdk.NewAttribute("contract", contract.String()),
  1803  		sdk.NewAttribute("preCodeHash", hex.EncodeToString(preCodeHash)),
  1804  		sdk.NewAttribute("preCodeSize", fmt.Sprintf("%d", len(preCode))),
  1805  		sdk.NewAttribute("SubstituteContract", substituteContract.String()),
  1806  		sdk.NewAttribute("codeHashAfterUpdateCode", hex.EncodeToString(contractAfterUpdateCode.CodeHash)),
  1807  		sdk.NewAttribute("codeSizeAfterUpdateCode", fmt.Sprintf("%d", len(newCode))),
  1808  	))
  1809  	// update watcher
  1810  	csdb.WithContext(ctx).IteratorCode(func(addr ethcmn.Address, c CacheCode) bool {
  1811  		ctx.GetWatcher().SaveContractCode(addr, c.Code, uint64(ctx.BlockHeight()))
  1812  		ctx.GetWatcher().SaveContractCodeByHash(c.CodeHash, c.Code)
  1813  		ctx.GetWatcher().SaveAccount(contractAfterUpdateCode)
  1814  		return true
  1815  	})
  1816  	return nil
  1817  }
  1818  
  1819  func (csdb *CommitStateDB) storeInitContractCodeHash(addr sdk.AccAddress, codeHash []byte) {
  1820  	var store sdk.KVStore
  1821  	if tmtypes.HigherThanMars(csdb.ctx.BlockHeight()) {
  1822  		store = csdb.paramSpace.CustomKVStore(csdb.ctx)
  1823  	} else {
  1824  		store = csdb.ctx.KVStore(csdb.storeKey)
  1825  	}
  1826  	key := GetInitContractCodeHashKey(addr)
  1827  	if !store.Has(key) {
  1828  		store.Set(key, codeHash)
  1829  	}
  1830  }
  1831  
  1832  func (csdb *CommitStateDB) getInitContractCodeHash(addr sdk.AccAddress) []byte {
  1833  	var store sdk.KVStore
  1834  	if tmtypes.HigherThanMars(csdb.ctx.BlockHeight()) {
  1835  		store = csdb.paramSpace.CustomKVStore(csdb.ctx)
  1836  	} else {
  1837  		store = csdb.ctx.KVStore(csdb.storeKey)
  1838  	}
  1839  	key := GetInitContractCodeHashKey(addr)
  1840  	return store.Get(key)
  1841  }