Skip to content

Commit

Permalink
use memstore instead of block wise transient store
Browse files Browse the repository at this point in the history
  • Loading branch information
beer-1 committed Nov 19, 2024
1 parent eef6099 commit 5afc565
Show file tree
Hide file tree
Showing 17 changed files with 250 additions and 147 deletions.
1 change: 0 additions & 1 deletion app/ibc-hooks/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,6 @@ func _createTestInput(
ac,
appCodec,
runtime.NewKVStoreService(keys[evmtypes.StoreKey]),
runtime.NewTransientStoreService(tkeys[evmtypes.TStoreKey]),
accountKeeper,
bankKeeper,
communityPoolKeeper,
Expand Down
3 changes: 1 addition & 2 deletions app/ibc-hooks/receive_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
nfttransfertypes "github.com/initia-labs/initia/x/ibc/nft-transfer/types"
evm_hooks "github.com/initia-labs/minievm/app/ibc-hooks"
"github.com/initia-labs/minievm/x/evm/contracts/counter"
"github.com/initia-labs/minievm/x/evm/types"
evmtypes "github.com/initia-labs/minievm/x/evm/types"
)

Expand Down Expand Up @@ -111,7 +110,7 @@ func Test_onReceiveIcs20Packet_memo(t *testing.T) {
require.Equal(t, uint256.NewInt(1).Bytes32(), [32]byte(queryRes))

// check allowance
erc20Addr, err := types.DenomToContractAddr(ctx, input.EVMKeeper, localDenom)
erc20Addr, err := evmtypes.DenomToContractAddr(ctx, input.EVMKeeper, localDenom)
require.NoError(t, err)
queryInputBz, err = input.EVMKeeper.ERC20Keeper().GetERC20ABI().Pack("allowance", common.BytesToAddress(intermediateSender.Bytes()), contractAddr)
require.NoError(t, err)
Expand Down
1 change: 0 additions & 1 deletion app/keepers/keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,6 @@ func NewAppKeeper(
ac,
appCodec,
runtime.NewKVStoreService(appKeepers.keys[evmtypes.StoreKey]),
runtime.NewTransientStoreService(appKeepers.tkeys[evmtypes.TStoreKey]),
accountKeeper,
bankKeeper,
communityPoolKeeper,
Expand Down
2 changes: 1 addition & 1 deletion app/keepers/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (appKeepers *AppKeepers) GenerateKeys() {
)

// Define transient store keys
appKeepers.tkeys = storetypes.NewTransientStoreKeys(evmtypes.TStoreKey, forwardingtypes.TransientStoreKey)
appKeepers.tkeys = storetypes.NewTransientStoreKeys(forwardingtypes.TransientStoreKey)

// MemKeys are for information that is stored only in RAM.
appKeepers.memKeys = storetypes.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
Expand Down
1 change: 0 additions & 1 deletion x/bank/keeper/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,6 @@ func _createTestInput(
ac,
appCodec,
runtime.NewKVStoreService(keys[evmtypes.StoreKey]),
runtime.NewTransientStoreService(tkeys[evmtypes.TStoreKey]),
accountKeeper,
bankKeeper,
communityPoolKeeper,
Expand Down
1 change: 0 additions & 1 deletion x/evm/keeper/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,6 @@ func _createTestInput(
ac,
appCodec,
runtime.NewKVStoreService(keys[evmtypes.StoreKey]),
runtime.NewTransientStoreService(tkeys[evmtypes.TStoreKey]),
accountKeeper,
bankKeeper,
communityPoolKeeper,
Expand Down
7 changes: 2 additions & 5 deletions x/evm/keeper/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,8 @@ import (
func (k Keeper) NewStateDB(ctx context.Context, evm callableEVM, fee types.Fee) (*evmstate.StateDB, error) {
return evmstate.NewStateDB(
// delegate gas meter to the EVM
sdk.UnwrapSDKContext(ctx).WithGasMeter(storetypes.NewInfiniteGasMeter()), k.Logger(ctx),
k.accountKeeper, k.VMStore, k.TransientVMStore, k.TransientCreated,
k.TransientSelfDestruct, k.TransientLogs, k.TransientLogSize,
k.TransientAccessList, k.TransientRefund, k.execIndex,
evm, k.ERC20Keeper().GetERC20ABI(), fee.Contract(),
sdk.UnwrapSDKContext(ctx).WithGasMeter(storetypes.NewInfiniteGasMeter()), k.cdc, k.Logger(ctx),
k.accountKeeper, k.VMStore, evm, k.ERC20Keeper().GetERC20ABI(), fee.Contract(),
)
}

Expand Down
31 changes: 0 additions & 31 deletions x/evm/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,6 @@ type Keeper struct {
Params collections.Item[types.Params]
VMStore collections.Map[[]byte, []byte]

// execIndex is unique index for each execution, which is used
// unique key for transient stores.
execIndex *atomic.Uint64

// transient store
TSchema collections.Schema
TransientVMStore collections.Map[collections.Pair[uint64, []byte], []byte]
TransientLogs collections.Map[collections.Pair[uint64, uint64], types.Log]
TransientLogSize collections.Map[uint64, uint64]
TransientRefund collections.Map[uint64, uint64]
TransientCreated collections.KeySet[collections.Pair[uint64, []byte]]
TransientSelfDestruct collections.KeySet[collections.Pair[uint64, []byte]]
TransientAccessList collections.KeySet[collections.Pair[uint64, []byte]]

// erc20 stores of users
ERC20FactoryAddr collections.Item[[]byte]
ERC20WrapperAddr collections.Item[[]byte]
Expand All @@ -87,7 +73,6 @@ func NewKeeper(
ac address.Codec,
cdc codec.Codec,
storeService corestoretypes.KVStoreService,
transientService corestoretypes.TransientStoreService,
accountKeeper types.AccountKeeper,
bankKeeper types.BankKeeper,
communityPoolKeeper types.CommunityPoolKeeper,
Expand All @@ -100,7 +85,6 @@ func NewKeeper(
queryCosmosWhitelist types.QueryCosmosWhitelist,
) *Keeper {
sb := collections.NewSchemaBuilder(storeService)
tsb := collections.NewSchemaBuilderFromAccessor(transientService.OpenTransientStore)

if evmConfig.ContractSimulationGasLimit == 0 {
evmConfig.ContractSimulationGasLimit = evmconfig.DefaultContractSimulationGasLimit
Expand Down Expand Up @@ -133,16 +117,6 @@ func NewKeeper(
Params: collections.NewItem(sb, types.ParamsKey, "params", codec.CollValue[types.Params](cdc)),
VMStore: collections.NewMap(sb, types.VMStorePrefix, "vm_store", collections.BytesKey, collections.BytesValue),

execIndex: execIndex,

TransientVMStore: collections.NewMap(tsb, types.TransientVMStorePrefix, "transient_vm_store", collections.PairKeyCodec(collections.Uint64Key, collections.BytesKey), collections.BytesValue),
TransientCreated: collections.NewKeySet(tsb, types.TransientCreatedPrefix, "transient_created", collections.PairKeyCodec(collections.Uint64Key, collections.BytesKey)),
TransientSelfDestruct: collections.NewKeySet(tsb, types.TransientSelfDestructPrefix, "transient_self_destruct", collections.PairKeyCodec(collections.Uint64Key, collections.BytesKey)),
TransientLogs: collections.NewMap(tsb, types.TransientLogsPrefix, "transient_logs", collections.PairKeyCodec(collections.Uint64Key, collections.Uint64Key), codec.CollValue[types.Log](cdc)),
TransientLogSize: collections.NewMap(tsb, types.TransientLogSizePrefix, "transient_log_size", collections.Uint64Key, collections.Uint64Value),
TransientAccessList: collections.NewKeySet(tsb, types.TransientAccessListPrefix, "transient_access_list", collections.PairKeyCodec(collections.Uint64Key, collections.BytesKey)),
TransientRefund: collections.NewMap(tsb, types.TransientRefundPrefix, "transient_refund", collections.Uint64Key, collections.Uint64Value),

ERC20WrapperAddr: collections.NewItem(sb, types.ERC20WrapperAddrKey, "erc20_wrapper_addr", collections.BytesValue),
ERC20FactoryAddr: collections.NewItem(sb, types.ERC20FactoryAddrKey, "erc20_factory_addr", collections.BytesValue),
ERC20s: collections.NewKeySet(sb, types.ERC20sPrefix, "erc20s", collections.BytesKey),
Expand All @@ -166,13 +140,8 @@ func NewKeeper(
if err != nil {
panic(err)
}
tSchema, err := tsb.Build()
if err != nil {
panic(err)
}

k.Schema = schema
k.TSchema = tSchema
k.erc20StoresKeeper = NewERC20StoresKeeper(k)
k.erc20Keeper, err = NewERC20Keeper(k)
if err != nil {
Expand Down
16 changes: 11 additions & 5 deletions x/evm/precompiles/cosmos/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@ import (
var _ evmtypes.StateDB = &MockStateDB{}

type MockStateDB struct {
ctx sdk.Context
initialCtx sdk.Context
ctx state.Context
initialCtx state.Context

// Snapshot stack
snaps []*state.Snapshot
}

func NewMockStateDB(ctx sdk.Context) *MockStateDB {
func NewMockStateDB(sdkCtx sdk.Context) *MockStateDB {
ctx := state.NewContext(sdkCtx)
return &MockStateDB{
ctx: ctx,
initialCtx: ctx,
Expand Down Expand Up @@ -73,10 +74,15 @@ func (m *MockStateDB) RevertToSnapshot(i int) {
// ContextOfSnapshot implements types.StateDB.
func (m *MockStateDB) ContextOfSnapshot(i int) sdk.Context {
if i == -1 {
return m.initialCtx
return m.initialCtx.Context
}

return m.snaps[i].Context()
return m.snaps[i].Context().Context
}

// Context implements types.StateDB.
func (m *MockStateDB) Context() sdk.Context {
return m.ctx.Context
}

//////////////////////// MOCKED METHODS ////////////////////////
Expand Down
16 changes: 11 additions & 5 deletions x/evm/precompiles/erc20_registry/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@ import (
var _ evmtypes.StateDB = &MockStateDB{}

type MockStateDB struct {
ctx sdk.Context
initialCtx sdk.Context
ctx state.Context
initialCtx state.Context

// Snapshot stack
snaps []*state.Snapshot
}

func NewMockStateDB(ctx sdk.Context) *MockStateDB {
func NewMockStateDB(sdkCtx sdk.Context) *MockStateDB {
ctx := state.NewContext(sdkCtx)
return &MockStateDB{
ctx: ctx,
initialCtx: ctx,
Expand Down Expand Up @@ -67,10 +68,15 @@ func (m *MockStateDB) RevertToSnapshot(i int) {
// ContextOfSnapshot implements types.StateDB.
func (m *MockStateDB) ContextOfSnapshot(i int) sdk.Context {
if i == -1 {
return m.initialCtx
return m.initialCtx.Context
}

return m.snaps[i].Context()
return m.snaps[i].Context().Context
}

// Context implements types.StateDB.
func (m *MockStateDB) Context() sdk.Context {
return m.ctx.Context
}

//////////////////////// MOCKED METHODS ////////////////////////
Expand Down
1 change: 0 additions & 1 deletion x/evm/state/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,6 @@ func _createTestInput(
ac,
appCodec,
runtime.NewKVStoreService(keys[evmtypes.StoreKey]),
runtime.NewTransientStoreService(tkeys[evmtypes.TStoreKey]),
accountKeeper,
bankKeeper,
communityPoolKeeper,
Expand Down
45 changes: 45 additions & 0 deletions x/evm/state/context.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package state

import (
storetypes "cosmossdk.io/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)

type Context struct {
sdk.Context

memStore storetypes.MultiStore
memStoreKey storetypes.StoreKey
}

func NewContext(ctx sdk.Context) Context {
memStore, memStoreKey := newMemStore()
return Context{
Context: ctx,
memStore: memStore,
memStoreKey: memStoreKey,
}
}

func (c Context) WithSDKContext(sdkCtx sdk.Context) Context {
c.Context = sdkCtx
return c
}

func (c Context) WithMemStore(memStore storetypes.MultiStore) Context {
c.memStore = memStore
return c
}

func (c Context) CacheContext() (cc Context, writeCache func()) {
cacheCtx, commit := c.Context.CacheContext()
cacheMemStore := c.memStore.CacheMultiStore()

cc = c.WithSDKContext(cacheCtx).WithMemStore(cacheMemStore)
writeCache = func() {
commit()
cacheMemStore.Write()
}

return cc, writeCache
}
11 changes: 11 additions & 0 deletions x/evm/state/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,14 @@ func uint64ToBytes(v uint64) []byte {
func bytesToUint64(bz []byte) uint64 {
return binary.BigEndian.Uint64(bz)
}

// Keys for transient store
var (
memStoreVMStorePrefix = []byte{0x01} // prefix for transient vm store
memStoreCreatedPrefix = []byte{0x02} // prefix for transient created accounts
memStoreSelfDestructPrefix = []byte{0x03} // prefix for transient self destruct accounts
memStoreLogsPrefix = []byte{0x04} // prefix for transient logs
memStoreLogSizePrefix = []byte{0x05} // prefix for transient log size
memStoreAccessListPrefix = []byte{0x06} // prefix for transient access list
memStoreRefundPrefix = []byte{0x07} // prefix for transient refund
)
80 changes: 80 additions & 0 deletions x/evm/state/memdb.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package state

import (
"fmt"

corestoretypes "cosmossdk.io/core/store"
"cosmossdk.io/log"
"cosmossdk.io/store"
storemetrics "cosmossdk.io/store/metrics"
storetypes "cosmossdk.io/store/types"
dbm "github.com/cosmos/cosmos-db"
)

const (
storeKey = "stateDB"
)

func newMemStore() (storetypes.MultiStore, storetypes.StoreKey) {
memStoreKey := storetypes.NewMemoryStoreKey(storeKey)
memStore := store.NewCommitMultiStore(dbm.NewMemDB(), log.NewNopLogger(), storemetrics.NewNoOpMetrics())
memStore.MountStoreWithDB(memStoreKey, storetypes.StoreTypeMemory, nil)
if err := memStore.LoadLatestVersion(); err != nil {
panic(fmt.Sprintf("failed to initialize memory store: %v", err))
}

return memStore, memStoreKey
}

// CoreKVStore is a wrapper of Core/Store kvstore interface
// Remove after https://github.com/cosmos/cosmos-sdk/issues/14714 is closed
type coreKVStore struct {
kvStore storetypes.KVStore
}

// NewKVStore returns a wrapper of Core/Store kvstore interface
// Remove once store migrates to core/store kvstore interface
func newKVStore(store storetypes.KVStore) corestoretypes.KVStore {
return coreKVStore{kvStore: store}
}

// Get returns nil iff key doesn't exist. Errors on nil key.
func (store coreKVStore) Get(key []byte) ([]byte, error) {
return store.kvStore.Get(key), nil
}

// Has checks if a key exists. Errors on nil key.
func (store coreKVStore) Has(key []byte) (bool, error) {
return store.kvStore.Has(key), nil
}

// Set sets the key. Errors on nil key or value.
func (store coreKVStore) Set(key, value []byte) error {
store.kvStore.Set(key, value)
return nil
}

// Delete deletes the key. Errors on nil key.
func (store coreKVStore) Delete(key []byte) error {
store.kvStore.Delete(key)
return nil
}

// Iterator iterates over a domain of keys in ascending order. End is exclusive.
// Start must be less than end, or the Iterator is invalid.
// Iterator must be closed by caller.
// To iterate over entire domain, use store.Iterator(nil, nil)
// CONTRACT: No writes may happen within a domain while an iterator exists over it.
// Exceptionally allowed for cachekv.Store, safe to write in the modules.
func (store coreKVStore) Iterator(start, end []byte) (store.Iterator, error) {
return store.kvStore.Iterator(start, end), nil
}

// ReverseIterator iterates over a domain of keys in descending order. End is exclusive.
// Start must be less than end, or the Iterator is invalid.
// Iterator must be closed by caller.
// CONTRACT: No writes may happen within a domain while an iterator exists over it.
// Exceptionally allowed for cachekv.Store, safe to write in the modules.
func (store coreKVStore) ReverseIterator(start, end []byte) (store.Iterator, error) {
return store.kvStore.ReverseIterator(start, end), nil
}
15 changes: 4 additions & 11 deletions x/evm/state/snapshot.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
package state

import (
"context"

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

type Snapshot struct {
ctx sdk.Context
ctx Context
commit func()
}

func NewSnapshot(ctx context.Context) *Snapshot {
sdkCtx := sdk.UnwrapSDKContext(ctx)
cacheCtx, commit := sdkCtx.CacheContext()
func NewSnapshot(ctx Context) *Snapshot {
cacheCtx, commit := ctx.CacheContext()
return &Snapshot{
ctx: cacheCtx,
commit: commit,
Expand All @@ -25,6 +18,6 @@ func (s *Snapshot) Commit() {
}

// for mock testing
func (s *Snapshot) Context() sdk.Context {
func (s *Snapshot) Context() Context {
return s.ctx
}
Loading

0 comments on commit 5afc565

Please sign in to comment.