Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem: block-stm is not integrated from sdk #564

Draft
wants to merge 5 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -809,15 +809,22 @@
app.ScopedIBCKeeper = scopedIBCKeeper
app.ScopedTransferKeeper = scopedTransferKeeper

executor := cast.ToString(appOpts.Get(srvflags.EVMBlockExecutor))
executor := cast.ToString(appOpts.Get(server.FlagBlockSTMExecutor))
app.SetTxResponsePatcher(evmtypes.EvmTxResponsePatcher{})
switch executor {
case srvconfig.BlockExecutorBlockSTM:
case config.BlockExecutorBlockSTM:

Check warning on line 815 in app/app.go

View check run for this annotation

Codecov / codecov/patch

app/app.go#L815

Added line #L815 was not covered by tests
sdk.SetAddrCacheEnabled(false)
workers := cast.ToInt(appOpts.Get(srvflags.EVMBlockSTMWorkers))
preEstimate := cast.ToBool(appOpts.Get(srvflags.EVMBlockSTMPreEstimate))
app.SetTxExecutor(STMTxExecutor(app.GetStoreKeys(), workers, preEstimate, app.EvmKeeper, txConfig.TxDecoder()))
case "", srvconfig.BlockExecutorSequential:
app.SetTxExecutor(DefaultTxExecutor)
workers := cast.ToInt(appOpts.Get(server.FlagBlockSTMWorkers))
preEstimate := cast.ToBool(appOpts.Get(server.FlagBlockSTMPreEstimate))
txDecoder := txConfig.TxDecoder()
stores := app.GetStoreKeys()
var preEstimateFn PreEstimateFunc
if preEstimate {
preEstimateFn = GetPreEstimateFunc(stores, app.EvmKeeper)
}
app.SetTxExecutor(baseapp.STMTxExecutor(stores, workers, txDecoder, preEstimateFn))

Check warning on line 825 in app/app.go

View check run for this annotation

Codecov / codecov/patch

app/app.go#L817-L825

Added lines #L817 - L825 were not covered by tests
case "", config.BlockExecutorSequential:
app.SetTxExecutor(baseapp.DefaultTxExecutor)
default:
panic(fmt.Errorf("unknown EVM block executor: %s", executor))
}
Expand Down
188 changes: 17 additions & 171 deletions app/executor.go
Original file line number Diff line number Diff line change
@@ -1,195 +1,41 @@
package app

import (
"context"
"io"
"sync"
"sync/atomic"

"cosmossdk.io/collections"
"cosmossdk.io/log"
"cosmossdk.io/store/cachemulti"
storetypes "cosmossdk.io/store/types"
abci "github.com/cometbft/cometbft/abci/types"
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
evmtypes "github.com/evmos/ethermint/x/evm/types"
evmkeeper "github.com/evmos/ethermint/x/evm/keeper"

"github.com/cosmos/cosmos-sdk/baseapp"
sdk "github.com/cosmos/cosmos-sdk/types"

blockstm "github.com/crypto-org-chain/go-block-stm"
)

const MinimalParallelPreEstimate = 16

func DefaultTxExecutor(_ context.Context,
txs [][]byte,
ms storetypes.MultiStore,
deliverTxWithMultiStore func(int, sdk.Tx, storetypes.MultiStore, map[string]any) *abci.ExecTxResult,
) ([]*abci.ExecTxResult, error) {
blockSize := len(txs)
results := make([]*abci.ExecTxResult, blockSize)
for i := 0; i < blockSize; i++ {
results[i] = deliverTxWithMultiStore(i, nil, ms, nil)
}
return evmtypes.PatchTxResponses(results), nil
}

type evmKeeper interface {
GetParams(ctx sdk.Context) evmtypes.Params
}

