Skip to content
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (evm) [#447](https://github.com/crypto-org-chain/ethermint/pull/447) Deduct fee through virtual bank transfer.
* (evm) [#448](https://github.com/crypto-org-chain/ethermint/pull/448) Refactor the evm transfer to be more efficient.
* (evm) [#450](https://github.com/crypto-org-chain/ethermint/pull/450) Refactor transient stores to be compatible with parallel tx execution.
* (evm) [#454](https://github.com/crypto-org-chain/ethermint/pull/454) Migrate transient stores to object stores.

### State Machine Breaking

Expand Down
9 changes: 4 additions & 5 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,9 +331,9 @@ func NewEthermintApp(
)

// Add the EVM transient store key
tkeys := storetypes.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey)
tkeys := storetypes.NewTransientStoreKeys(paramstypes.TStoreKey)
memKeys := storetypes.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
okeys := storetypes.NewObjectStoreKeys(banktypes.ObjectStoreKey)
okeys := storetypes.NewObjectStoreKeys(banktypes.ObjectStoreKey, evmtypes.ObjectStoreKey, feemarkettypes.ObjectStoreKey)

// load state streaming if enabled
if err := bApp.RegisterStreamingServices(appOpts, keys); err != nil {
Expand Down Expand Up @@ -495,17 +495,16 @@ func NewEthermintApp(
feeMarketSs := app.GetSubspace(feemarkettypes.ModuleName)
app.FeeMarketKeeper = feemarketkeeper.NewKeeper(
appCodec,
runtime.NewKVStoreService(keys[feemarkettypes.StoreKey]),
authtypes.NewModuleAddress(govtypes.ModuleName),
keys[feemarkettypes.StoreKey],
keys[feemarkettypes.StoreKey], okeys[feemarkettypes.ObjectStoreKey],
)

// Set authority to x/gov module account to only expect the module account to update params
evmSs := app.GetSubspace(evmtypes.ModuleName)
app.EvmKeeper = evmkeeper.NewKeeper(
appCodec,
runtime.NewKVStoreService(keys[evmtypes.StoreKey]),
keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], authtypes.NewModuleAddress(govtypes.ModuleName),
keys[evmtypes.StoreKey], okeys[evmtypes.ObjectStoreKey], authtypes.NewModuleAddress(govtypes.ModuleName),
app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.FeeMarketKeeper,
tracer,
nil,
Expand Down
4 changes: 4 additions & 0 deletions x/evm/keeper/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ import (
// BeginBlock sets the sdk Context and EIP155 chain id to the Keeper.
func (k *Keeper) BeginBlock(ctx sdk.Context) error {
k.WithChainID(ctx)

// cache params object
_ = k.GetParams(ctx)

Check warning

Code scanning / CodeQL

Panic in BeginBock or EndBlock consensus methods

path flow from Begin/EndBlock to a panic call

return nil
}

Expand Down
10 changes: 5 additions & 5 deletions x/evm/keeper/bloom.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ import (
"github.com/evmos/ethermint/x/evm/types"
)

func (k Keeper) SetTxBloom(ctx sdk.Context, bloom []byte) {
store := ctx.KVStore(k.transientKey)
store.Set(types.TransientBloomKey(ctx.TxIndex(), ctx.MsgIndex()), bloom)
func (k Keeper) SetTxBloom(ctx sdk.Context, bloom *big.Int) {
store := ctx.ObjectStore(k.objectKey)
store.Set(types.ObjectBloomKey(ctx.TxIndex(), ctx.MsgIndex()), bloom)
}

func (k Keeper) CollectTxBloom(ctx sdk.Context) {
store := prefix.NewStore(ctx.KVStore(k.transientKey), types.KeyPrefixTransientBloom)
store := prefix.NewObjStore(ctx.ObjectStore(k.objectKey), types.KeyPrefixObjectBloom)
it := store.Iterator(nil, nil)
defer it.Close()

bloom := new(big.Int)
for ; it.Valid(); it.Next() {
bloom.Or(bloom, big.NewInt(0).SetBytes(it.Value()))
bloom.Or(bloom, it.Value().(*big.Int))
}

k.EmitBlockBloomEvent(ctx, bloom.Bytes())
Expand Down
19 changes: 9 additions & 10 deletions x/evm/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ type Keeper struct {
storeKey storetypes.StoreKey

// key to access the transient store, which is reset on every block during Commit
transientKey storetypes.StoreKey
objectKey storetypes.StoreKey

// the address capable of executing a MsgUpdateParams message. Typically, this should be the x/gov module account.
authority sdk.AccAddress
Expand Down Expand Up @@ -79,7 +79,7 @@ type Keeper struct {
func NewKeeper(
cdc codec.Codec,
storeService corestoretypes.KVStoreService,
storeKey, transientKey storetypes.StoreKey,
storeKey, objectKey storetypes.StoreKey,
authority sdk.AccAddress,
ak types.AccountKeeper,
bankKeeper types.BankKeeper,
Expand Down Expand Up @@ -108,7 +108,7 @@ func NewKeeper(
stakingKeeper: sk,
feeMarketKeeper: fmk,
storeKey: storeKey,
transientKey: transientKey,
objectKey: objectKey,
tracer: tracer,
customContractFns: customContractFns,
}
Expand Down Expand Up @@ -287,19 +287,18 @@ func (k Keeper) getBaseFee(ctx sdk.Context, london bool) *big.Int {

// GetTransientGasUsed returns the gas used by current cosmos tx.
func (k Keeper) GetTransientGasUsed(ctx sdk.Context) uint64 {
store := ctx.TransientStore(k.transientKey)
bz := store.Get(types.TransientGasUsedKey(ctx.TxIndex()))
if len(bz) == 0 {
store := ctx.ObjectStore(k.objectKey)
v := store.Get(types.ObjectGasUsedKey(ctx.TxIndex()))
if v == nil {
return 0
}
return sdk.BigEndianToUint64(bz)
return v.(uint64)
}

// SetTransientGasUsed sets the gas used by current cosmos tx.
func (k Keeper) SetTransientGasUsed(ctx sdk.Context, gasUsed uint64) {
store := ctx.TransientStore(k.transientKey)
bz := sdk.Uint64ToBigEndian(gasUsed)
store.Set(types.TransientGasUsedKey(ctx.TxIndex()), bz)
store := ctx.ObjectStore(k.objectKey)
store.Set(types.ObjectGasUsedKey(ctx.TxIndex()), gasUsed)
}

// AddTransientGasUsed accumulate gas used by each eth msgs included in current cosmos tx.
Expand Down
41 changes: 30 additions & 11 deletions x/evm/keeper/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,27 @@ import (
)

// GetParams returns the total set of evm parameters.
func (k Keeper) GetParams(ctx sdk.Context) (p types.Params) {
store := k.storeService.OpenKVStore(ctx)
bz, err := store.Get(types.KeyPrefixParams)
if err != nil {
panic(err)
}
if bz == nil {
return p
func (k Keeper) GetParams(ctx sdk.Context) types.Params {
var params *types.Params
objStore := ctx.ObjectStore(k.objectKey)
v := objStore.Get(types.KeyPrefixObjectParams)
if v == nil {
store := k.storeService.OpenKVStore(ctx)
bz, err := store.Get(types.KeyPrefixParams)
if err != nil {
panic(err)

Check warning

Code scanning / CodeQL

Panic in BeginBock or EndBlock consensus methods

Possible panics in BeginBock- or EndBlock-related consensus methods could cause a chain halt
}
params = new(types.Params)
if bz != nil {
k.cdc.MustUnmarshal(bz, params)
}

objStore.Set(types.KeyPrefixObjectParams, params)
} else {
params = v.(*types.Params)
}
k.cdc.MustUnmarshal(bz, &p)
return p

return *params
}

// SetParams sets the EVM params each in their individual key for better get performance
Expand All @@ -41,5 +51,14 @@ func (k Keeper) SetParams(ctx sdk.Context, p types.Params) error {
}
store := k.storeService.OpenKVStore(ctx)
bz := k.cdc.MustMarshal(&p)
return store.Set(types.KeyPrefixParams, bz)
if err := store.Set(types.KeyPrefixParams, bz); err != nil {
return err
}

// set to cache as well, decode again to be compatible with the previous behavior
var params types.Params
k.cdc.MustUnmarshal(bz, &params)
ctx.ObjectStore(k.objectKey).Set(types.KeyPrefixObjectParams, &params)

return nil
}
2 changes: 1 addition & 1 deletion x/evm/keeper/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ func (k *Keeper) ApplyTransaction(ctx sdk.Context, msgEth *types.MsgEthereumTx)

// Compute block bloom filter
if len(logs) > 0 {
k.SetTxBloom(tmpCtx, ethtypes.LogsBloom(logs))
k.SetTxBloom(tmpCtx, new(big.Int).SetBytes(ethtypes.LogsBloom(logs)))
}

var contractAddr common.Address
Expand Down
22 changes: 9 additions & 13 deletions x/evm/statedb/statedb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ func (suite *StateDBTestSuite) TestIterateStorage() {
func (suite *StateDBTestSuite) TestNativeAction() {
_, ctx, keeper := setupTestEnv(suite.T())
storeKey := testStoreKeys["testnative"]
transientKey := testTransientKeys[evmtypes.TransientKey]
objStoreKey := testObjKeys[evmtypes.ObjectStoreKey]
memKey := testMemKeys[capabilitytypes.MemStoreKey]

eventConverter := func(event sdk.Event) (*ethtypes.Log, error) {
Expand All @@ -619,8 +619,8 @@ func (suite *StateDBTestSuite) TestNativeAction() {
store.Set([]byte("success1"), []byte("value"))
ctx.EventManager().EmitEvent(sdk.NewEvent("success1"))

transient := ctx.KVStore(transientKey)
transient.Set([]byte("transient"), []byte("value"))
objStore := ctx.ObjectStore(objStoreKey)
objStore.Set([]byte("transient"), "value")

mem := ctx.KVStore(memKey)
mem.Set([]byte("mem"), []byte("value"))
Expand All @@ -632,8 +632,8 @@ func (suite *StateDBTestSuite) TestNativeAction() {
store.Set([]byte("failure1"), []byte("value"))
ctx.EventManager().EmitEvent(sdk.NewEvent("failure1"))

transient := ctx.KVStore(transientKey)
suite.Require().Equal([]byte("value"), transient.Get([]byte("transient")))
objStore := ctx.ObjectStore(objStoreKey)
suite.Require().Equal("value", objStore.Get([]byte("transient")).(string))

mem := ctx.KVStore(memKey)
suite.Require().Equal([]byte("value"), mem.Get([]byte("mem")))
Expand Down Expand Up @@ -771,10 +771,9 @@ func CollectContractStorage(db vm.StateDB, address common.Address) statedb.Stora
}

var (
testStoreKeys = storetypes.NewKVStoreKeys(authtypes.StoreKey, banktypes.StoreKey, evmtypes.StoreKey, "testnative")
testObjKeys = storetypes.NewObjectStoreKeys(banktypes.ObjectStoreKey)
testTransientKeys = storetypes.NewTransientStoreKeys(evmtypes.TransientKey)
testMemKeys = storetypes.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
testStoreKeys = storetypes.NewKVStoreKeys(authtypes.StoreKey, banktypes.StoreKey, evmtypes.StoreKey, "testnative")
testObjKeys = storetypes.NewObjectStoreKeys(banktypes.ObjectStoreKey, evmtypes.ObjectStoreKey)
testMemKeys = storetypes.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
)

func cloneRawState(t *testing.T, cms storetypes.MultiStore) map[string]map[string][]byte {
Expand Down Expand Up @@ -822,7 +821,7 @@ func newTestKeeper(t *testing.T, cms storetypes.MultiStore) (sdk.Context, *evmke
evmKeeper := evmkeeper.NewKeeper(
appCodec,
runtime.NewKVStoreService(testStoreKeys[evmtypes.StoreKey]),
testStoreKeys[evmtypes.StoreKey], testTransientKeys[evmtypes.TransientKey], authtypes.NewModuleAddress(govtypes.ModuleName),
testStoreKeys[evmtypes.StoreKey], testObjKeys[evmtypes.ObjectStoreKey], authtypes.NewModuleAddress(govtypes.ModuleName),
accountKeeper, bankKeeper, nil, nil,
"",
nil,
Expand All @@ -838,9 +837,6 @@ func setupTestEnv(t *testing.T) (storetypes.MultiStore, sdk.Context, *evmkeeper.
for _, key := range testStoreKeys {
cms.MountStoreWithDB(key, storetypes.StoreTypeIAVL, nil)
}
for _, key := range testTransientKeys {
cms.MountStoreWithDB(key, storetypes.StoreTypeTransient, nil)
}
for _, key := range testMemKeys {
cms.MountStoreWithDB(key, storetypes.StoreTypeMemory, nil)
}
Expand Down
28 changes: 15 additions & 13 deletions x/evm/types/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ const (
// The EVM module should use a prefix store.
StoreKey = ModuleName

// TransientKey is the key to access the EVM transient store, that is reset
// ObjectStoreKey is the key to access the EVM object store, that is reset
// during the Commit phase.
TransientKey = "transient_" + ModuleName
ObjectStoreKey = "object:" + ModuleName

// RouterKey uses module name for routing
RouterKey = ModuleName
Expand All @@ -45,10 +45,11 @@ const (
prefixParams
)

// prefix bytes for the EVM transient store
// prefix bytes for the EVM object store
const (
prefixTransientBloom = iota + 1
prefixTransientGasUsed
prefixObjectBloom = iota + 1
prefixObjectGasUsed
prefixObjectParams
)

// KVStore key prefixes
Expand All @@ -58,10 +59,11 @@ var (
KeyPrefixParams = []byte{prefixParams}
)

// Transient Store key prefixes
// Object Store key prefixes
var (
KeyPrefixTransientBloom = []byte{prefixTransientBloom}
KeyPrefixTransientGasUsed = []byte{prefixTransientGasUsed}
KeyPrefixObjectBloom = []byte{prefixObjectBloom}
KeyPrefixObjectGasUsed = []byte{prefixObjectGasUsed}
KeyPrefixObjectParams = []byte{prefixObjectParams}
)

// AddressStoragePrefix returns a prefix to iterate over a given account storage.
Expand All @@ -74,16 +76,16 @@ func StateKey(address common.Address, key []byte) []byte {
return append(AddressStoragePrefix(address), key...)
}

func TransientGasUsedKey(txIndex int) []byte {
var key [9]byte
key[0] = prefixTransientGasUsed
func ObjectGasUsedKey(txIndex int) []byte {
var key [1 + 8]byte
key[0] = prefixObjectGasUsed
binary.BigEndian.PutUint64(key[1:], uint64(txIndex))
return key[:]
}

func TransientBloomKey(txIndex, msgIndex int) []byte {
func ObjectBloomKey(txIndex, msgIndex int) []byte {
var key [1 + 8 + 8]byte
key[0] = prefixTransientBloom
key[0] = prefixObjectBloom
binary.BigEndian.PutUint64(key[1:], uint64(txIndex))
binary.BigEndian.PutUint64(key[9:], uint64(msgIndex))
return key[:]
Expand Down
17 changes: 7 additions & 10 deletions x/feemarket/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package keeper
import (
"math/big"

corestoretypes "cosmossdk.io/core/store"
"cosmossdk.io/log"
storetypes "cosmossdk.io/store/types"
"github.com/cosmos/cosmos-sdk/codec"
Expand All @@ -33,31 +32,29 @@ var KeyPrefixBaseFeeV1 = []byte{2}
// Keeper grants access to the Fee Market module state.
type Keeper struct {
// Protobuf codec
cdc codec.BinaryCodec
storeService corestoretypes.KVStoreService
cdc codec.BinaryCodec
// Store key required for the Fee Market Prefix KVStore.
storeKey storetypes.StoreKey
storeKey, objectKey storetypes.StoreKey
// the address capable of executing a MsgUpdateParams message. Typically, this should be the x/gov module account.
authority sdk.AccAddress
}

// NewKeeper generates new fee market module keeper
func NewKeeper(
cdc codec.BinaryCodec,
storeService corestoretypes.KVStoreService,
authority sdk.AccAddress,
storeKey storetypes.StoreKey,
storeKey, objectKey storetypes.StoreKey,
) Keeper {
// ensure authority account is correctly formatted
if err := sdk.VerifyAddressFormat(authority); err != nil {
panic(err)
}

return Keeper{
cdc: cdc,
storeService: storeService,
storeKey: storeKey,
authority: authority,
cdc: cdc,
storeKey: storeKey,
objectKey: objectKey,
authority: authority,
}
}

Expand Down
Loading