Skip to content

Commit a0312c7

Browse files
author
HuangYi
committed
Problem: transient store usage not compatible with parallel tx execution
Currently we use shared transient store keys to accumulate some states, which cause issues when developing parallel tx execution Solution: - remove some transient stores. - the others are used in a per-tx fasion. Update CHANGELOG.md Signed-off-by: yihuang <huang@crypto.com> cleanup fix test
1 parent 078d3b0 commit a0312c7

File tree

19 files changed

+172
-103
lines changed

19 files changed

+172
-103
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
4949
* (statedb) [#446](https://github.com/crypto-org-chain/ethermint/pull/446) Re-use the cache store implementation with sdk.
5050
* (evm) [#447](https://github.com/crypto-org-chain/ethermint/pull/447) Deduct fee through virtual bank transfer.
5151
* (evm) [#448](https://github.com/crypto-org-chain/ethermint/pull/448) Refactor the evm transfer to be more efficient.
52+
* (evm) [#450](https://github.com/crypto-org-chain/ethermint/pull/450) Refactor transient stores to be compatible with parallel tx execution.
5253

5354
### State Machine Breaking
5455

app/ante/handler_options.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func newEthAnteHandler(options HandlerOptions) sdk.AnteHandler {
8787
}
8888

8989
// We need to setup an empty gas config so that the gas is consistent with Ethereum.
90-
ctx, err = SetupEthContext(ctx, options.EvmKeeper)
90+
ctx, err = SetupEthContext(ctx)
9191
if err != nil {
9292
return ctx, err
9393
}

app/ante/interfaces.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ type EVMKeeper interface {
3232
ChainID() *big.Int
3333

3434
DeductTxCostsFromUserBalance(ctx sdk.Context, fees sdk.Coins, from common.Address) error
35-
ResetTransientGasUsed(ctx sdk.Context)
36-
GetTxIndexTransient(ctx sdk.Context) uint64
3735
}
3836

3937
type protoTxProvider interface {

app/ante/setup.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,12 @@ import (
3030

3131
// SetupEthContext is adapted from SetUpContextDecorator from cosmos-sdk, it ignores gas consumption
3232
// by setting the gas meter to infinite
33-
func SetupEthContext(ctx sdk.Context, evmKeeper EVMKeeper) (newCtx sdk.Context, err error) {
33+
func SetupEthContext(ctx sdk.Context) (newCtx sdk.Context, err error) {
3434
// We need to setup an empty gas config so that the gas is consistent with Ethereum.
3535
newCtx = ctx.WithGasMeter(storetypes.NewInfiniteGasMeter()).
3636
WithKVGasConfig(storetypes.GasConfig{}).
3737
WithTransientKVGasConfig(storetypes.GasConfig{})
3838

39-
// Reset transient gas used to prepare the execution of current cosmos tx.
40-
// Transient gas-used is necessary to sum the gas-used of cosmos tx, when it contains multiple eth msgs.
41-
evmKeeper.ResetTransientGasUsed(ctx)
42-
4339
return newCtx, nil
4440
}
4541

app/ante/setup_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func (suite *AnteTestSuite) TestEthSetupContextDecorator() {
2828

2929
for _, tc := range testCases {
3030
suite.Run(tc.name, func() {
31-
ctx, err := ante.SetupEthContext(suite.ctx, suite.app.EvmKeeper)
31+
ctx, err := ante.SetupEthContext(suite.ctx)
3232

3333
if tc.expPass {
3434
suite.Require().NoError(err)

app/app.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ func NewEthermintApp(
314314
bApp.SetVersion(version.Version)
315315
bApp.SetInterfaceRegistry(interfaceRegistry)
316316
bApp.SetTxEncoder(txConfig.TxEncoder())
317+
bApp.SetTxExecutor(DefaultTxExecutor)
317318

318319
keys := storetypes.NewKVStoreKeys(
319320
// SDK keys

app/executor.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package app
2+
3+
import (
4+
"context"
5+
6+
storetypes "cosmossdk.io/store/types"
7+
abci "github.com/cometbft/cometbft/abci/types"
8+
evmtypes "github.com/evmos/ethermint/x/evm/types"
9+
)
10+
11+
func DefaultTxExecutor(_ context.Context,
12+
blockSize int,
13+
ms storetypes.MultiStore,
14+
deliverTxWithMultiStore func(int, storetypes.MultiStore) *abci.ExecTxResult,
15+
) ([]*abci.ExecTxResult, error) {
16+
results := make([]*abci.ExecTxResult, blockSize)
17+
for i := 0; i < blockSize; i++ {
18+
results[i] = deliverTxWithMultiStore(i, ms)
19+
}
20+
return evmtypes.PatchTxResponses(results), nil
21+
}

tests/importer/importer_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,10 @@ func (suite *ImporterTestSuite) TestImportBlocks() {
144144
applyDAOHardFork(vmdb)
145145
}
146146

147-
for _, tx := range block.Transactions() {
147+
for i, tx := range block.Transactions() {
148148

149149
receipt, gas, err := applyTransaction(
150-
ctx, chainConfig, chainContext, nil, gp, suite.app.EvmKeeper, vmdb, header, tx, usedGas, vmConfig,
150+
ctx, chainConfig, chainContext, nil, gp, suite.app.EvmKeeper, vmdb, header, tx, usedGas, vmConfig, uint(i)
151151
)
152152
suite.Require().NoError(err, "failed to apply tx at block %d; tx: %X; gas %d; receipt:%v", block.NumberU64(), tx.Hash(), gas, receipt)
153153
suite.Require().NotNil(receipt)
@@ -230,7 +230,7 @@ func applyDAOHardFork(vmdb ethvm.StateDB) {
230230
func applyTransaction(
231231
ctx sdk.Context, config *ethparams.ChainConfig, bc ethcore.ChainContext, author *common.Address,
232232
gp *ethcore.GasPool, evmKeeper *evmkeeper.Keeper, vmdb *statedb.StateDB, header *ethtypes.Header,
233-
tx *ethtypes.Transaction, usedGas *uint64, cfg ethvm.Config,
233+
tx *ethtypes.Transaction, usedGas *uint64, cfg ethvm.Config, index uint,
234234
) (*ethtypes.Receipt, uint64, error) {
235235
msg, err := ethcore.TransactionToMessage(tx, ethtypes.MakeSigner(config, header.Number), sdkmath.ZeroInt().BigInt())
236236
if err != nil {
@@ -271,7 +271,7 @@ func applyTransaction(
271271
receipt.Bloom = ethtypes.CreateBloom(ethtypes.Receipts{receipt})
272272
receipt.BlockHash = header.Hash()
273273
receipt.BlockNumber = header.Number
274-
receipt.TransactionIndex = uint(evmKeeper.GetTxIndexTransient(ctx))
274+
receipt.TransactionIndex = index
275275

276276
return receipt, execResult.UsedGas, err
277277
}

x/evm/keeper/abci.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ import (
1919
"cosmossdk.io/store/types"
2020

2121
sdk "github.com/cosmos/cosmos-sdk/types"
22-
23-
ethtypes "github.com/ethereum/go-ethereum/core/types"
2422
)
2523

2624
// BeginBlock sets the sdk Context and EIP155 chain id to the Keeper.
@@ -35,9 +33,6 @@ func (k *Keeper) BeginBlock(ctx sdk.Context) error {
3533
func (k *Keeper) EndBlock(ctx sdk.Context) error {
3634
// Gas costs are handled within msg handler so costs should be ignored
3735
infCtx := ctx.WithGasMeter(types.NewInfiniteGasMeter())
38-
39-
bloom := ethtypes.BytesToBloom(k.GetBlockBloomTransient(infCtx).Bytes())
40-
k.EmitBlockBloomEvent(infCtx, bloom)
41-
36+
k.CollectTxBloom(infCtx)
4237
return nil
4338
}

x/evm/keeper/bloom.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package keeper
2+
3+
import (
4+
"math/big"
5+
6+
"cosmossdk.io/store/prefix"
7+
sdk "github.com/cosmos/cosmos-sdk/types"
8+
"github.com/evmos/ethermint/x/evm/types"
9+
)
10+
11+
func (k Keeper) SetTxBloom(ctx sdk.Context, bloom []byte) {
12+
store := ctx.KVStore(k.transientKey)
13+
store.Set(types.TransientBloomKey(ctx.TxIndex(), ctx.MsgIndex()), bloom)
14+
}
15+
16+
func (k Keeper) CollectTxBloom(ctx sdk.Context) {
17+
store := prefix.NewStore(ctx.KVStore(k.transientKey), types.KeyPrefixTransientBloom)
18+
it := store.Iterator(nil, nil)
19+
defer it.Close()
20+
21+
bloom := new(big.Int)
22+
for ; it.Valid(); it.Next() {
23+
bloom.Or(bloom, big.NewInt(0).SetBytes(it.Value()))
24+
}
25+
26+
k.EmitBlockBloomEvent(ctx, bloom.Bytes())
27+
}

0 commit comments

Comments
 (0)