-
Notifications
You must be signed in to change notification settings - Fork 179
/
evm.go
111 lines (93 loc) · 3.09 KB
/
evm.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package simulation
import (
"time"
"github.com/okex/exchain/libs/cosmos-sdk/codec"
"github.com/okex/exchain/libs/cosmos-sdk/store"
sdk "github.com/okex/exchain/libs/cosmos-sdk/types"
"github.com/okex/exchain/libs/cosmos-sdk/x/auth"
"github.com/okex/exchain/libs/cosmos-sdk/x/params"
"github.com/ethereum/go-ethereum/common"
"github.com/okex/exchain/x/evm"
evmtypes "github.com/okex/exchain/x/evm/types"
"github.com/okex/exchain/x/evm/watcher"
abci "github.com/okex/exchain/libs/tendermint/abci/types"
tmlog "github.com/okex/exchain/libs/tendermint/libs/log"
dbm "github.com/tendermint/tm-db"
)
type EvmFactory struct {
ChainId string
WrappedQuerier *watcher.Querier
}
func NewEvmFactory(chainId string, q *watcher.Querier) EvmFactory {
return EvmFactory{ChainId: chainId, WrappedQuerier: q}
}
func (ef EvmFactory) BuildSimulator(qoc QueryOnChainProxy) *EvmSimulator {
keeper := ef.makeEvmKeeper(qoc)
if !watcher.IsWatcherEnabled() {
return nil
}
timestamp := time.Now()
latest, _ := ef.WrappedQuerier.GetLatestBlockNumber()
hash, e := ef.WrappedQuerier.GetBlockHashByNumber(latest)
if e != nil {
hash = common.HexToHash("0x000000000000000000000000000000")
}
block, e := ef.WrappedQuerier.GetBlockByHash(hash, false)
if e == nil {
timestamp = time.Unix(int64(block.Timestamp), 0)
}
req := abci.RequestBeginBlock{
Header: abci.Header{
ChainID: ef.ChainId,
LastBlockId: abci.BlockID{
Hash: hash.Bytes(),
},
Height: int64(latest),
Time: timestamp,
},
Hash: hash.Bytes(),
}
ctx := ef.makeContext(keeper, req.Header)
keeper.BeginBlock(ctx, req)
return &EvmSimulator{
handler: evm.NewHandler(keeper),
ctx: ctx,
}
}
type EvmSimulator struct {
handler sdk.Handler
ctx sdk.Context
}
func (es *EvmSimulator) DoCall(msg evmtypes.MsgEthermint) (*sdk.SimulationResponse, error) {
r, e := es.handler(es.ctx, msg)
if e != nil {
return nil, e
}
return &sdk.SimulationResponse{
GasInfo: sdk.GasInfo{
GasWanted: es.ctx.GasMeter().Limit(),
GasUsed: es.ctx.GasMeter().GasConsumed(),
},
Result: r,
}, nil
}
func (ef EvmFactory) makeEvmKeeper(qoc QueryOnChainProxy) *evm.Keeper {
module := evm.AppModuleBasic{}
cdc := codec.New()
module.RegisterCodec(cdc)
return evm.NewSimulateKeeper(cdc, sdk.NewKVStoreKey(evm.StoreKey), NewSubspaceProxy(), NewAccountKeeperProxy(qoc), SupplyKeeperProxy{}, NewBankKeeperProxy(), NewInternalDba(qoc), tmlog.NewNopLogger())
}
func (ef EvmFactory) makeContext(k *evm.Keeper, header abci.Header) sdk.Context {
db := dbm.NewMemDB()
cms := store.NewCommitMultiStore(db)
authKey := sdk.NewKVStoreKey(auth.StoreKey)
paramsKey := sdk.NewKVStoreKey(params.StoreKey)
paramsTKey := sdk.NewTransientStoreKey(params.TStoreKey)
cms.MountStoreWithDB(authKey, sdk.StoreTypeIAVL, db)
cms.MountStoreWithDB(paramsKey, sdk.StoreTypeIAVL, db)
cms.MountStoreWithDB(k.GetStoreKey(), sdk.StoreTypeIAVL, db)
cms.MountStoreWithDB(paramsTKey, sdk.StoreTypeTransient, db)
cms.LoadLatestVersion()
ctx := sdk.NewContext(cms, header, true, tmlog.NewNopLogger()).WithGasMeter(sdk.NewGasMeter(evmtypes.DefaultMaxGasLimitPerTx))
return ctx
}