func STMTxExecutor(
stores []storetypes.StoreKey,
workers int,
estimate bool,
evmKeeper evmKeeper,
txDecoder sdk.TxDecoder,
) baseapp.TxExecutor {
var authStore, bankStore int
index := make(map[storetypes.StoreKey]int, len(stores))
for i, k := range stores {
switch k.Name() {
case authtypes.StoreKey:
authStore = i
case banktypes.StoreKey:
bankStore = i
}
index[k] = i
}
return func(
ctx context.Context,
txs [][]byte,
ms storetypes.MultiStore,
deliverTxWithMultiStore func(int, sdk.Tx, storetypes.MultiStore, map[string]any) *abci.ExecTxResult,
) ([]*abci.ExecTxResult, error) {
blockSize := len(txs)
if blockSize == 0 {
return nil, nil
}
results := make([]*abci.ExecTxResult, blockSize)
incarnationCache := make([]atomic.Pointer[map[string]any], blockSize)
for i := 0; i < blockSize; i++ {
m := make(map[string]any)
incarnationCache[i].Store(&m)
}

var (
estimates []blockstm.MultiLocations
memTxs []sdk.Tx
)
if estimate {
// pre-estimation
evmDenom := evmKeeper.GetParams(sdk.NewContext(ms, cmtproto.Header{}, false, log.NewNopLogger())).EvmDenom
memTxs, estimates = preEstimates(txs, workers, authStore, bankStore, evmDenom, txDecoder)
}

if err := blockstm.ExecuteBlockWithEstimates(
ctx,
blockSize,
index,
stmMultiStoreWrapper{ms},
workers,
estimates,
func(txn blockstm.TxnIndex, ms blockstm.MultiStore) {
var cache map[string]any

// only one of the concurrent incarnations gets the cache if there are any, otherwise execute without
// cache, concurrent incarnations should be rare.
v := incarnationCache[txn].Swap(nil)
if v != nil {
cache = *v
}

var memTx sdk.Tx
if memTxs != nil {
memTx = memTxs[txn]
}
results[txn] = deliverTxWithMultiStore(int(txn), memTx, msWrapper{ms}, cache)

if v != nil {
incarnationCache[txn].Store(v)
}
},
); err != nil {
return nil, err
type PreEstimateFunc func(txs [][]byte, workers int, txDecoder sdk.TxDecoder, ms storetypes.MultiStore) ([]sdk.Tx, []blockstm.MultiLocations)

func GetPreEstimateFunc(stores []storetypes.StoreKey, evmKeeper *evmkeeper.Keeper) PreEstimateFunc {
return func(txs [][]byte, workers int, txDecoder sdk.TxDecoder, ms storetypes.MultiStore) ([]sdk.Tx, []blockstm.MultiLocations) {
var authStore, bankStore int
index := make(map[storetypes.StoreKey]int, len(stores))
for i, k := range stores {
switch k.Name() {
case authtypes.StoreKey:
authStore = i
case banktypes.StoreKey:
bankStore = i

Check warning on line 30 in app/executor.go

View check run for this annotation

Codecov / codecov/patch

app/executor.go#L21-L30

Added lines #L21 - L30 were not covered by tests
}
index[k] = i

Check warning on line 32 in app/executor.go

View check run for this annotation

Codecov / codecov/patch

app/executor.go#L32

Added line #L32 was not covered by tests
}

return evmtypes.PatchTxResponses(results), nil
evmDenom := evmKeeper.GetParams(sdk.NewContext(ms, cmtproto.Header{}, false, log.NewNopLogger())).EvmDenom
return preEstimates(txs, workers, authStore, bankStore, evmDenom, txDecoder)

Check warning on line 35 in app/executor.go

View check run for this annotation

Codecov / codecov/patch

app/executor.go#L34-L35

Added lines #L34 - L35 were not covered by tests
}
}

type msWrapper struct {
blockstm.MultiStore
}

var _ storetypes.MultiStore = msWrapper{}

func (ms msWrapper) getCacheWrapper(key storetypes.StoreKey) storetypes.CacheWrapper {
return ms.GetStore(key)
}

func (ms msWrapper) GetStore(key storetypes.StoreKey) storetypes.Store {
return ms.MultiStore.GetStore(key)
}

func (ms msWrapper) GetKVStore(key storetypes.StoreKey) storetypes.KVStore {
return ms.MultiStore.GetKVStore(key)
}

func (ms msWrapper) GetObjKVStore(key storetypes.StoreKey) storetypes.ObjKVStore {
return ms.MultiStore.GetObjKVStore(key)
}

func (ms msWrapper) CacheMultiStore() storetypes.CacheMultiStore {
return cachemulti.NewFromParent(ms.getCacheWrapper, nil, nil)
}

// Implements CacheWrapper.
func (ms msWrapper) CacheWrap() storetypes.CacheWrap {
return ms.CacheMultiStore().(storetypes.CacheWrap)
}

// GetStoreType returns the type of the store.
func (ms msWrapper) GetStoreType() storetypes.StoreType {
return storetypes.StoreTypeMulti
}

// Implements interface MultiStore
func (ms msWrapper) SetTracer(io.Writer) storetypes.MultiStore {
return nil
}

// Implements interface MultiStore
func (ms msWrapper) SetTracingContext(storetypes.TraceContext) storetypes.MultiStore {
return nil
}

// Implements interface MultiStore
func (ms msWrapper) TracingEnabled() bool {
return false
}

type stmMultiStoreWrapper struct {
storetypes.MultiStore
}

var _ blockstm.MultiStore = stmMultiStoreWrapper{}

func (ms stmMultiStoreWrapper) GetStore(key storetypes.StoreKey) storetypes.Store {
return ms.MultiStore.GetStore(key)
}

func (ms stmMultiStoreWrapper) GetKVStore(key storetypes.StoreKey) storetypes.KVStore {
return ms.MultiStore.GetKVStore(key)
}

func (ms stmMultiStoreWrapper) GetObjKVStore(key storetypes.StoreKey) storetypes.ObjKVStore {
return ms.MultiStore.GetObjKVStore(key)
}

// preEstimates returns a static estimation of the written keys for each transaction.
// NOTE: make sure it sync with the latest sdk logic when sdk upgrade.
func preEstimates(txs [][]byte, workers, authStore, bankStore int, evmDenom string, txDecoder sdk.TxDecoder) ([]sdk.Tx, []blockstm.MultiLocations) {
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -242,9 +242,9 @@ require (

replace (
// release/v0.50.x
cosmossdk.io/store => github.com/crypto-org-chain/cosmos-sdk/store v0.0.0-20241015015202-783e224f9517
cosmossdk.io/x/tx => github.com/crypto-org-chain/cosmos-sdk/x/tx v0.0.0-20241015015202-783e224f9517
github.com/cosmos/cosmos-sdk => github.com/crypto-org-chain/cosmos-sdk v0.50.6-0.20241015015202-783e224f9517
cosmossdk.io/store => github.com/mmsqe/cosmos-sdk/store v0.0.0-20241211125423-756926949166
cosmossdk.io/x/tx => github.com/mmsqe/cosmos-sdk/x/tx v0.0.0-20241211125423-756926949166
github.com/cosmos/cosmos-sdk => github.com/mmsqe/cosmos-sdk v0.46.0-beta2.0.20241211125423-756926949166
)

replace (
Expand Down
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -410,12 +410,6 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/crypto-org-chain/btree v0.0.0-20240406140148-2687063b042c h1:MOgfS4+FBB8cMkDE2j2VBVsbY+HCkPIu0YsJ/9bbGeQ=
github.com/crypto-org-chain/btree v0.0.0-20240406140148-2687063b042c/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY=
github.com/crypto-org-chain/cosmos-sdk v0.50.6-0.20241015015202-783e224f9517 h1:iRnJMiquXPE3OpVX8ENCrcstfd7mI206yC3Bkl6WeK4=
github.com/crypto-org-chain/cosmos-sdk v0.50.6-0.20241015015202-783e224f9517/go.mod h1:JwwsMeZldLN20b72mmbWPY0EV9rs+v/12hRu1JFttvY=
github.com/crypto-org-chain/cosmos-sdk/store v0.0.0-20241015015202-783e224f9517 h1:y3i8TiU7E60zmbpLyo4PqrnwZaWNU3kizU+1OezuoA8=
github.com/crypto-org-chain/cosmos-sdk/store v0.0.0-20241015015202-783e224f9517/go.mod h1:8DwVTz83/2PSI366FERGbWSH7hL6sB7HbYp8bqksNwM=
github.com/crypto-org-chain/cosmos-sdk/x/tx v0.0.0-20241015015202-783e224f9517 h1:CwheSMAqz+kYCFz/X4lZq3BJAWINm/hndzVkjOc/2mI=
github.com/crypto-org-chain/cosmos-sdk/x/tx v0.0.0-20241015015202-783e224f9517/go.mod h1:V6DImnwJMTq5qFjeGWpXNiT/fjgE4HtmclRmTqRVM3w=
github.com/crypto-org-chain/go-block-stm v0.0.0-20240919080136-6c49aef68716 h1:OvD5Rm0B6LHUJk6z858UgwdP72jU2DuUdXeclRyKpDI=
github.com/crypto-org-chain/go-block-stm v0.0.0-20240919080136-6c49aef68716/go.mod h1:iwQTX9xMX8NV9k3o2BiWXA0SswpsZrDk5q3gA7nWYiE=
github.com/crypto-org-chain/go-ethereum v1.10.20-0.20241030073450-b9cc632bc183 h1:JDBTqDkd9X9oBF2C4FKOpn0GVDQDzVkHzeS8eDWNl6A=
Expand Down Expand Up @@ -873,6 +867,12 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A=
github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4=
github.com/mmsqe/cosmos-sdk v0.46.0-beta2.0.20241211125423-756926949166 h1:V4V18HyEijuRDU2yYs7d4ISg3PskaYzkxQLFJuD4KKQ=
github.com/mmsqe/cosmos-sdk v0.46.0-beta2.0.20241211125423-756926949166/go.mod h1:bkUh1YaLvBd4WAYd8iE0xwpHecaqH8A7vg6v/YCj0yo=
github.com/mmsqe/cosmos-sdk/store v0.0.0-20241211125423-756926949166 h1:33rsrNKVmEu859tr4sDBpAiafhyNWSblX5vpaQjoafE=
github.com/mmsqe/cosmos-sdk/store v0.0.0-20241211125423-756926949166/go.mod h1:8DwVTz83/2PSI366FERGbWSH7hL6sB7HbYp8bqksNwM=
github.com/mmsqe/cosmos-sdk/x/tx v0.0.0-20241211125423-756926949166 h1:fufnTgFbNYXISiTY1ZGE5S4IKEFd379DF8uKJgX4B4g=
github.com/mmsqe/cosmos-sdk/x/tx v0.0.0-20241211125423-756926949166/go.mod h1:V6DImnwJMTq5qFjeGWpXNiT/fjgE4HtmclRmTqRVM3w=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
Expand Down
18 changes: 9 additions & 9 deletions gomod2nix.toml

Large diffs are not rendered by default.

28 changes: 4 additions & 24 deletions server/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,18 +98,13 @@
// DefaultRosettaDenomToSuggest defines the default denom for fee suggestion
DefaultRosettaDenomToSuggest = "basecro"

BlockExecutorSequential = "sequential"
BlockExecutorBlockSTM = "block-stm"
DefaultMaxTxs = 3000
DefaultMaxTxs = 3000
)

var (
// DefaultRosettaGasPrices defines the default list of prices to suggest
DefaultRosettaGasPrices = sdk.NewDecCoins(sdk.NewDecCoin(DefaultRosettaDenomToSuggest, sdkmath.NewInt(4_000_000)))

evmTracers = []string{"json", "markdown", "struct", "access_list"}

blockExecutors = []string{BlockExecutorSequential, BlockExecutorBlockSTM}
evmTracers = []string{"json", "markdown", "struct", "access_list"}
)

// Config defines the server's top level configuration. It includes the default app config
Expand All @@ -130,12 +125,6 @@
Tracer string `mapstructure:"tracer"`
// MaxTxGasWanted defines the gas wanted for each eth tx returned in ante handler in check tx mode.
MaxTxGasWanted uint64 `mapstructure:"max-tx-gas-wanted"`
// BlockExecutor set block executor type, "block-stm" for parallel execution, "sequential" for sequential execution.
BlockExecutor string `mapstructure:"block-executor"`
// BlockSTMWorkers is the number of workers for block-stm execution, `0` means using all available CPUs.
BlockSTMWorkers int `mapstructure:"block-stm-workers"`
// BlockSTMPreEstimate is the flag to enable pre-estimation for block-stm execution.
BlockSTMPreEstimate bool `mapstructure:"block-stm-pre-estimate"`
}

// JSONRPCConfig defines configuration for the EVM RPC server.
Expand Down Expand Up @@ -250,7 +239,6 @@
return &EVMConfig{
Tracer: DefaultEVMTracer,
MaxTxGasWanted: DefaultMaxTxGasWanted,
BlockExecutor: BlockExecutorSequential,
}
}

Expand All @@ -259,11 +247,6 @@
if c.Tracer != "" && !strings.StringInSlice(c.Tracer, evmTracers) {
return fmt.Errorf("invalid tracer type %s, available types: %v", c.Tracer, evmTracers)
}

if c.BlockExecutor != "" && !strings.StringInSlice(c.BlockExecutor, blockExecutors) {
return fmt.Errorf("invalid block executor type %s, available types: %v", c.BlockExecutor, blockExecutors)
}

return nil
}

Expand Down Expand Up @@ -409,11 +392,8 @@
return Config{
Config: cfg,
EVM: EVMConfig{
Tracer: v.GetString("evm.tracer"),
MaxTxGasWanted: v.GetUint64("evm.max-tx-gas-wanted"),
BlockExecutor: v.GetString("evm.block-executor"),
BlockSTMWorkers: v.GetInt("evm.block-stm-workers"),
BlockSTMPreEstimate: v.GetBool("evm.block-stm-pre-estimate"),
Tracer: v.GetString("evm.tracer"),
MaxTxGasWanted: v.GetUint64("evm.max-tx-gas-wanted"),

Check warning on line 396 in server/config/config.go

View check run for this annotation

Codecov / codecov/patch

server/config/config.go#L395-L396

Added lines #L395 - L396 were not covered by tests
},
JSONRPC: JSONRPCConfig{
Enable: v.GetBool("json-rpc.enable"),
Expand Down
7 changes: 0 additions & 7 deletions server/config/toml.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,6 @@ tracer = "{{ .EVM.Tracer }}"
# MaxTxGasWanted defines the gas wanted for each eth tx returned in ante handler in check tx mode.
max-tx-gas-wanted = {{ .EVM.MaxTxGasWanted }}

# BlockExecutor set block executor type, "block-stm" for parallel execution, "sequential" for sequential execution.
block-executor = "{{ .EVM.BlockExecutor }}"
# BlockSTMWorkers is the number of workers for block-stm execution, 0 means using all available CPUs.
block-stm-workers = {{ .EVM.BlockSTMWorkers }}
# BlockSTMPreEstimate is the flag to enable pre-estimation for block-stm execution.
block-stm-pre-estimate = {{ .EVM.BlockSTMPreEstimate }}

###############################################################################
### JSON RPC Configuration ###
###############################################################################
Expand Down
7 changes: 2 additions & 5 deletions server/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,8 @@ const (

// EVM flags
const (
EVMTracer = "evm.tracer"
EVMMaxTxGasWanted = "evm.max-tx-gas-wanted"
EVMBlockExecutor = "evm.block-executor"
EVMBlockSTMWorkers = "evm.block-stm-workers"
EVMBlockSTMPreEstimate = "evm.block-stm-pre-estimate"
EVMTracer = "evm.tracer"
EVMMaxTxGasWanted = "evm.max-tx-gas-wanted"
)

// TLS flags
Expand Down
6 changes: 3 additions & 3 deletions tests/integration_tests/configs/default.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@
'broadcast-mode': 'sync',
},
'app-config': {
evm: {
'block-executor': 'block-stm',
'block-stm-workers': 32,
'block-stm': {
executor: 'block-stm',
workers: 32,
},
},
}, {
Expand Down
Loading
Loading