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:
Austin Abell 2019-09-27 10:08:45 -04:00 committed by GitHub
parent f7ad8f53f0
commit 09a71a2a3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 161 additions and 83 deletions

View File

@ -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])
}

View File

@ -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 {

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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))

View File

@ -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)

View File

@ -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

View File

@ -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}
}

View File

@ -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)
}

View File

@ -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")

View File

@ -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 {

View File

@ -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
}

View File

@ -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
)