Skip to content

Commit 7d1130e

Browse files
codchenpdrobnjakstevenlanders
authored
[giga] fork x/evm (#2697)
## Describe your changes and provide context create a fork of x/evm under `/giga` and uses this fork for giga executor's logic in `app.go` ## Testing performed to validate your change tests are also copied --------- Co-authored-by: pdrobnjak <drobnjakpavle95@gmail.com> Co-authored-by: Steven Landers <steven.landers@gmail.com> Co-authored-by: Steven Landers <steven@seinetwork.io>
1 parent d996f50 commit 7d1130e

149 files changed

Lines changed: 33783 additions & 31 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

app/app.go

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,6 @@ import (
134134
evmkeeper "github.com/sei-protocol/sei-chain/x/evm/keeper"
135135
"github.com/sei-protocol/sei-chain/x/evm/querier"
136136
"github.com/sei-protocol/sei-chain/x/evm/replay"
137-
evmstate "github.com/sei-protocol/sei-chain/x/evm/state"
138137
evmtypes "github.com/sei-protocol/sei-chain/x/evm/types"
139138
"github.com/sei-protocol/sei-chain/x/mint"
140139
mintclient "github.com/sei-protocol/sei-chain/x/mint/client/cli"
@@ -164,6 +163,9 @@ import (
164163
// unnamed import of statik for openapi/swagger UI support
165164
_ "github.com/sei-protocol/sei-chain/docs/swagger"
166165
ssconfig "github.com/sei-protocol/sei-chain/sei-db/config"
166+
167+
gigaevmkeeper "github.com/sei-protocol/sei-chain/giga/deps/xevm/keeper"
168+
gigaevmstate "github.com/sei-protocol/sei-chain/giga/deps/xevm/state"
167169
)
168170

169171
// this line is used by starport scaffolding # stargate/wasm/app/enabledProposals
@@ -342,6 +344,7 @@ type App struct {
342344
WasmKeeper wasm.Keeper
343345
OracleKeeper oraclekeeper.Keeper
344346
EvmKeeper evmkeeper.Keeper
347+
GigaEvmKeeper gigaevmkeeper.Keeper
345348

346349
// make scoped keepers public for test purposes
347350
ScopedIBCKeeper capabilitykeeper.ScopedKeeper
@@ -402,6 +405,12 @@ type App struct {
402405

403406
benchmarkProposalCh <-chan *abci.ResponsePrepareProposal
404407
benchmarkLogger *benchmarkLogger
408+
409+
// GigaExecutorEnabled controls whether to use the Giga executor (evmone-based)
410+
// instead of geth's interpreter for EVM execution. Experimental feature.
411+
GigaExecutorEnabled bool
412+
// GigaOCCEnabled controls whether to use OCC with the Giga executor
413+
GigaOCCEnabled bool
405414
}
406415

407416
type AppOption func(*App)
@@ -672,19 +681,23 @@ func New(
672681
app.EvmKeeper.EthClient = ethclient.NewClient(rpcclient)
673682
}
674683

684+
app.GigaEvmKeeper = *gigaevmkeeper.NewKeeper(keys[evmtypes.StoreKey],
685+
tkeys[evmtypes.TransientStoreKey], app.GetSubspace(evmtypes.ModuleName), app.receiptStore, app.BankKeeper,
686+
&app.AccountKeeper, &app.StakingKeeper, app.TransferKeeper,
687+
wasmkeeper.NewDefaultPermissionKeeper(app.WasmKeeper), &app.WasmKeeper, &app.UpgradeKeeper)
675688
// Read Giga Executor config
676689
gigaExecutorConfig, err := gigaconfig.ReadConfig(appOpts)
677690
if err != nil {
678691
panic(fmt.Sprintf("error reading giga executor config due to %s", err))
679692
}
680-
app.EvmKeeper.GigaExecutorEnabled = gigaExecutorConfig.Enabled
681-
app.EvmKeeper.GigaOCCEnabled = gigaExecutorConfig.OCCEnabled
693+
app.GigaExecutorEnabled = gigaExecutorConfig.Enabled
694+
app.GigaOCCEnabled = gigaExecutorConfig.OCCEnabled
682695
if gigaExecutorConfig.Enabled {
683696
evmoneVM, err := gigalib.InitEvmoneVM()
684697
if err != nil {
685698
panic(fmt.Sprintf("failed to load evmone: %s", err))
686699
}
687-
app.EvmKeeper.EvmoneVM = evmoneVM
700+
app.GigaEvmKeeper.EvmoneVM = evmoneVM
688701
if gigaExecutorConfig.OCCEnabled {
689702
logger.Info("benchmark: Giga Executor with OCC is ENABLED - using new EVM execution path with parallel execution")
690703
} else {
@@ -1469,8 +1482,8 @@ func (app *App) ProcessBlock(ctx sdk.Context, txs [][]byte, req BlockProcessRequ
14691482
}()
14701483

14711484
// Route to Giga Executor when enabled - bypasses Cosmos SDK transaction processing
1472-
if app.EvmKeeper.GigaExecutorEnabled {
1473-
if app.EvmKeeper.GigaOCCEnabled {
1485+
if app.GigaExecutorEnabled {
1486+
if app.GigaOCCEnabled {
14741487
return app.ProcessBlockWithGigaExecutorOCC(ctx, txs, req, lastCommit, simulate)
14751488
}
14761489
return app.ProcessBlockWithGigaExecutor(ctx, txs, req, lastCommit, simulate)
@@ -1636,7 +1649,7 @@ func (app *App) executeEVMTxWithGigaExecutor(ctx sdk.Context, txIndex int, msg *
16361649
return nil, fmt.Errorf("failed to convert to eth transaction")
16371650
}
16381651

1639-
chainID := app.EvmKeeper.ChainID(ctx)
1652+
chainID := app.GigaEvmKeeper.ChainID(ctx)
16401653

16411654
// Recover sender using the same logic as preprocess.go (version-based signer selection)
16421655
sender, seiAddr, pubkey, recoverErr := evmante.RecoverSenderFromEthTx(ctx, ethTx, chainID)
@@ -1648,8 +1661,8 @@ func (app *App) executeEVMTxWithGigaExecutor(ctx sdk.Context, txIndex int, msg *
16481661
}
16491662

16501663
// Associate the address if not already associated (same as EVMPreprocessDecorator)
1651-
if _, isAssociated := app.EvmKeeper.GetEVMAddress(ctx, seiAddr); !isAssociated {
1652-
associateHelper := helpers.NewAssociationHelper(&app.EvmKeeper, app.BankKeeper, &app.AccountKeeper)
1664+
if _, isAssociated := app.GigaEvmKeeper.GetEVMAddress(ctx, seiAddr); !isAssociated {
1665+
associateHelper := helpers.NewAssociationHelper(&app.GigaEvmKeeper, app.BankKeeper, &app.AccountKeeper)
16531666
if err := associateHelper.AssociateAddresses(ctx, seiAddr, sender, pubkey); err != nil {
16541667
return &abci.ExecTxResult{
16551668
Code: 1,
@@ -1663,14 +1676,14 @@ func (app *App) executeEVMTxWithGigaExecutor(ctx sdk.Context, txIndex int, msg *
16631676
ctx = ctx.WithTxIndex(txIndex)
16641677

16651678
// Create state DB for this transaction
1666-
stateDB := evmstate.NewDBImpl(ctx, &app.EvmKeeper, false)
1679+
stateDB := gigaevmstate.NewDBImpl(ctx, &app.GigaEvmKeeper, false)
16671680
defer stateDB.Cleanup()
16681681

16691682
// Get gas pool
1670-
gp := app.EvmKeeper.GetGasPool()
1683+
gp := app.GigaEvmKeeper.GetGasPool()
16711684

16721685
// Get block context
1673-
blockCtx, blockCtxErr := app.EvmKeeper.GetVMBlockContext(ctx, gp)
1686+
blockCtx, blockCtxErr := app.GigaEvmKeeper.GetVMBlockContext(ctx, gp)
16741687
if blockCtxErr != nil {
16751688
return &abci.ExecTxResult{
16761689
Code: 1,
@@ -1679,14 +1692,14 @@ func (app *App) executeEVMTxWithGigaExecutor(ctx sdk.Context, txIndex int, msg *
16791692
}
16801693

16811694
// Get chain config
1682-
sstore := app.EvmKeeper.GetParams(ctx).SeiSstoreSetGasEip2200
1683-
cfg := evmtypes.DefaultChainConfig().EthereumConfigWithSstore(app.EvmKeeper.ChainID(ctx), &sstore)
1695+
sstore := app.GigaEvmKeeper.GetParams(ctx).SeiSstoreSetGasEip2200
1696+
cfg := evmtypes.DefaultChainConfig().EthereumConfigWithSstore(app.GigaEvmKeeper.ChainID(ctx), &sstore)
16841697

16851698
// Create Giga executor VM (wraps evmone)
1686-
gigaExecutor := gigaexecutor.NewEvmoneExecutor(app.EvmKeeper.EvmoneVM, *blockCtx, stateDB, cfg, vm.Config{}, app.EvmKeeper.CustomPrecompiles(ctx))
1699+
gigaExecutor := gigaexecutor.NewEvmoneExecutor(app.GigaEvmKeeper.EvmoneVM, *blockCtx, stateDB, cfg, vm.Config{}, app.GigaEvmKeeper.CustomPrecompiles(ctx))
16871700

16881701
// Execute the transaction through giga VM
1689-
execResult, execErr := gigaExecutor.ExecuteTransaction(ethTx, sender, app.EvmKeeper.GetBaseFee(ctx), &gp)
1702+
execResult, execErr := gigaExecutor.ExecuteTransaction(ethTx, sender, app.GigaEvmKeeper.GetBaseFee(ctx), &gp)
16901703
if execErr != nil {
16911704
return &abci.ExecTxResult{
16921705
Code: 1,
@@ -1722,7 +1735,7 @@ func (app *App) executeEVMTxWithGigaExecutor(ctx sdk.Context, txIndex int, msg *
17221735
Data: ethTx.Data(),
17231736
From: sender,
17241737
}
1725-
receipt, rerr := app.EvmKeeper.WriteReceipt(ctx, stateDB, evmMsg, uint32(ethTx.Type()), ethTx.Hash(), execResult.UsedGas, vmError)
1738+
receipt, rerr := app.GigaEvmKeeper.WriteReceipt(ctx, stateDB, evmMsg, uint32(ethTx.Type()), ethTx.Hash(), execResult.UsedGas, vmError)
17261739
if rerr != nil {
17271740
return &abci.ExecTxResult{
17281741
Code: 1,
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package fuzzing
2+
3+
import (
4+
sdk "github.com/cosmos/cosmos-sdk/types"
5+
)
6+
7+
func FuzzDec(i int64, isNil bool) sdk.Dec {
8+
if isNil {
9+
return sdk.Dec{}
10+
}
11+
return sdk.NewDec(i)
12+
}
13+
14+
func FuzzCoin(denom string, isNil bool, i int64) sdk.Coin {
15+
if isNil {
16+
return sdk.Coin{Denom: denom, Amount: sdk.Int{}}
17+
}
18+
return sdk.Coin{Denom: denom, Amount: sdk.NewInt(i)}
19+
}

giga/deps/testutil/keeper/epoch.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package keeper
2+
3+
import (
4+
"testing"
5+
6+
"github.com/cosmos/cosmos-sdk/codec"
7+
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
8+
"github.com/cosmos/cosmos-sdk/store"
9+
storetypes "github.com/cosmos/cosmos-sdk/store/types"
10+
sdk "github.com/cosmos/cosmos-sdk/types"
11+
typesparams "github.com/cosmos/cosmos-sdk/x/params/types"
12+
"github.com/sei-protocol/sei-chain/app"
13+
"github.com/sei-protocol/sei-chain/x/epoch/keeper"
14+
"github.com/sei-protocol/sei-chain/x/epoch/types"
15+
"github.com/stretchr/testify/require"
16+
"github.com/tendermint/tendermint/libs/log"
17+
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
18+
tmdb "github.com/tendermint/tm-db"
19+
)
20+
21+
func TestApp(t *testing.T) *app.App {
22+
return app.Setup(t, false, false, false)
23+
}
24+
25+
func EpochKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) {
26+
storeKey := sdk.NewKVStoreKey(types.StoreKey)
27+
memStoreKey := storetypes.NewMemoryStoreKey(types.MemStoreKey)
28+
29+
db := tmdb.NewMemDB()
30+
stateStore := store.NewCommitMultiStore(db)
31+
stateStore.MountStoreWithDB(storeKey, sdk.StoreTypeIAVL, db)
32+
stateStore.MountStoreWithDB(memStoreKey, sdk.StoreTypeMemory, nil)
33+
require.NoError(t, stateStore.LoadLatestVersion())
34+
35+
registry := codectypes.NewInterfaceRegistry()
36+
cdc := codec.NewProtoCodec(registry)
37+
38+
paramsSubspace := typesparams.NewSubspace(cdc,
39+
codec.NewLegacyAmino(),
40+
storeKey,
41+
memStoreKey,
42+
"EpochParams",
43+
)
44+
k := keeper.NewKeeper(
45+
cdc,
46+
storeKey,
47+
memStoreKey,
48+
paramsSubspace,
49+
)
50+
51+
ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger())
52+
53+
// Initialize params
54+
k.SetParams(ctx, types.DefaultParams())
55+
56+
return k, ctx
57+
}

giga/deps/testutil/keeper/evm.go

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
package keeper
2+
3+
import (
4+
"encoding/hex"
5+
"sync"
6+
"testing"
7+
"time"
8+
9+
"github.com/cosmos/cosmos-sdk/crypto/hd"
10+
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
11+
sdk "github.com/cosmos/cosmos-sdk/types"
12+
"github.com/cosmos/go-bip39"
13+
"github.com/ethereum/go-ethereum/common"
14+
"github.com/ethereum/go-ethereum/crypto"
15+
16+
"github.com/sei-protocol/sei-chain/app"
17+
evmkeeper "github.com/sei-protocol/sei-chain/giga/deps/xevm/keeper"
18+
evmtypes "github.com/sei-protocol/sei-chain/giga/deps/xevm/types"
19+
"github.com/stretchr/testify/require"
20+
)
21+
22+
var EVMTestApp = app.SetupWithDefaultHome(false, true, false)
23+
var mockKeeper *evmkeeper.Keeper
24+
var mockCtx sdk.Context
25+
var mtx = &sync.Mutex{}
26+
27+
func MockEVMKeeperWithPrecompiles() (*evmkeeper.Keeper, sdk.Context) {
28+
mtx.Lock()
29+
defer mtx.Unlock()
30+
if mockKeeper != nil {
31+
return mockKeeper, mockCtx
32+
}
33+
ctx := EVMTestApp.GetContextForDeliverTx([]byte{}).WithBlockHeight(8)
34+
k := EVMTestApp.GigaEvmKeeper
35+
k.InitGenesis(ctx, *evmtypes.DefaultGenesis())
36+
37+
// mint some coins to a sei address
38+
seiAddr, err := sdk.AccAddressFromHex(common.Bytes2Hex([]byte("seiAddr")))
39+
if err != nil {
40+
panic(err)
41+
}
42+
err = EVMTestApp.BankKeeper.MintCoins(ctx, "evm", sdk.NewCoins(sdk.NewCoin("usei", sdk.NewInt(10))))
43+
if err != nil {
44+
panic(err)
45+
}
46+
err = EVMTestApp.BankKeeper.SendCoinsFromModuleToAccount(ctx, "evm", seiAddr, sdk.NewCoins(sdk.NewCoin("usei", sdk.NewInt(10))))
47+
if err != nil {
48+
panic(err)
49+
}
50+
mockKeeper = &k
51+
mockCtx = ctx
52+
return &k, ctx
53+
}
54+
55+
func MockEVMKeeper(t *testing.T) (*evmkeeper.Keeper, sdk.Context) {
56+
testApp := app.Setup(t, false, false, false)
57+
ctx := testApp.GetContextForDeliverTx([]byte{}).WithBlockHeight(8).WithBlockTime(time.Now())
58+
k := testApp.GigaEvmKeeper
59+
k.InitGenesis(ctx, *evmtypes.DefaultGenesis())
60+
61+
// mint some coins to a sei address
62+
seiAddr, err := sdk.AccAddressFromHex(common.Bytes2Hex([]byte("seiAddr")))
63+
if err != nil {
64+
panic(err)
65+
}
66+
err = testApp.BankKeeper.MintCoins(ctx, "evm", sdk.NewCoins(sdk.NewCoin("usei", sdk.NewInt(10))))
67+
if err != nil {
68+
panic(err)
69+
}
70+
err = testApp.BankKeeper.SendCoinsFromModuleToAccount(ctx, "evm", seiAddr, sdk.NewCoins(sdk.NewCoin("usei", sdk.NewInt(10))))
71+
if err != nil {
72+
panic(err)
73+
}
74+
return &k, ctx
75+
}
76+
77+
func MockEVMKeeperPrecompiles(t *testing.T) (*evmkeeper.Keeper, sdk.Context) {
78+
testApp := app.Setup(t, false, true, false)
79+
ctx := testApp.GetContextForDeliverTx([]byte{}).WithBlockHeight(8).WithBlockTime(time.Now())
80+
k := testApp.GigaEvmKeeper
81+
k.InitGenesis(ctx, *evmtypes.DefaultGenesis())
82+
83+
// mint some coins to a sei address
84+
seiAddr, err := sdk.AccAddressFromHex(common.Bytes2Hex([]byte("seiAddr")))
85+
if err != nil {
86+
panic(err)
87+
}
88+
err = testApp.BankKeeper.MintCoins(ctx, "evm", sdk.NewCoins(sdk.NewCoin("usei", sdk.NewInt(10))))
89+
if err != nil {
90+
panic(err)
91+
}
92+
err = testApp.BankKeeper.SendCoinsFromModuleToAccount(ctx, "evm", seiAddr, sdk.NewCoins(sdk.NewCoin("usei", sdk.NewInt(10))))
93+
if err != nil {
94+
panic(err)
95+
}
96+
return &k, ctx
97+
}
98+
99+
func MockAddressPair() (sdk.AccAddress, common.Address) {
100+
return PrivateKeyToAddresses(MockPrivateKey())
101+
}
102+
103+
func MockPrivateKey() cryptotypes.PrivKey {
104+
// Generate a new Sei private key
105+
entropySeed, _ := bip39.NewEntropy(256)
106+
mnemonic, _ := bip39.NewMnemonic(entropySeed)
107+
algo := hd.Secp256k1
108+
derivedPriv, _ := algo.Derive()(mnemonic, "", "")
109+
return algo.Generate()(derivedPriv)
110+
}
111+
112+
func PrivateKeyToAddresses(privKey cryptotypes.PrivKey) (sdk.AccAddress, common.Address) {
113+
// Encode the private key to hex (i.e. what wallets do behind the scene when users reveal private keys)
114+
testPrivHex := hex.EncodeToString(privKey.Bytes())
115+
116+
// Sign an Ethereum transaction with the hex private key
117+
key, _ := crypto.HexToECDSA(testPrivHex)
118+
msg := crypto.Keccak256([]byte("foo"))
119+
sig, _ := crypto.Sign(msg, key)
120+
121+
// Recover the public keys from the Ethereum signature
122+
recoveredPub, _ := crypto.Ecrecover(msg, sig)
123+
pubKey, _ := crypto.UnmarshalPubkey(recoveredPub)
124+
125+
return sdk.AccAddress(privKey.PubKey().Address()), crypto.PubkeyToAddress(*pubKey)
126+
}
127+
128+
func UseiCoins(amount int64) sdk.Coins {
129+
return sdk.NewCoins(sdk.NewCoin(sdk.MustGetBaseDenom(), sdk.NewInt(amount)))
130+
}
131+
132+
func WaitForReceipt(t *testing.T, k *evmkeeper.Keeper, ctx sdk.Context, txHash common.Hash) *evmtypes.Receipt {
133+
t.Helper()
134+
var receipt *evmtypes.Receipt
135+
require.Eventually(t, func() bool {
136+
var err error
137+
receipt, err = k.GetReceipt(ctx, txHash)
138+
return err == nil
139+
}, 2*time.Second, 10*time.Millisecond)
140+
return receipt
141+
}
142+
143+
func WaitForReceiptFromStore(t *testing.T, k *evmkeeper.Keeper, ctx sdk.Context, txHash common.Hash) *evmtypes.Receipt {
144+
t.Helper()
145+
var receipt *evmtypes.Receipt
146+
require.Eventually(t, func() bool {
147+
var err error
148+
receipt, err = k.GetReceiptFromReceiptStore(ctx, txHash)
149+
return err == nil
150+
}, 2*time.Second, 10*time.Millisecond)
151+
return receipt
152+
}
153+
154+
func MustMockReceipt(t *testing.T, k *evmkeeper.Keeper, ctx sdk.Context, txHash common.Hash, receipt *evmtypes.Receipt) {
155+
t.Helper()
156+
require.NoError(t, k.MockReceipt(ctx, txHash, receipt))
157+
WaitForReceipt(t, k, ctx, txHash)
158+
}

0 commit comments

Comments
 (0)