github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/app/rpc/namespaces/eth/simulation/evm.go (about)

     1  package simulation
     2  
     3  import (
     4  	"sync"
     5  	"time"
     6  
     7  	"github.com/ethereum/go-ethereum/common"
     8  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store"
     9  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    10  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth"
    11  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/params"
    12  	abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types"
    13  	tmlog "github.com/fibonacci-chain/fbc/libs/tendermint/libs/log"
    14  	dbm "github.com/fibonacci-chain/fbc/libs/tm-db"
    15  	"github.com/fibonacci-chain/fbc/x/evm"
    16  	evmtypes "github.com/fibonacci-chain/fbc/x/evm/types"
    17  	"github.com/fibonacci-chain/fbc/x/evm/watcher"
    18  )
    19  
    20  type EvmFactory struct {
    21  	ChainId        string
    22  	WrappedQuerier *watcher.Querier
    23  	storeKey       *sdk.KVStoreKey
    24  	cms            sdk.CommitMultiStore
    25  	storePool      sync.Pool
    26  }
    27  
    28  func NewEvmFactory(chainId string, q *watcher.Querier) EvmFactory {
    29  	ef := EvmFactory{ChainId: chainId, WrappedQuerier: q, storeKey: sdk.NewKVStoreKey(evm.StoreKey)}
    30  	ef.cms = initCommitMultiStore(ef.storeKey)
    31  	ef.storePool = sync.Pool{
    32  		New: func() interface{} {
    33  			return ef.cms.CacheMultiStore()
    34  		},
    35  	}
    36  	return ef
    37  }
    38  
    39  func initCommitMultiStore(storeKey *sdk.KVStoreKey) sdk.CommitMultiStore {
    40  	db := dbm.NewMemDB()
    41  	cms := store.NewCommitMultiStore(db)
    42  	authKey := sdk.NewKVStoreKey(auth.StoreKey)
    43  	paramsKey := sdk.NewKVStoreKey(params.StoreKey)
    44  	paramsTKey := sdk.NewTransientStoreKey(params.TStoreKey)
    45  	cms.MountStoreWithDB(authKey, sdk.StoreTypeIAVL, db)
    46  	cms.MountStoreWithDB(paramsKey, sdk.StoreTypeIAVL, db)
    47  	cms.MountStoreWithDB(storeKey, sdk.StoreTypeIAVL, db)
    48  	cms.MountStoreWithDB(paramsTKey, sdk.StoreTypeTransient, db)
    49  	cms.LoadLatestVersion()
    50  	return cms
    51  }
    52  
    53  func (ef *EvmFactory) PutBackStorePool(multiStore sdk.CacheMultiStore) {
    54  	multiStore.Clear()
    55  	ef.storePool.Put(multiStore)
    56  }
    57  
    58  func (ef EvmFactory) BuildSimulator(qoc QueryOnChainProxy) *EvmSimulator {
    59  	keeper := ef.makeEvmKeeper(qoc)
    60  	if !watcher.IsWatcherEnabled() {
    61  		return nil
    62  	}
    63  	timestamp := time.Now()
    64  
    65  	latest, _ := ef.WrappedQuerier.GetLatestBlockNumber()
    66  	hash, e := ef.WrappedQuerier.GetBlockHashByNumber(latest)
    67  	if e != nil {
    68  		hash = common.HexToHash("0x000000000000000000000000000000")
    69  	}
    70  
    71  	block, e := ef.WrappedQuerier.GetBlockByHash(hash, false)
    72  
    73  	if e == nil {
    74  		timestamp = time.Unix(int64(block.Timestamp), 0)
    75  	}
    76  	req := abci.RequestBeginBlock{
    77  		Header: abci.Header{
    78  			ChainID: ef.ChainId,
    79  			LastBlockId: abci.BlockID{
    80  				Hash: hash.Bytes(),
    81  			},
    82  			Height: int64(latest),
    83  			Time:   timestamp,
    84  		},
    85  		Hash: hash.Bytes(),
    86  	}
    87  
    88  	multiStore := ef.storePool.Get().(sdk.CacheMultiStore)
    89  	ctx := ef.makeContext(multiStore, req.Header)
    90  
    91  	keeper.BeginBlock(ctx, req)
    92  
    93  	return &EvmSimulator{
    94  		handler: evm.NewHandler(keeper),
    95  		ctx:     ctx,
    96  	}
    97  }
    98  
    99  type EvmSimulator struct {
   100  	handler sdk.Handler
   101  	ctx     sdk.Context
   102  }
   103  
   104  // DoCall call simulate tx. we pass the sender by args to reduce address convert
   105  func (es *EvmSimulator) DoCall(msg *evmtypes.MsgEthereumTx, sender string, overridesBytes []byte, callBack func(sdk.CacheMultiStore)) (*sdk.SimulationResponse, error) {
   106  	defer callBack(es.ctx.MultiStore().(sdk.CacheMultiStore))
   107  	es.ctx.SetFrom(sender)
   108  	if overridesBytes != nil {
   109  		es.ctx.SetOverrideBytes(overridesBytes)
   110  	}
   111  	r, err := es.handler(es.ctx, msg)
   112  	if err != nil {
   113  		return nil, err
   114  	}
   115  	return &sdk.SimulationResponse{
   116  		GasInfo: sdk.GasInfo{
   117  			GasWanted: es.ctx.GasMeter().Limit(),
   118  			GasUsed:   es.ctx.GasMeter().GasConsumed(),
   119  		},
   120  		Result: r,
   121  	}, nil
   122  }
   123  
   124  func (ef EvmFactory) makeEvmKeeper(qoc QueryOnChainProxy) *evm.Keeper {
   125  	return evm.NewSimulateKeeper(qoc.GetCodec(), ef.storeKey, NewSubspaceProxy(), NewAccountKeeperProxy(qoc), SupplyKeeperProxy{}, NewBankKeeperProxy(), StakingKeeperProxy{}, NewInternalDba(qoc), tmlog.NewNopLogger())
   126  }
   127  
   128  func (ef EvmFactory) makeContext(multiStore sdk.CacheMultiStore, header abci.Header) sdk.Context {
   129  	ctx := sdk.NewContext(multiStore, header, true, tmlog.NewNopLogger())
   130  	ctx.SetGasMeter(sdk.NewInfiniteGasMeter())
   131  	return ctx
   132  }