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 }