eth_getBlockByHash and block hash mapping functionality (#114)
* Set up block hash to height mapping storage and fixed linting issues * fix typos * Set up module query for block height * fix bug with block mappings and implemented get block by hash * Fix other consensus hash references
This commit is contained in:
parent
f7ad8f53f0
commit
09a71a2a3a
@ -37,13 +37,13 @@ import (
|
||||
const appName = "Ethermint"
|
||||
|
||||
var (
|
||||
// default home directories for the application CLI
|
||||
// DefaultCLIHome sets the default home directories for the application CLI
|
||||
DefaultCLIHome = os.ExpandEnv("$HOME/.emintcli")
|
||||
|
||||
// DefaultNodeHome sets the folder where the applcation data and configuration will be stored
|
||||
DefaultNodeHome = os.ExpandEnv("$HOME/.emintd")
|
||||
|
||||
// The module BasicManager is in charge of setting up basic,
|
||||
// ModuleBasics is the module BasicManager is in charge of setting up basic,
|
||||
// non-dependant module elements, such as codec registration
|
||||
// and genesis verification.
|
||||
ModuleBasics = module.NewBasicManager(
|
||||
@ -131,7 +131,7 @@ func NewEthermintApp(
|
||||
|
||||
keys := sdk.NewKVStoreKeys(bam.MainStoreKey, auth.StoreKey, staking.StoreKey,
|
||||
supply.StoreKey, mint.StoreKey, distr.StoreKey, slashing.StoreKey,
|
||||
gov.StoreKey, params.StoreKey, evmtypes.EvmStoreKey, evmtypes.EvmCodeKey)
|
||||
gov.StoreKey, params.StoreKey, evmtypes.EvmStoreKey, evmtypes.EvmCodeKey, evmtypes.EvmBlockKey)
|
||||
tkeys := sdk.NewTransientStoreKeys(staking.TStoreKey, params.TStoreKey)
|
||||
|
||||
app := &EthermintApp{
|
||||
@ -165,7 +165,7 @@ func NewEthermintApp(
|
||||
app.slashingKeeper = slashing.NewKeeper(app.cdc, keys[slashing.StoreKey], &stakingKeeper,
|
||||
slashingSubspace, slashing.DefaultCodespace)
|
||||
app.crisisKeeper = crisis.NewKeeper(crisisSubspace, invCheckPeriod, app.supplyKeeper, auth.FeeCollectorName)
|
||||
app.evmKeeper = evm.NewKeeper(app.accountKeeper, keys[evmtypes.EvmStoreKey], keys[evmtypes.EvmCodeKey], cdc)
|
||||
app.evmKeeper = evm.NewKeeper(app.accountKeeper, keys[evmtypes.EvmStoreKey], keys[evmtypes.EvmCodeKey], keys[evmtypes.EvmBlockKey], cdc)
|
||||
|
||||
// register the proposal types
|
||||
govRouter := gov.NewRouter()
|
||||
@ -199,9 +199,9 @@ func NewEthermintApp(
|
||||
// During begin block slashing happens after distr.BeginBlocker so that
|
||||
// there is nothing left over in the validator fee pool, so as to keep the
|
||||
// CanWithdrawInvariant invariant.
|
||||
app.mm.SetOrderBeginBlockers(mint.ModuleName, distr.ModuleName, slashing.ModuleName)
|
||||
app.mm.SetOrderBeginBlockers(mint.ModuleName, distr.ModuleName, slashing.ModuleName, evmtypes.ModuleName)
|
||||
|
||||
app.mm.SetOrderEndBlockers(crisis.ModuleName, gov.ModuleName, staking.ModuleName)
|
||||
app.mm.SetOrderEndBlockers(crisis.ModuleName, gov.ModuleName, staking.ModuleName, evmtypes.ModuleName)
|
||||
|
||||
// NOTE: The genutils module must occur after staking so that pools are
|
||||
// properly initialized with tokens from genesis accounts.
|
||||
@ -233,28 +233,28 @@ func NewEthermintApp(
|
||||
return app
|
||||
}
|
||||
|
||||
// The genesis state of the blockchain is represented here as a map of raw json
|
||||
// GenesisState is the state of the blockchain is represented here as a map of raw json
|
||||
// messages key'd by a identifier string.
|
||||
type GenesisState map[string]json.RawMessage
|
||||
|
||||
// application updates every begin block
|
||||
// BeginBlocker updates every begin block
|
||||
func (app *EthermintApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock {
|
||||
return app.mm.BeginBlock(ctx, req)
|
||||
}
|
||||
|
||||
// application updates every end block
|
||||
// EndBlocker updates every end block
|
||||
func (app *EthermintApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
|
||||
return app.mm.EndBlock(ctx, req)
|
||||
}
|
||||
|
||||
// application update at chain initialization
|
||||
// InitChainer updates at chain initialization
|
||||
func (app *EthermintApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
|
||||
var genesisState GenesisState
|
||||
app.cdc.MustUnmarshalJSON(req.AppStateBytes, &genesisState)
|
||||
return app.mm.InitGenesis(ctx, genesisState)
|
||||
}
|
||||
|
||||
// load a particular height
|
||||
// LoadHeight loads state at a particular height
|
||||
func (app *EthermintApp) LoadHeight(height int64) error {
|
||||
return app.LoadVersion(height, app.keys[bam.MainStoreKey])
|
||||
}
|
||||
|
@ -20,8 +20,8 @@ import (
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
tmcrypto "github.com/tendermint/tendermint/crypto"
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
)
|
||||
|
||||
type testSetup struct {
|
||||
|
@ -11,8 +11,8 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
sdkrpc "github.com/cosmos/cosmos-sdk/client/rpc"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
emintkeys "github.com/cosmos/ethermint/keys"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
emintkeys "github.com/cosmos/ethermint/keys"
|
||||
|
||||
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
|
||||
bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
|
||||
|
@ -4,9 +4,9 @@ import (
|
||||
cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
cosmosKeys "github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/hd"
|
||||
emintCrypto "github.com/cosmos/ethermint/crypto"
|
||||
cosmosKeys "github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
)
|
||||
|
||||
var cdc *codec.Codec
|
||||
|
@ -13,8 +13,8 @@ import (
|
||||
cosmosKeys "github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/hd"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/keyerror"
|
||||
"github.com/cosmos/ethermint/crypto/keys/mintkey"
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/ethermint/crypto/keys/mintkey"
|
||||
|
||||
bip39 "github.com/cosmos/go-bip39"
|
||||
|
||||
|
@ -35,8 +35,8 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
tmlog "github.com/tendermint/tendermint/libs/log"
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -326,7 +326,7 @@ func applyDAOHardFork(statedb *evmtypes.CommitStateDB) {
|
||||
// and uses the input parameters for its environment. It returns the receipt
|
||||
// for the transaction, gas used and an error if the transaction failed,
|
||||
// indicating the block was invalid.
|
||||
// Function is also pulled from go-ethereum 1.9 because of the imcompatible usage
|
||||
// Function is also pulled from go-ethereum 1.9 because of the incompatible usage
|
||||
// Ref: https://github.com/ethereum/go-ethereum/blob/52f2461774bcb8cdd310f86b4bc501df5b783852/core/state_processor.go#L88
|
||||
func applyTransaction(config *ethparams.ChainConfig, bc ethcore.ChainContext, author *ethcmn.Address, gp *ethcore.GasPool, statedb *evmtypes.CommitStateDB, header *ethtypes.Header, tx *ethtypes.Transaction, usedGas *uint64, cfg ethvm.Config) (*ethtypes.Receipt, uint64, error) {
|
||||
msg, err := tx.AsMessage(ethtypes.MakeSigner(config, header.Number))
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/cosmos/ethermint/rpc/args"
|
||||
"github.com/cosmos/ethermint/utils"
|
||||
"github.com/cosmos/ethermint/version"
|
||||
"github.com/cosmos/ethermint/x/evm"
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
@ -332,14 +333,24 @@ func (e *PublicEthAPI) EstimateGas(args CallArgs, blockNum BlockNumber) hexutil.
|
||||
}
|
||||
|
||||
// GetBlockByHash returns the block identified by hash.
|
||||
func (e *PublicEthAPI) GetBlockByHash(hash common.Hash, fullTx bool) map[string]interface{} {
|
||||
return nil
|
||||
func (e *PublicEthAPI) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error) {
|
||||
res, _, err := e.cliCtx.Query(fmt.Sprintf("custom/%s/%s/%s", types.ModuleName, evm.QueryHashToHeight, hash.Hex()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var out types.QueryResBlockNumber
|
||||
e.cliCtx.Codec.MustUnmarshalJSON(res, &out)
|
||||
return e.getEthBlockByNumber(out.Number, fullTx)
|
||||
}
|
||||
|
||||
// GetBlockByNumber returns the block identified by number.
|
||||
func (e *PublicEthAPI) GetBlockByNumber(blockNum BlockNumber, fullTx bool) (map[string]interface{}, error) {
|
||||
value := blockNum.Int64()
|
||||
return e.getEthBlockByNumber(value, fullTx)
|
||||
}
|
||||
|
||||
func (e *PublicEthAPI) getEthBlockByNumber(value int64, fullTx bool) (map[string]interface{}, error) {
|
||||
// Remove this check when 0 query is fixed ref: (https://github.com/tendermint/tendermint/issues/4014)
|
||||
var blkNumPtr *int64
|
||||
if value != 0 {
|
||||
@ -363,7 +374,7 @@ func (e *PublicEthAPI) GetBlockByNumber(blockNum BlockNumber, fullTx bool) (map[
|
||||
if fullTx {
|
||||
// Populate full transaction data
|
||||
transactions, gasUsed = convertTransactionsToRPC(e.cliCtx, block.Block.Txs,
|
||||
common.BytesToHash(header.ConsensusHash.Bytes()), uint64(header.Height))
|
||||
common.BytesToHash(header.Hash()), uint64(header.Height))
|
||||
} else {
|
||||
// TODO: Gas used not saved and cannot be calculated by hashes
|
||||
// Return slice of transaction hashes
|
||||
@ -382,7 +393,7 @@ func formatBlock(
|
||||
) map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"number": hexutil.Uint64(header.Height),
|
||||
"hash": hexutil.Bytes(header.ConsensusHash),
|
||||
"hash": hexutil.Bytes(header.Hash()),
|
||||
"parentHash": hexutil.Bytes(header.LastBlockID.Hash),
|
||||
"nonce": nil, // PoW specific
|
||||
"sha3Uncles": nil, // No uncles in Tendermint
|
||||
@ -485,7 +496,7 @@ func (e *PublicEthAPI) GetTransactionByHash(hash common.Hash) (*Transaction, err
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
blockHash := common.BytesToHash(block.BlockMeta.Header.ConsensusHash)
|
||||
blockHash := common.BytesToHash(block.BlockMeta.Header.Hash())
|
||||
|
||||
ethTx, err := bytesToEthTx(e.cliCtx, tx.Tx)
|
||||
if err != nil {
|
||||
@ -518,7 +529,7 @@ func (e *PublicEthAPI) GetTransactionByBlockNumberAndIndex(blockNum BlockNumber,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
transaction := newRPCTransaction(ethTx, common.BytesToHash(header.ConsensusHash.Bytes()), uint64(header.Height), uint64(idx))
|
||||
transaction := newRPCTransaction(ethTx, common.BytesToHash(header.Hash()), uint64(header.Height), uint64(idx))
|
||||
return transaction, nil
|
||||
}
|
||||
|
||||
@ -535,7 +546,7 @@ func (e *PublicEthAPI) GetTransactionReceipt(hash common.Hash) (map[string]inter
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
blockHash := common.BytesToHash(block.BlockMeta.Header.ConsensusHash)
|
||||
blockHash := common.BytesToHash(block.BlockMeta.Header.Hash())
|
||||
|
||||
// Convert tx bytes to eth transaction
|
||||
ethTx, err := bytesToEthTx(e.cliCtx, tx.Tx)
|
||||
|
@ -127,7 +127,7 @@ func completeAndBroadcastETHTxCLI(txBldr authtypes.TxBuilder, cliCtx context.CLI
|
||||
}
|
||||
}
|
||||
|
||||
// * This function is overriden to change the keybase reference here
|
||||
// * This function is overridden to change the keybase reference here
|
||||
passphrase, err := emintkeys.GetPassphrase(fromName)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -151,7 +151,7 @@ func completeAndBroadcastETHTxCLI(txBldr authtypes.TxBuilder, cliCtx context.CLI
|
||||
|
||||
// BuildAndSign builds a single message to be signed, and signs a transaction
|
||||
// with the built message given a name, passphrase, and a set of messages.
|
||||
// * overriden from github.com/cosmos/cosmos-sdk/x/auth/types/txbuilder.go
|
||||
// * overridden from github.com/cosmos/cosmos-sdk/x/auth/types/txbuilder.go
|
||||
// * This is just modified to change the functionality in makeSignature, through sign
|
||||
func buildAndSign(bldr authtypes.TxBuilder, name, passphrase string, msgs []sdk.Msg) ([]byte, error) {
|
||||
msg, err := bldr.BuildSignMsg(msgs)
|
||||
@ -179,7 +179,7 @@ func sign(bldr authtypes.TxBuilder, name, passphrase string, msg authtypes.StdSi
|
||||
func makeSignature(keybase crkeys.Keybase, name, passphrase string,
|
||||
msg authtypes.StdSignMsg) (sig authtypes.StdSignature, err error) {
|
||||
if keybase == nil {
|
||||
// * This is overriden to allow ethermint keys, but not used because keybase is set
|
||||
// * This is overridden to allow ethermint keys, but not used because keybase is set
|
||||
keybase, err = emintkeys.NewKeyBaseFromHomeFlag()
|
||||
if err != nil {
|
||||
return
|
||||
@ -212,7 +212,7 @@ func makeSignature(keybase crkeys.Keybase, name, passphrase string,
|
||||
|
||||
ethTx.Sign(chainID, emintKey.ToECDSA())
|
||||
|
||||
// * This is needed to be overriden to get bytes to sign (RLPSignBytes) with the chainID
|
||||
// * This is needed to be overridden to get bytes to sign (RLPSignBytes) with the chainID
|
||||
sigBytes, pubkey, err := keybase.Sign(name, passphrase, ethTx.RLPSignBytes(chainID).Bytes())
|
||||
if err != nil {
|
||||
return
|
||||
@ -321,7 +321,7 @@ func getFromFields(from string, genOnly bool) (sdk.AccAddress, string, error) {
|
||||
return addr, "", nil
|
||||
}
|
||||
|
||||
// * This is the line that needed to be overriden, change could be to pass in optional keybase?
|
||||
// * This is the line that needed to be overridden, change could be to pass in optional keybase?
|
||||
keybase, err := emintkeys.NewKeyBaseFromHomeFlag()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
|
@ -2,11 +2,12 @@ package evm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/ethermint/types"
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
type (
|
||||
@ -25,6 +26,7 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
// ValidateGenesis validates evm genesis config
|
||||
func ValidateGenesis(data GenesisState) error {
|
||||
for _, acct := range data.Accounts {
|
||||
if len(acct.Address.Bytes()) == 0 {
|
||||
@ -37,12 +39,14 @@ func ValidateGenesis(data GenesisState) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DefaultGenesisState sets default evm genesis config
|
||||
func DefaultGenesisState() GenesisState {
|
||||
return GenesisState{
|
||||
Accounts: []GenesisAccount{},
|
||||
}
|
||||
}
|
||||
|
||||
// InitGenesis initializes genesis state based on exported genesis
|
||||
func InitGenesis(ctx sdk.Context, keeper Keeper, data GenesisState) []abci.ValidatorUpdate {
|
||||
for _, record := range data.Accounts {
|
||||
keeper.SetCode(ctx, record.Address, record.Code)
|
||||
@ -51,7 +55,7 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data GenesisState) []abci.Valid
|
||||
return []abci.ValidatorUpdate{}
|
||||
}
|
||||
|
||||
// TODO: Implement
|
||||
// ExportGenesis exports genesis state
|
||||
func ExportGenesis(ctx sdk.Context, k Keeper) GenesisState {
|
||||
return GenesisState{Accounts: nil}
|
||||
}
|
||||
|
123
x/evm/keeper.go
123
x/evm/keeper.go
@ -1,6 +1,9 @@
|
||||
package evm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
ethvm "github.com/ethereum/go-ethereum/core/vm"
|
||||
@ -17,17 +20,45 @@ import (
|
||||
// Keeper wraps the CommitStateDB, allowing us to pass in SDK context while adhering
|
||||
// to the StateDB interface
|
||||
type Keeper struct {
|
||||
csdb *types.CommitStateDB
|
||||
cdc *codec.Codec
|
||||
csdb *types.CommitStateDB
|
||||
cdc *codec.Codec
|
||||
blockKey sdk.StoreKey
|
||||
}
|
||||
|
||||
func NewKeeper(ak auth.AccountKeeper, storageKey, codeKey sdk.StoreKey, cdc *codec.Codec) Keeper {
|
||||
// NewKeeper generates new evm module keeper
|
||||
func NewKeeper(ak auth.AccountKeeper, storageKey, codeKey sdk.StoreKey,
|
||||
blockKey sdk.StoreKey, cdc *codec.Codec) Keeper {
|
||||
return Keeper{
|
||||
csdb: types.NewCommitStateDB(sdk.Context{}, ak, storageKey, codeKey),
|
||||
cdc: cdc,
|
||||
csdb: types.NewCommitStateDB(sdk.Context{}, ak, storageKey, codeKey),
|
||||
cdc: cdc,
|
||||
blockKey: blockKey,
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Block hash mapping functions
|
||||
// May be removed when using only as module (only required by rpc api)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// SetBlockHashMapping sets the mapping from block consensus hash to block height
|
||||
func (k *Keeper) SetBlockHashMapping(ctx sdk.Context, hash []byte, height int64) {
|
||||
store := ctx.KVStore(k.blockKey)
|
||||
if !bytes.Equal(hash, []byte{}) {
|
||||
store.Set(hash, k.cdc.MustMarshalBinaryLengthPrefixed(height))
|
||||
}
|
||||
}
|
||||
|
||||
// GetBlockHashMapping gets block height from block consensus hash
|
||||
func (k *Keeper) GetBlockHashMapping(ctx sdk.Context, hash []byte) (height int64) {
|
||||
store := ctx.KVStore(k.blockKey)
|
||||
bz := store.Get(hash)
|
||||
if bytes.Equal(bz, []byte{}) {
|
||||
panic(fmt.Errorf("block with hash %s not found", ethcmn.Bytes2Hex(hash)))
|
||||
}
|
||||
k.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &height)
|
||||
return
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Genesis
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -47,52 +78,52 @@ func (k *Keeper) CreateGenesisAccount(ctx sdk.Context, account GenesisAccount) {
|
||||
// Setters
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Calls CommitStateDB.SetBalance using the passed in context
|
||||
// SetBalance calls CommitStateDB.SetBalance using the passed in context
|
||||
func (k *Keeper) SetBalance(ctx sdk.Context, addr ethcmn.Address, amount *big.Int) {
|
||||
k.csdb.WithContext(ctx).SetBalance(addr, amount)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.AddBalance using the passed in context
|
||||
// AddBalance calls CommitStateDB.AddBalance using the passed in context
|
||||
func (k *Keeper) AddBalance(ctx sdk.Context, addr ethcmn.Address, amount *big.Int) {
|
||||
k.csdb.WithContext(ctx).AddBalance(addr, amount)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.SubBalance using the passed in context
|
||||
// SubBalance calls CommitStateDB.SubBalance using the passed in context
|
||||
func (k *Keeper) SubBalance(ctx sdk.Context, addr ethcmn.Address, amount *big.Int) {
|
||||
k.csdb.WithContext(ctx).SubBalance(addr, amount)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.SetNonce using the passed in context
|
||||
// SetNonce calls CommitStateDB.SetNonce using the passed in context
|
||||
func (k *Keeper) SetNonce(ctx sdk.Context, addr ethcmn.Address, nonce uint64) {
|
||||
k.csdb.WithContext(ctx).SetNonce(addr, nonce)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.SetState using the passed in context
|
||||
// SetState calls CommitStateDB.SetState using the passed in context
|
||||
func (k *Keeper) SetState(ctx sdk.Context, addr ethcmn.Address, key, value ethcmn.Hash) {
|
||||
k.csdb.WithContext(ctx).SetState(addr, key, value)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.SetCode using the passed in context
|
||||
// SetCode calls CommitStateDB.SetCode using the passed in context
|
||||
func (k *Keeper) SetCode(ctx sdk.Context, addr ethcmn.Address, code []byte) {
|
||||
k.csdb.WithContext(ctx).SetCode(addr, code)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.AddLog using the passed in context
|
||||
// AddLog calls CommitStateDB.AddLog using the passed in context
|
||||
func (k *Keeper) AddLog(ctx sdk.Context, log *ethtypes.Log) {
|
||||
k.csdb.WithContext(ctx).AddLog(log)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.AddPreimage using the passed in context
|
||||
// AddPreimage calls CommitStateDB.AddPreimage using the passed in context
|
||||
func (k *Keeper) AddPreimage(ctx sdk.Context, hash ethcmn.Hash, preimage []byte) {
|
||||
k.csdb.WithContext(ctx).AddPreimage(hash, preimage)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.AddRefund using the passed in context
|
||||
// AddRefund calls CommitStateDB.AddRefund using the passed in context
|
||||
func (k *Keeper) AddRefund(ctx sdk.Context, gas uint64) {
|
||||
k.csdb.WithContext(ctx).AddRefund(gas)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.SubRefund using the passed in context
|
||||
// SubRefund calls CommitStateDB.SubRefund using the passed in context
|
||||
func (k *Keeper) SubRefund(ctx sdk.Context, gas uint64) {
|
||||
k.csdb.WithContext(ctx).SubRefund(gas)
|
||||
}
|
||||
@ -101,77 +132,77 @@ func (k *Keeper) SubRefund(ctx sdk.Context, gas uint64) {
|
||||
// Getters
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Calls CommitStateDB.GetBalance using the passed in context
|
||||
// GetBalance calls CommitStateDB.GetBalance using the passed in context
|
||||
func (k *Keeper) GetBalance(ctx sdk.Context, addr ethcmn.Address) *big.Int {
|
||||
return k.csdb.WithContext(ctx).GetBalance(addr)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.GetNonce using the passed in context
|
||||
// GetNonce calls CommitStateDB.GetNonce using the passed in context
|
||||
func (k *Keeper) GetNonce(ctx sdk.Context, addr ethcmn.Address) uint64 {
|
||||
return k.csdb.WithContext(ctx).GetNonce(addr)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.TxIndex using the passed in context
|
||||
// TxIndex calls CommitStateDB.TxIndex using the passed in context
|
||||
func (k *Keeper) TxIndex(ctx sdk.Context) int {
|
||||
return k.csdb.WithContext(ctx).TxIndex()
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.BlockHash using the passed in context
|
||||
// BlockHash calls CommitStateDB.BlockHash using the passed in context
|
||||
func (k *Keeper) BlockHash(ctx sdk.Context) ethcmn.Hash {
|
||||
return k.csdb.WithContext(ctx).BlockHash()
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.GetCode using the passed in context
|
||||
// GetCode calls CommitStateDB.GetCode using the passed in context
|
||||
func (k *Keeper) GetCode(ctx sdk.Context, addr ethcmn.Address) []byte {
|
||||
return k.csdb.WithContext(ctx).GetCode(addr)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.GetCodeSize using the passed in context
|
||||
// GetCodeSize calls CommitStateDB.GetCodeSize using the passed in context
|
||||
func (k *Keeper) GetCodeSize(ctx sdk.Context, addr ethcmn.Address) int {
|
||||
return k.csdb.WithContext(ctx).GetCodeSize(addr)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.GetCodeHash using the passed in context
|
||||
// GetCodeHash calls CommitStateDB.GetCodeHash using the passed in context
|
||||
func (k *Keeper) GetCodeHash(ctx sdk.Context, addr ethcmn.Address) ethcmn.Hash {
|
||||
return k.csdb.WithContext(ctx).GetCodeHash(addr)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.GetState using the passed in context
|
||||
// GetState calls CommitStateDB.GetState using the passed in context
|
||||
func (k *Keeper) GetState(ctx sdk.Context, addr ethcmn.Address, hash ethcmn.Hash) ethcmn.Hash {
|
||||
return k.csdb.WithContext(ctx).GetState(addr, hash)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.GetCommittedState using the passed in context
|
||||
// GetCommittedState calls CommitStateDB.GetCommittedState using the passed in context
|
||||
func (k *Keeper) GetCommittedState(ctx sdk.Context, addr ethcmn.Address, hash ethcmn.Hash) ethcmn.Hash {
|
||||
return k.csdb.WithContext(ctx).GetCommittedState(addr, hash)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.GetLogs using the passed in context
|
||||
// GetLogs calls CommitStateDB.GetLogs using the passed in context
|
||||
func (k *Keeper) GetLogs(ctx sdk.Context, hash ethcmn.Hash) []*ethtypes.Log {
|
||||
return k.csdb.WithContext(ctx).GetLogs(hash)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.Logs using the passed in context
|
||||
// Logs calls CommitStateDB.Logs using the passed in context
|
||||
func (k *Keeper) Logs(ctx sdk.Context) []*ethtypes.Log {
|
||||
return k.csdb.WithContext(ctx).Logs()
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.GetRefund using the passed in context
|
||||
// GetRefund calls CommitStateDB.GetRefund using the passed in context
|
||||
func (k *Keeper) GetRefund(ctx sdk.Context) uint64 {
|
||||
return k.csdb.WithContext(ctx).GetRefund()
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.Preimages using the passed in context
|
||||
// Preimages calls CommitStateDB.Preimages using the passed in context
|
||||
func (k *Keeper) Preimages(ctx sdk.Context) map[ethcmn.Hash][]byte {
|
||||
return k.csdb.WithContext(ctx).Preimages()
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.HasSuicided using the passed in context
|
||||
// HasSuicided calls CommitStateDB.HasSuicided using the passed in context
|
||||
func (k *Keeper) HasSuicided(ctx sdk.Context, addr ethcmn.Address) bool {
|
||||
return k.csdb.WithContext(ctx).HasSuicided(addr)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.StorageTrie using the passed in context
|
||||
// StorageTrie calls CommitStateDB.StorageTrie using the passed in context
|
||||
func (k *Keeper) StorageTrie(ctx sdk.Context, addr ethcmn.Address) ethstate.Trie {
|
||||
return k.csdb.WithContext(ctx).StorageTrie(addr)
|
||||
}
|
||||
@ -180,17 +211,17 @@ func (k *Keeper) StorageTrie(ctx sdk.Context, addr ethcmn.Address) ethstate.Trie
|
||||
// Persistence
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Calls CommitStateDB.Commit using the passed in context
|
||||
// Commit calls CommitStateDB.Commit using the passed { in context
|
||||
func (k *Keeper) Commit(ctx sdk.Context, deleteEmptyObjects bool) (root ethcmn.Hash, err error) {
|
||||
return k.csdb.WithContext(ctx).Commit(deleteEmptyObjects)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.Finalise using the passed in context
|
||||
// Finalise calls CommitStateDB.Finalise using the passed in context
|
||||
func (k *Keeper) Finalise(ctx sdk.Context, deleteEmptyObjects bool) {
|
||||
k.csdb.WithContext(ctx).Finalise(deleteEmptyObjects)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.IntermediateRoot using the passed in context
|
||||
// IntermediateRoot calls CommitStateDB.IntermediateRoot using the passed in context
|
||||
func (k *Keeper) IntermediateRoot(ctx sdk.Context, deleteEmptyObjects bool) {
|
||||
k.csdb.WithContext(ctx).IntermediateRoot(deleteEmptyObjects)
|
||||
}
|
||||
@ -199,12 +230,12 @@ func (k *Keeper) IntermediateRoot(ctx sdk.Context, deleteEmptyObjects bool) {
|
||||
// Snapshotting
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Calls CommitStateDB.Snapshot using the passed in context
|
||||
// Snapshot calls CommitStateDB.Snapshot using the passed in context
|
||||
func (k *Keeper) Snapshot(ctx sdk.Context) int {
|
||||
return k.csdb.WithContext(ctx).Snapshot()
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.RevertToSnapshot using the passed in context
|
||||
// RevertToSnapshot calls CommitStateDB.RevertToSnapshot using the passed in context
|
||||
func (k *Keeper) RevertToSnapshot(ctx sdk.Context, revID int) {
|
||||
k.csdb.WithContext(ctx).RevertToSnapshot(revID)
|
||||
}
|
||||
@ -213,57 +244,57 @@ func (k *Keeper) RevertToSnapshot(ctx sdk.Context, revID int) {
|
||||
// Auxiliary
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Calls CommitStateDB.Database using the passed in context
|
||||
// Database calls CommitStateDB.Database using the passed in context
|
||||
func (k *Keeper) Database(ctx sdk.Context) ethstate.Database {
|
||||
return k.csdb.WithContext(ctx).Database()
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.Empty using the passed in context
|
||||
// Empty calls CommitStateDB.Empty using the passed in context
|
||||
func (k *Keeper) Empty(ctx sdk.Context, addr ethcmn.Address) bool {
|
||||
return k.csdb.WithContext(ctx).Empty(addr)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.Exist using the passed in context
|
||||
// Exist calls CommitStateDB.Exist using the passed in context
|
||||
func (k *Keeper) Exist(ctx sdk.Context, addr ethcmn.Address) bool {
|
||||
return k.csdb.WithContext(ctx).Exist(addr)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.Error using the passed in context
|
||||
// Error calls CommitStateDB.Error using the passed in context
|
||||
func (k *Keeper) Error(ctx sdk.Context) error {
|
||||
return k.csdb.WithContext(ctx).Error()
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.Suicide using the passed in context
|
||||
// Suicide calls CommitStateDB.Suicide using the passed in context
|
||||
func (k *Keeper) Suicide(ctx sdk.Context, addr ethcmn.Address) bool {
|
||||
return k.csdb.WithContext(ctx).Suicide(addr)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.Reset using the passed in context
|
||||
// Reset calls CommitStateDB.Reset using the passed in context
|
||||
func (k *Keeper) Reset(ctx sdk.Context, root ethcmn.Hash) error {
|
||||
return k.csdb.WithContext(ctx).Reset(root)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.Prepare using the passed in context
|
||||
// Prepare calls CommitStateDB.Prepare using the passed in context
|
||||
func (k *Keeper) Prepare(ctx sdk.Context, thash, bhash ethcmn.Hash, txi int) {
|
||||
k.csdb.WithContext(ctx).Prepare(thash, bhash, txi)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.CreateAccount using the passed in context
|
||||
// CreateAccount calls CommitStateDB.CreateAccount using the passed in context
|
||||
func (k *Keeper) CreateAccount(ctx sdk.Context, addr ethcmn.Address) {
|
||||
k.csdb.WithContext(ctx).CreateAccount(addr)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.Copy using the passed in context
|
||||
// Copy calls CommitStateDB.Copy using the passed in context
|
||||
func (k *Keeper) Copy(ctx sdk.Context) ethvm.StateDB {
|
||||
return k.csdb.WithContext(ctx).Copy()
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.ForEachStorage using passed in context
|
||||
// ForEachStorage calls CommitStateDB.ForEachStorage using passed in context
|
||||
func (k *Keeper) ForEachStorage(ctx sdk.Context, addr ethcmn.Address, cb func(key, value ethcmn.Hash) bool) error {
|
||||
return k.csdb.WithContext(ctx).ForEachStorage(addr, cb)
|
||||
}
|
||||
|
||||
// Calls CommitStateDB.GetOrNetStateObject using the passed in context
|
||||
// GetOrNewStateObject calls CommitStateDB.GetOrNetStateObject using the passed in context
|
||||
func (k *Keeper) GetOrNewStateObject(ctx sdk.Context, addr ethcmn.Address) types.StateObject {
|
||||
return k.csdb.WithContext(ctx).GetOrNewStateObject(addr)
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ var (
|
||||
accKey = sdk.NewKVStoreKey("acc")
|
||||
storageKey = sdk.NewKVStoreKey(evmtypes.EvmStoreKey)
|
||||
codeKey = sdk.NewKVStoreKey(evmtypes.EvmCodeKey)
|
||||
blockKey = sdk.NewKVStoreKey(evmtypes.EvmBlockKey)
|
||||
|
||||
logger = tmlog.NewNopLogger()
|
||||
)
|
||||
@ -54,12 +55,12 @@ func TestDBStorage(t *testing.T) {
|
||||
// Set specific supspaces
|
||||
authSubspace := paramsKeeper.Subspace(auth.DefaultParamspace)
|
||||
ak := auth.NewAccountKeeper(cdc, accKey, authSubspace, types.ProtoBaseAccount)
|
||||
ek := NewKeeper(ak, storageKey, codeKey, cdc)
|
||||
ek := NewKeeper(ak, storageKey, codeKey, blockKey, cdc)
|
||||
|
||||
db := dbm.NewMemDB()
|
||||
cms := store.NewCommitMultiStore(db)
|
||||
// mount stores
|
||||
keys := []*sdk.KVStoreKey{accKey, storageKey, codeKey}
|
||||
keys := []*sdk.KVStoreKey{accKey, storageKey, codeKey, blockKey}
|
||||
for _, key := range keys {
|
||||
cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, nil)
|
||||
}
|
||||
@ -79,12 +80,19 @@ func TestDBStorage(t *testing.T) {
|
||||
ek.SetState(ctx, address, ethcmn.HexToHash("0x2"), ethcmn.HexToHash("0x3"))
|
||||
ek.SetCode(ctx, address, []byte{0x1})
|
||||
|
||||
// Test block hash mapping functionality
|
||||
ek.SetBlockHashMapping(ctx, ethcmn.FromHex("0x0d87a3a5f73140f46aac1bf419263e4e94e87c292f25007700ab7f2060e2af68"), 7)
|
||||
ek.SetBlockHashMapping(ctx, []byte{0x43, 0x32}, 8)
|
||||
|
||||
// Get those state transitions
|
||||
require.Equal(t, ek.GetBalance(ctx, address).Cmp(big.NewInt(5)), 0)
|
||||
require.Equal(t, ek.GetNonce(ctx, address), uint64(4))
|
||||
require.Equal(t, ek.GetState(ctx, address, ethcmn.HexToHash("0x2")), ethcmn.HexToHash("0x3"))
|
||||
require.Equal(t, ek.GetCode(ctx, address), []byte{0x1})
|
||||
|
||||
require.Equal(t, ek.GetBlockHashMapping(ctx, ethcmn.FromHex("0x0d87a3a5f73140f46aac1bf419263e4e94e87c292f25007700ab7f2060e2af68")), int64(7))
|
||||
require.Equal(t, ek.GetBlockHashMapping(ctx, []byte{0x43, 0x32}), int64(8))
|
||||
|
||||
// commit stateDB
|
||||
_, err = ek.Commit(ctx, false)
|
||||
require.NoError(t, err, "failed to commit StateDB")
|
||||
|
@ -104,7 +104,10 @@ func (am AppModule) NewQuerierHandler() sdk.Querier {
|
||||
}
|
||||
|
||||
// BeginBlock function for module at start of each block
|
||||
func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}
|
||||
func (am AppModule) BeginBlock(ctx sdk.Context, bl abci.RequestBeginBlock) {
|
||||
// Consider removing this when using evm as module without web3 API
|
||||
am.keeper.SetBlockHashMapping(ctx, bl.Header.LastBlockId.GetHash(), bl.Header.GetHeight()-1)
|
||||
}
|
||||
|
||||
// EndBlock function for module at end of block
|
||||
func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
|
||||
|
@ -19,6 +19,7 @@ const (
|
||||
QueryStorage = "storage"
|
||||
QueryCode = "code"
|
||||
QueryNonce = "nonce"
|
||||
QueryHashToHeight = "hashToHeight"
|
||||
)
|
||||
|
||||
// NewQuerier is the module level router for state queries
|
||||
@ -37,6 +38,8 @@ func NewQuerier(keeper Keeper) sdk.Querier {
|
||||
return queryCode(ctx, path, keeper)
|
||||
case QueryNonce:
|
||||
return queryNonce(ctx, path, keeper)
|
||||
case QueryHashToHeight:
|
||||
return queryHashToHeight(ctx, path, keeper)
|
||||
default:
|
||||
return nil, sdk.ErrUnknownRequest("unknown query endpoint")
|
||||
}
|
||||
@ -113,3 +116,16 @@ func queryNonce(ctx sdk.Context, path []string, keeper Keeper) ([]byte, sdk.Erro
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func queryHashToHeight(ctx sdk.Context, path []string, keeper Keeper) ([]byte, sdk.Error) {
|
||||
blockHash := ethcmn.FromHex(path[1])
|
||||
blockNumber := keeper.GetBlockHashMapping(ctx, blockHash)
|
||||
|
||||
bRes := types.QueryResBlockNumber{Number: blockNumber}
|
||||
res, err := codec.MarshalJSONIndent(keeper.cdc, bRes)
|
||||
if err != nil {
|
||||
panic("could not marshal result to JSON: " + err.Error())
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
@ -1,11 +1,16 @@
|
||||
package types
|
||||
|
||||
const (
|
||||
// module name
|
||||
// ModuleName string name of module
|
||||
ModuleName = "ethermint"
|
||||
|
||||
// EvmStoreKey key for ethereum storage data
|
||||
EvmStoreKey = "evmstore"
|
||||
EvmCodeKey = "evmcode"
|
||||
// EvmCodeKey key for ethereum code data
|
||||
EvmCodeKey = "evmcode"
|
||||
// EvmBlockKey key for ethereum block data
|
||||
EvmBlockKey = "evmblock"
|
||||
|
||||
// RouterKey uses module name for routing
|
||||
RouterKey = ModuleName
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user