evm: replace block hash storage (#80)

* evm: replace block hash storage

* c++
This commit is contained in:
Federico Kunze 2021-06-07 07:00:14 -04:00 committed by GitHub
parent e639cb4a82
commit 1ff3c46663
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 36 additions and 50 deletions

View File

@ -40,6 +40,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### State Machine Breaking
* (evm) [tharsis#72](https://github.com/tharsis/ethermint/issues/72) Update `AccessList` to use `TransientStore` instead of map.
* (evm) [tharsis#68](https://github.com/tharsis/ethermint/issues/68) Replace block hash storage map to use staking `HistoricalInfo`.
### API Breaking

View File

@ -311,7 +311,8 @@ func NewEthermintApp(
// Create Ethermint keepers
app.EvmKeeper = evmkeeper.NewKeeper(
appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], app.GetSubspace(evmtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], app.GetSubspace(evmtypes.ModuleName),
app.AccountKeeper, app.BankKeeper, app.StakingKeeper,
)
// Create IBC Keeper

View File

@ -27,6 +27,8 @@ import (
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
paramkeeper "github.com/cosmos/cosmos-sdk/x/params/keeper"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/cosmos/ethermint/encoding/codec"
"github.com/cosmos/ethermint/types"
@ -183,13 +185,14 @@ func TestImportBlocks(t *testing.T) {
authStoreKey := sdk.NewKVStoreKey(authtypes.StoreKey)
bankStoreKey := sdk.NewKVStoreKey(banktypes.StoreKey)
stakingStoreKey := sdk.NewKVStoreKey(stakingtypes.StoreKey)
evmStoreKey := sdk.NewKVStoreKey(evmtypes.StoreKey)
paramsStoreKey := sdk.NewKVStoreKey(paramtypes.StoreKey)
evmTransientStoreKey := sdk.NewTransientStoreKey(evmtypes.TransientKey)
paramsTransientStoreKey := sdk.NewTransientStoreKey(paramtypes.TStoreKey)
// mount stores
keys := []*sdk.KVStoreKey{authStoreKey, bankStoreKey, evmStoreKey, paramsStoreKey}
keys := []*sdk.KVStoreKey{authStoreKey, bankStoreKey, stakingStoreKey, evmStoreKey, paramsStoreKey}
tkeys := []*sdk.TransientStoreKey{paramsTransientStoreKey, evmTransientStoreKey}
for _, key := range keys {
cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, nil)
@ -204,12 +207,14 @@ func TestImportBlocks(t *testing.T) {
// Set specific subspaces
authSubspace := paramsKeeper.Subspace(authtypes.ModuleName)
bankSubspace := paramsKeeper.Subspace(banktypes.ModuleName)
stakingSubspace := paramsKeeper.Subspace(stakingtypes.ModuleName)
evmSubspace := paramsKeeper.Subspace(evmtypes.ModuleName).WithKeyTable(evmtypes.ParamKeyTable())
// create keepers
ak := authkeeper.NewAccountKeeper(cdc, authStoreKey, authSubspace, types.ProtoAccount, nil)
bk := bankkeeper.NewBaseKeeper(cdc, bankStoreKey, ak, bankSubspace, nil)
evmKeeper := evmkeeper.NewKeeper(cdc, evmStoreKey, evmTransientStoreKey, evmSubspace, ak, bk)
sk := stakingkeeper.NewKeeper(cdc, stakingStoreKey, ak, bk, stakingSubspace)
evmKeeper := evmkeeper.NewKeeper(cdc, evmStoreKey, evmTransientStoreKey, evmSubspace, ak, bk, sk)
cms.SetPruning(sdkstore.PruneNothing)

View File

@ -20,20 +20,7 @@ import (
func (k *Keeper) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyBeginBlocker)
k.WithContext(ctx)
if req.Header.Height < 1 {
return
}
// Gas costs are handled within msg handler so costs should be ignored
ctx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
k.headerHash = common.BytesToHash(req.Hash)
// set height -> hash
// TODO: prune
k.SetHeaderHash(ctx, req.Header.Height, k.headerHash)
}
// EndBlock updates the accounts and commits state objects to the KV Store, while

View File

@ -35,6 +35,7 @@ type Keeper struct {
paramSpace paramtypes.Subspace
accountKeeper types.AccountKeeper
bankKeeper types.BankKeeper
stakingKeeper types.StakingKeeper
ctx sdk.Context
// chain ID number obtained from the context's chain id
@ -52,7 +53,7 @@ type Keeper struct {
// NewKeeper generates new evm module keeper
func NewKeeper(
cdc codec.BinaryMarshaler, storeKey, transientKey sdk.StoreKey, paramSpace paramtypes.Subspace,
ak types.AccountKeeper, bankKeeper types.BankKeeper,
ak types.AccountKeeper, bankKeeper types.BankKeeper, sk types.StakingKeeper,
) *Keeper {
// set KeyTable if it has not already been set
if !paramSpace.HasKeyTable() {
@ -65,6 +66,7 @@ func NewKeeper(
paramSpace: paramSpace,
accountKeeper: ak,
bankKeeper: bankKeeper,
stakingKeeper: sk,
storeKey: storeKey,
transientKey: transientKey,
CommitStateDB: types.NewCommitStateDB(sdk.Context{}, storeKey, transientKey, paramSpace, ak, bankKeeper),
@ -146,26 +148,6 @@ func (k Keeper) SetBlockBloomTransient(bloom *big.Int) {
// Block
// ----------------------------------------------------------------------------
// GetHeaderHash gets the header hash from a given height
func (k Keeper) GetHeaderHash(ctx sdk.Context, height int64) common.Hash {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixHeightToHeaderHash)
key := sdk.Uint64ToBigEndian(uint64(height))
bz := store.Get(key)
if len(bz) == 0 {
return common.Hash{}
}
return common.BytesToHash(bz)
}
// SetBlockHash sets the mapping from heigh -> header hash
func (k Keeper) SetHeaderHash(ctx sdk.Context, height int64, hash common.Hash) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixHeightToHeaderHash)
key := sdk.Uint64ToBigEndian(uint64(height))
store.Set(key, hash.Bytes())
}
// SetTxReceiptToHash sets the mapping from tx hash to tx receipt
func (k Keeper) SetTxReceiptToHash(ctx sdk.Context, hash common.Hash, receipt *types.TxReceipt) {
ctx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
@ -176,16 +158,6 @@ func (k Keeper) SetTxReceiptToHash(ctx sdk.Context, hash common.Hash, receipt *t
store.Set(types.KeyHashTxReceipt(hash), data)
}
// GetHeightHash returns the block header hash associated with a given block height and chain epoch number.
func (k Keeper) GetHeightHash(ctx sdk.Context, height uint64) common.Hash {
return k.CommitStateDB.WithContext(ctx).GetHeightHash(height)
}
// SetHeightHash sets the block header hash associated with a given height.
func (k Keeper) SetHeightHash(ctx sdk.Context, height uint64, hash common.Hash) {
k.CommitStateDB.WithContext(ctx).SetHeightHash(height, hash)
}
// ----------------------------------------------------------------------------
// Tx
// ----------------------------------------------------------------------------

View File

@ -7,6 +7,8 @@ import (
"os"
"time"
tmtypes "github.com/tendermint/tendermint/types"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
@ -58,18 +60,30 @@ func (k Keeper) VMConfig() vm.Config {
// 3. The requested height is from a height greater than the latest one
func (k Keeper) GetHashFn() vm.GetHashFunc {
return func(height uint64) common.Hash {
h := int64(height)
switch {
case k.ctx.BlockHeight() == int64(height):
case k.ctx.BlockHeight() == h:
// Case 1: The requested height matches the one from the context so we can retrieve the header
// hash directly from the context.
// TODO: deprecate field from the keeper on next SDK release
return k.headerHash
case k.ctx.BlockHeight() > int64(height):
case k.ctx.BlockHeight() > h:
// Case 2: if the chain is not the current height we need to retrieve the hash from the store for the
// current chain epoch. This only applies if the current height is greater than the requested height.
return k.GetHeightHash(k.ctx, height)
histInfo, found := k.stakingKeeper.GetHistoricalInfo(k.ctx, h)
if !found {
k.Logger(k.ctx).Debug("historical info not found", "height", h)
return common.Hash{}
}
header, err := tmtypes.HeaderFromProto(&histInfo.Header)
if err != nil {
k.Logger(k.ctx).Error("failed to cast tendermint header from proto", "error", err)
return common.Hash{}
}
return common.BytesToHash(header.Hash())
default:
// Case 3: heights greater than the current one returns an empty hash.
return common.Hash{}

View File

@ -3,6 +3,7 @@ package types
import (
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)
// AccountKeeper defines the expected account keeper interface
@ -24,3 +25,8 @@ type BankKeeper interface {
SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) error
SetBalance(ctx sdk.Context, addr sdk.AccAddress, balance sdk.Coin) error
}
// StakingKeeper returns the historical headers kept in store.
type StakingKeeper interface {
GetHistoricalInfo(ctx sdk.Context, height int64) (stakingtypes.HistoricalInfo, bool)
}