Implement initial ABCI logic
This commit is contained in:
parent
50e0602923
commit
f93135f0f8
158
app/ethermint.go
158
app/ethermint.go
@ -5,12 +5,19 @@ import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/wire"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
"github.com/cosmos/cosmos-sdk/x/slashing"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/cosmos/ethermint/handlers"
|
||||
"github.com/cosmos/ethermint/types"
|
||||
|
||||
ethparams "github.com/ethereum/go-ethereum/params"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
tmcmn "github.com/tendermint/tendermint/libs/common"
|
||||
dbm "github.com/tendermint/tendermint/libs/db"
|
||||
tmlog "github.com/tendermint/tendermint/libs/log"
|
||||
@ -27,52 +34,146 @@ type (
|
||||
EthermintApp struct {
|
||||
*bam.BaseApp
|
||||
|
||||
codec *wire.Codec
|
||||
sealed bool
|
||||
codec *wire.Codec
|
||||
|
||||
accountKey *sdk.KVStoreKey
|
||||
accountMapper auth.AccountMapper
|
||||
// TODO: keys, stores, mappers, and keepers
|
||||
accountKey *sdk.KVStoreKey
|
||||
mainKey *sdk.KVStoreKey
|
||||
stakeKey *sdk.KVStoreKey
|
||||
slashingKey *sdk.KVStoreKey
|
||||
govKey *sdk.KVStoreKey
|
||||
feeCollKey *sdk.KVStoreKey
|
||||
paramsKey *sdk.KVStoreKey
|
||||
tParamsKey *sdk.TransientStoreKey
|
||||
|
||||
accountMapper auth.AccountMapper
|
||||
feeCollKeeper auth.FeeCollectionKeeper
|
||||
coinKeeper bank.Keeper
|
||||
stakeKeeper stake.Keeper
|
||||
slashingKeeper slashing.Keeper
|
||||
govKeeper gov.Keeper
|
||||
paramsKeeper params.Keeper
|
||||
}
|
||||
|
||||
// Options is a function signature that provides the ability to modify
|
||||
// options of an EthermintApp during initialization.
|
||||
Options func(*EthermintApp)
|
||||
)
|
||||
|
||||
// NewEthermintApp returns a reference to a new initialized Ethermint
|
||||
// application.
|
||||
func NewEthermintApp(logger tmlog.Logger, db dbm.DB, ethChainCfg *ethparams.ChainConfig, opts ...Options,
|
||||
func NewEthermintApp(
|
||||
logger tmlog.Logger, db dbm.DB, ethChainCfg *ethparams.ChainConfig, baseAppOptions ...func(*bam.BaseApp),
|
||||
) *EthermintApp {
|
||||
|
||||
codec := CreateCodec()
|
||||
app := &EthermintApp{
|
||||
BaseApp: bam.NewBaseApp(appName, logger, db, types.TxDecoder(codec)),
|
||||
codec: codec,
|
||||
accountKey: sdk.NewKVStoreKey("accounts"),
|
||||
BaseApp: bam.NewBaseApp(appName, logger, db, types.TxDecoder(codec), baseAppOptions...),
|
||||
codec: codec,
|
||||
accountKey: sdk.NewKVStoreKey("acc"),
|
||||
mainKey: sdk.NewKVStoreKey("main"),
|
||||
stakeKey: sdk.NewKVStoreKey("stake"),
|
||||
slashingKey: sdk.NewKVStoreKey("slashing"),
|
||||
govKey: sdk.NewKVStoreKey("gov"),
|
||||
feeCollKey: sdk.NewKVStoreKey("fee"),
|
||||
paramsKey: sdk.NewKVStoreKey("params"),
|
||||
tParamsKey: sdk.NewTransientStoreKey("transient_params"),
|
||||
}
|
||||
|
||||
// set application keepers and mappers
|
||||
app.accountMapper = auth.NewAccountMapper(codec, app.accountKey, auth.ProtoBaseAccount)
|
||||
app.coinKeeper = bank.NewKeeper(app.accountMapper)
|
||||
app.paramsKeeper = params.NewKeeper(app.codec, app.paramsKey)
|
||||
app.feeCollKeeper = auth.NewFeeCollectionKeeper(app.codec, app.feeCollKey)
|
||||
app.stakeKeeper = stake.NewKeeper(
|
||||
app.codec, app.stakeKey, app.coinKeeper, app.RegisterCodespace(stake.DefaultCodespace),
|
||||
)
|
||||
app.govKeeper = gov.NewKeeper(
|
||||
app.codec, app.govKey, app.paramsKeeper.Setter(), app.coinKeeper,
|
||||
app.stakeKeeper, app.RegisterCodespace(gov.DefaultCodespace),
|
||||
)
|
||||
app.slashingKeeper = slashing.NewKeeper(
|
||||
app.codec, app.slashingKey, app.stakeKeeper,
|
||||
app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace),
|
||||
)
|
||||
|
||||
app.SetAnteHandler(handlers.AnteHandler(app.accountMapper))
|
||||
app.MountStoresIAVL(app.accountKey)
|
||||
// register message handlers
|
||||
app.Router().
|
||||
// TODO: Do we need to mount bank and IBC handlers? Should be handled
|
||||
// directly in the EVM.
|
||||
AddRoute("stake", stake.NewHandler(app.stakeKeeper)).
|
||||
AddRoute("slashing", slashing.NewHandler(app.slashingKeeper)).
|
||||
AddRoute("gov", gov.NewHandler(app.govKeeper))
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(app)
|
||||
}
|
||||
// initialize the underlying ABCI BaseApp
|
||||
app.SetInitChainer(app.initChainer)
|
||||
app.SetBeginBlocker(app.BeginBlocker)
|
||||
app.SetEndBlocker(app.EndBlocker)
|
||||
app.SetAnteHandler(handlers.AnteHandler(app.accountMapper, app.feeCollKeeper))
|
||||
|
||||
err := app.LoadLatestVersion(app.accountKey)
|
||||
if err != nil {
|
||||
app.MountStoresIAVL(
|
||||
app.mainKey, app.accountKey, app.stakeKey, app.slashingKey,
|
||||
app.govKey, app.feeCollKey, app.paramsKey,
|
||||
)
|
||||
app.MountStore(app.tParamsKey, sdk.StoreTypeTransient)
|
||||
|
||||
if err := app.LoadLatestVersion(app.accountKey); err != nil {
|
||||
tmcmn.Exit(err.Error())
|
||||
}
|
||||
|
||||
app.seal()
|
||||
app.BaseApp.Seal()
|
||||
return app
|
||||
}
|
||||
|
||||
// seal seals the Ethermint application and prohibits any future modifications
|
||||
// that change critical components.
|
||||
func (app *EthermintApp) seal() {
|
||||
app.sealed = true
|
||||
// BeginBlocker signals the beginning of a block. It performs application
|
||||
// updates on the start of every block.
|
||||
func (app *EthermintApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock {
|
||||
tags := slashing.BeginBlocker(ctx, req, app.slashingKeeper)
|
||||
|
||||
return abci.ResponseBeginBlock{
|
||||
Tags: tags.ToKVPairs(),
|
||||
}
|
||||
}
|
||||
|
||||
// EndBlocker signals the end of a block. It performs application updates on
|
||||
// the end of every block.
|
||||
func (app *EthermintApp) EndBlocker(ctx sdk.Context, _ abci.RequestEndBlock) abci.ResponseEndBlock {
|
||||
tags := gov.EndBlocker(ctx, app.govKeeper)
|
||||
validatorUpdates := stake.EndBlocker(ctx, app.stakeKeeper)
|
||||
|
||||
app.slashingKeeper.AddValidators(ctx, validatorUpdates)
|
||||
|
||||
return abci.ResponseEndBlock{
|
||||
ValidatorUpdates: validatorUpdates,
|
||||
Tags: tags,
|
||||
}
|
||||
}
|
||||
|
||||
// initChainer initializes the application blockchain with validators and other
|
||||
// state data from TendermintCore.
|
||||
func (app *EthermintApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
|
||||
var genesisState GenesisState
|
||||
stateJSON := req.AppStateBytes
|
||||
|
||||
err := app.codec.UnmarshalJSON(stateJSON, &genesisState)
|
||||
if err != nil {
|
||||
panic(errors.Wrap(err, "failed to parse application genesis state"))
|
||||
}
|
||||
|
||||
// load the genesis accounts
|
||||
for _, genAcc := range genesisState.Accounts {
|
||||
acc := genAcc.ToAccount()
|
||||
acc.AccountNumber = app.accountMapper.GetNextAccountNumber(ctx)
|
||||
app.accountMapper.SetAccount(ctx, acc)
|
||||
}
|
||||
|
||||
// load the genesis stake information
|
||||
validators, err := stake.InitGenesis(ctx, app.stakeKeeper, genesisState.StakeData)
|
||||
if err != nil {
|
||||
panic(errors.Wrap(err, "failed to initialize genesis validators"))
|
||||
}
|
||||
|
||||
slashing.InitGenesis(ctx, app.slashingKeeper, genesisState.StakeData)
|
||||
gov.InitGenesis(ctx, app.govKeeper, genesisState.GovData)
|
||||
|
||||
return abci.ResponseInitChain{
|
||||
Validators: validators,
|
||||
}
|
||||
}
|
||||
|
||||
// CreateCodec creates a new amino wire codec and registers all the necessary
|
||||
@ -80,7 +181,12 @@ func (app *EthermintApp) seal() {
|
||||
func CreateCodec() *wire.Codec {
|
||||
codec := wire.NewCodec()
|
||||
|
||||
// Register other modules, types, and messages...
|
||||
types.RegisterWire(codec)
|
||||
auth.RegisterWire(codec)
|
||||
gov.RegisterWire(codec)
|
||||
slashing.RegisterWire(codec)
|
||||
stake.RegisterWire(codec)
|
||||
wire.RegisterCrypto(codec)
|
||||
|
||||
return codec
|
||||
}
|
||||
|
47
app/genesis.go
Normal file
47
app/genesis.go
Normal file
@ -0,0 +1,47 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||
"github.com/cosmos/ethermint/types"
|
||||
)
|
||||
|
||||
type (
|
||||
// GenesisState defines the application's genesis state. It contains all the
|
||||
// information required and accounts to initialize the blockchain.
|
||||
GenesisState struct {
|
||||
Accounts []GenesisAccount `json:"accounts"`
|
||||
StakeData stake.GenesisState `json:"stake"`
|
||||
GovData gov.GenesisState `json:"gov"`
|
||||
}
|
||||
|
||||
// GenesisAccount defines an account to be initialized in the genesis state.
|
||||
GenesisAccount struct {
|
||||
Address sdk.AccAddress `json:"address"`
|
||||
Coins sdk.Coins `json:"coins"`
|
||||
Code []byte `json:"code,omitempty"`
|
||||
Storage types.Storage `json:"storage,omitempty"`
|
||||
}
|
||||
)
|
||||
|
||||
// NewGenesisAccount returns a reference to a new initialized genesis account.
|
||||
func NewGenesisAccount(acc *types.Account) GenesisAccount {
|
||||
return GenesisAccount{
|
||||
Address: acc.GetAddress(),
|
||||
Coins: acc.GetCoins(),
|
||||
Code: acc.Code,
|
||||
Storage: acc.Storage,
|
||||
}
|
||||
}
|
||||
|
||||
// ToAccount converts a genesis account to an initialized Ethermint account.
|
||||
func (ga *GenesisAccount) ToAccount() (acc *types.Account) {
|
||||
base := auth.BaseAccount{
|
||||
Address: ga.Address,
|
||||
Coins: ga.Coins.Sort(),
|
||||
}
|
||||
|
||||
return types.NewAccount(base, ga.Code, ga.Storage)
|
||||
}
|
@ -30,7 +30,7 @@ type internalAnteHandler func(
|
||||
// transaction to an internal ante handler for performing transaction-level
|
||||
// processing (e.g. fee payment, signature verification) before being passed
|
||||
// onto it's respective handler.
|
||||
func AnteHandler(am auth.AccountMapper) sdk.AnteHandler {
|
||||
func AnteHandler(am auth.AccountMapper, _ auth.FeeCollectionKeeper) sdk.AnteHandler {
|
||||
return func(sdkCtx sdk.Context, tx sdk.Tx) (newCtx sdk.Context, res sdk.Result, abort bool) {
|
||||
var (
|
||||
gasLimit int64
|
||||
|
53
types/account.go
Normal file
53
types/account.go
Normal file
@ -0,0 +1,53 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/wire"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
var _ auth.Account = (*Account)(nil)
|
||||
|
||||
type (
|
||||
// Storage defines account storage
|
||||
Storage map[ethcmn.Hash]ethcmn.Hash
|
||||
|
||||
// Account defines an auth.BaseAccount extension for Ethermint. It is
|
||||
// compatible with the auth.AccountMapper.
|
||||
Account struct {
|
||||
auth.BaseAccount
|
||||
|
||||
Code []byte
|
||||
Storage Storage
|
||||
}
|
||||
)
|
||||
|
||||
// NewAccount returns a reference to a new initialized account.
|
||||
func NewAccount(base auth.BaseAccount, code []byte, storage Storage) *Account {
|
||||
return &Account{
|
||||
BaseAccount: base,
|
||||
Code: code,
|
||||
Storage: storage,
|
||||
}
|
||||
}
|
||||
|
||||
// GetAccountDecoder returns the auth.AccountDecoder function for the custom
|
||||
// Account type.
|
||||
func GetAccountDecoder(cdc *wire.Codec) auth.AccountDecoder {
|
||||
return func(accBytes []byte) (auth.Account, error) {
|
||||
if len(accBytes) == 0 {
|
||||
return nil, sdk.ErrTxDecode("account bytes are empty")
|
||||
}
|
||||
|
||||
acc := new(Account)
|
||||
|
||||
err := cdc.UnmarshalBinaryBare(accBytes, &acc)
|
||||
if err != nil {
|
||||
return nil, sdk.ErrTxDecode("failed to decode account bytes")
|
||||
}
|
||||
|
||||
return acc, err
|
||||
}
|
||||
}
|
@ -17,6 +17,8 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var _ sdk.Tx = (*Transaction)(nil)
|
||||
|
||||
const (
|
||||
// TypeTxEthereum reflects an Ethereum Transaction type.
|
||||
TypeTxEthereum = "Ethereum"
|
||||
|
@ -15,6 +15,7 @@ func init() {
|
||||
// codec.
|
||||
func RegisterWire(codec *wire.Codec) {
|
||||
sdk.RegisterWire(codec)
|
||||
codec.RegisterConcrete(&Account{}, "types/Account", nil)
|
||||
codec.RegisterConcrete(&EthSignature{}, "types/EthSignature", nil)
|
||||
codec.RegisterConcrete(TxData{}, "types/TxData", nil)
|
||||
codec.RegisterConcrete(Transaction{}, "types/Transaction", nil)
|
||||
|
Loading…
Reference in New Issue
Block a user