simplify baseapp and InitStater -> InitChainer
This commit is contained in:
parent
96b734b729
commit
c7df77ce3c
|
@ -1,9 +1,7 @@
|
|||
package baseapp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime/debug"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
|
@ -27,7 +25,7 @@ type BaseApp struct {
|
|||
db dbm.DB // common DB backend
|
||||
cms sdk.CommitMultiStore // Main (uncached) state
|
||||
txDecoder sdk.TxDecoder // unmarshal []byte into sdk.Tx
|
||||
InitStater sdk.InitStater // TODO unexpose
|
||||
initChainer sdk.InitChainer //
|
||||
anteHandler sdk.AnteHandler // ante handler for fee and auth
|
||||
router Router // handle any kind of message
|
||||
|
||||
|
@ -43,34 +41,14 @@ type BaseApp struct {
|
|||
var _ abci.Application = &BaseApp{}
|
||||
|
||||
// Create and name new BaseApp
|
||||
func NewBaseApp(name string) *BaseApp {
|
||||
var baseapp = &BaseApp{
|
||||
logger: makeDefaultLogger(),
|
||||
func NewBaseApp(name string, logger log.Logger, db dbm.DB) *BaseApp {
|
||||
return &BaseApp{
|
||||
logger: logger,
|
||||
name: name,
|
||||
db: nil,
|
||||
cms: nil,
|
||||
db: db,
|
||||
cms: store.NewCommitMultiStore(db),
|
||||
router: NewRouter(),
|
||||
}
|
||||
baseapp.initDB()
|
||||
baseapp.initMultiStore()
|
||||
|
||||
return baseapp
|
||||
}
|
||||
|
||||
// Create the underlying leveldb datastore which will
|
||||
// persist the Merkle tree inner & leaf nodes.
|
||||
func (app *BaseApp) initDB() {
|
||||
db, err := dbm.NewGoLevelDB(app.name, "data")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
app.db = db
|
||||
}
|
||||
|
||||
func (app *BaseApp) initMultiStore() {
|
||||
cms := store.NewCommitMultiStore(app.db)
|
||||
app.cms = cms
|
||||
}
|
||||
|
||||
// BaseApp Name
|
||||
|
@ -94,8 +72,8 @@ func (app *BaseApp) MountStore(key sdk.StoreKey, typ sdk.StoreType) {
|
|||
func (app *BaseApp) SetTxDecoder(txDecoder sdk.TxDecoder) {
|
||||
app.txDecoder = txDecoder
|
||||
}
|
||||
func (app *BaseApp) SetInitStater(initStater sdk.InitStater) {
|
||||
app.InitStater = initStater
|
||||
func (app *BaseApp) SetInitChainer(initChainer sdk.InitChainer) {
|
||||
app.initChainer = initChainer
|
||||
}
|
||||
func (app *BaseApp) SetAnteHandler(ah sdk.AnteHandler) {
|
||||
// deducts fee from payer, verifies signatures and nonces, sets Signers to ctx.
|
||||
|
@ -170,6 +148,22 @@ func (app *BaseApp) initFromStore(mainKey sdk.StoreKey) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// NewContext returns a new Context suitable for AnteHandler (and indirectly Handler) processing.
|
||||
// NOTE: txBytes may be nil to support TestApp.RunCheckTx
|
||||
// and TestApp.RunDeliverTx.
|
||||
func (app *BaseApp) NewContext(isCheckTx bool, txBytes []byte) sdk.Context {
|
||||
|
||||
store := app.getMultiStore(isCheckTx)
|
||||
if store == nil {
|
||||
panic("BaseApp.NewContext() requires BeginBlock(): missing store")
|
||||
}
|
||||
if app.header == nil {
|
||||
panic("BaseApp.NewContext() requires BeginBlock(): missing header")
|
||||
}
|
||||
|
||||
return sdk.NewContext(store, *app.header, isCheckTx, txBytes)
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
// ABCI
|
||||
|
||||
|
@ -193,18 +187,18 @@ func (app *BaseApp) SetOption(req abci.RequestSetOption) (res abci.ResponseSetOp
|
|||
|
||||
// Implements ABCI
|
||||
func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitChain) {
|
||||
// TODO: Use req.Validators
|
||||
// TODO: Use req.AppState in InitStater
|
||||
|
||||
if app.InitStater == nil {
|
||||
if app.initChainer == nil {
|
||||
// TODO: should we have some default handling of validators?
|
||||
return
|
||||
}
|
||||
|
||||
app.msDeliver = app.cms.CacheMultiStore()
|
||||
ctx := app.GenesisContext(nil)
|
||||
// get the store and make a context for the initialization
|
||||
store := app.cms.CacheMultiStore()
|
||||
ctx := sdk.NewContext(store, abci.Header{}, false, nil)
|
||||
|
||||
err := app.InitStater(ctx, nil)
|
||||
err := app.initChainer(ctx, req)
|
||||
if err != nil {
|
||||
// TODO: something better https://github.com/cosmos/cosmos-sdk/issues/468
|
||||
cmn.Exit(fmt.Sprintf("error initializing application genesis state: %v", err))
|
||||
}
|
||||
return
|
||||
|
@ -376,20 +370,3 @@ func (app *BaseApp) getMultiStore(isCheckTx bool) sdk.MultiStore {
|
|||
}
|
||||
return app.msDeliver
|
||||
}
|
||||
|
||||
// Return index of list with validator of same PubKey, or -1 if no match
|
||||
func pubKeyIndex(val *abci.Validator, list []*abci.Validator) int {
|
||||
for i, v := range list {
|
||||
if bytes.Equal(val.PubKey, v.PubKey) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// Make a simple default logger
|
||||
// TODO: Make log capturable for each transaction, and return it in
|
||||
// ResponseDeliverTx.Log and ResponseCheckTx.Log.
|
||||
func makeDefaultLogger() log.Logger {
|
||||
return log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app")
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -12,12 +13,23 @@ import (
|
|||
"github.com/tendermint/go-crypto"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
dbm "github.com/tendermint/tmlibs/db"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
func defaultLogger() log.Logger {
|
||||
return log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app")
|
||||
}
|
||||
|
||||
func newBaseApp(name string) *BaseApp {
|
||||
logger := defaultLogger()
|
||||
db := dbm.NewMemDB()
|
||||
return NewBaseApp(name, logger, db)
|
||||
}
|
||||
|
||||
func TestMountStores(t *testing.T) {
|
||||
app := NewBaseApp(t.Name())
|
||||
app := newBaseApp(t.Name())
|
||||
|
||||
// make some cap keys
|
||||
capKey1 := sdk.NewKVStoreKey("key1")
|
||||
|
@ -65,7 +77,7 @@ func (tx testUpdatePowerTx) GetSignatures() []sdk.StdSignature { return ni
|
|||
func TestExecution(t *testing.T) {
|
||||
|
||||
// Create app.
|
||||
app := NewBaseApp(t.Name())
|
||||
app := newBaseApp(t.Name())
|
||||
storeKeys := createMounts(app.cms)
|
||||
app.SetTxDecoder(func(txBytes []byte) (sdk.Tx, sdk.Error) {
|
||||
var ttx testUpdatePowerTx
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
package baseapp
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
abci "github.com/tendermint/abci/types"
|
||||
)
|
||||
|
||||
// NewContext returns a new Context suitable for AnteHandler (and indirectly Handler) processing.
|
||||
// NOTE: txBytes may be nil to support TestApp.RunCheckTx
|
||||
// and TestApp.RunDeliverTx.
|
||||
func (app *BaseApp) NewContext(isCheckTx bool, txBytes []byte) sdk.Context {
|
||||
var store sdk.MultiStore
|
||||
if isCheckTx {
|
||||
store = app.msCheck
|
||||
} else {
|
||||
store = app.msDeliver
|
||||
}
|
||||
|
||||
if store == nil {
|
||||
panic("BaseApp.NewContext() requires BeginBlock(): missing store")
|
||||
}
|
||||
if app.header == nil {
|
||||
panic("BaseApp.NewContext() requires BeginBlock(): missing header")
|
||||
}
|
||||
|
||||
return sdk.NewContext(store, *app.header, isCheckTx, txBytes)
|
||||
}
|
||||
|
||||
// context used during genesis
|
||||
func (app *BaseApp) GenesisContext(txBytes []byte) sdk.Context {
|
||||
store := app.msDeliver
|
||||
if store == nil {
|
||||
panic("BaseApp.NewContext() requires BeginBlock(): missing store")
|
||||
}
|
||||
return sdk.NewContext(store, abci.Header{}, false, txBytes)
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
package baseapp
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
// TODO: remove from here and pass the AppState through InitChain
|
||||
|
||||
// GenesisDoc defines the initial conditions for a tendermint blockchain, in particular its validator set.
|
||||
type GenesisDoc struct {
|
||||
AppState json.RawMessage `json:"app_state,omitempty"`
|
||||
}
|
||||
|
||||
// GenesisDocFromFile reads JSON data from a file and unmarshalls it into a GenesisDoc.
|
||||
func LoadGenesisAppState(genesisPath string) (state json.RawMessage, err error) {
|
||||
if genesisPath == "" {
|
||||
return
|
||||
}
|
||||
jsonBlob, err := ioutil.ReadFile(genesisPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
genDoc := GenesisDoc{}
|
||||
err = json.Unmarshal(jsonBlob, &genDoc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return genDoc.AppState, nil
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
package baseapp
|
||||
|
||||
import (
|
||||
abci "github.com/tendermint/abci/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp/testtx"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// TestApp wraps BaseApp with helper methods,
|
||||
// and exposes more functionality than otherwise needed.
|
||||
type TestApp struct {
|
||||
*BaseApp
|
||||
|
||||
// These get set as we receive them.
|
||||
*abci.ResponseBeginBlock
|
||||
*abci.ResponseEndBlock
|
||||
}
|
||||
|
||||
func NewTestApp(bapp *BaseApp) *TestApp {
|
||||
app := &TestApp{
|
||||
BaseApp: bapp,
|
||||
}
|
||||
return app
|
||||
}
|
||||
|
||||
// execute BaseApp BeginBlock
|
||||
func (tapp *TestApp) RunBeginBlock() {
|
||||
if tapp.header != nil {
|
||||
panic("TestApp.header not nil, BeginBlock already run, or EndBlock not yet run.")
|
||||
}
|
||||
cms := tapp.CommitMultiStore()
|
||||
lastCommit := cms.LastCommitID()
|
||||
header := abci.Header{
|
||||
ChainID: "chain_" + tapp.BaseApp.name,
|
||||
Height: lastCommit.Version + 1,
|
||||
Time: -1, // TODO
|
||||
NumTxs: -1, // TODO
|
||||
LastCommitHash: lastCommit.Hash,
|
||||
DataHash: nil, // TODO
|
||||
ValidatorsHash: nil, // TODO
|
||||
AppHash: nil, // TODO
|
||||
}
|
||||
res := tapp.BeginBlock(abci.RequestBeginBlock{
|
||||
Hash: nil, // TODO
|
||||
Header: header,
|
||||
AbsentValidators: nil, // TODO
|
||||
ByzantineValidators: nil, // TODO
|
||||
})
|
||||
tapp.ResponseBeginBlock = &res
|
||||
return
|
||||
}
|
||||
|
||||
// kill resources used by basecapp
|
||||
func (tapp *TestApp) Close() {
|
||||
tapp.db.Close()
|
||||
}
|
||||
|
||||
func (tapp *TestApp) ensureBeginBlock() {
|
||||
if tapp.header == nil {
|
||||
panic("TestApp.header was nil, call TestApp.RunBeginBlock()")
|
||||
}
|
||||
}
|
||||
|
||||
// run tx through CheckTx of TestApp
|
||||
func (tapp *TestApp) RunCheckTx(tx sdk.Tx) sdk.Result {
|
||||
tapp.ensureBeginBlock()
|
||||
return tapp.BaseApp.runTx(true, nil, tx)
|
||||
}
|
||||
|
||||
// run tx through DeliverTx of TestApp
|
||||
func (tapp *TestApp) RunDeliverTx(tx sdk.Tx) sdk.Result {
|
||||
tapp.ensureBeginBlock()
|
||||
return tapp.BaseApp.runTx(false, nil, tx)
|
||||
}
|
||||
|
||||
// run tx through CheckTx of TestApp
|
||||
// NOTE: Skips authentication by wrapping msg in TestTx{}.
|
||||
func (tapp *TestApp) RunCheckMsg(msg sdk.Msg) sdk.Result {
|
||||
var tx = testtx.TestTx{msg}
|
||||
return tapp.RunCheckTx(tx)
|
||||
}
|
||||
|
||||
// run tx through DeliverTx of TestApp
|
||||
// NOTE: Skips authentication by wrapping msg in TestTx{}.
|
||||
func (tapp *TestApp) RunDeliverMsg(msg sdk.Msg) sdk.Result {
|
||||
var tx = testtx.TestTx{msg}
|
||||
return tapp.RunDeliverTx(tx)
|
||||
}
|
||||
|
||||
// return the commited multistore
|
||||
func (tapp *TestApp) CommitMultiStore() sdk.CommitMultiStore {
|
||||
return tapp.BaseApp.cms
|
||||
}
|
||||
|
||||
// return a cache-wrap CheckTx state of multistore
|
||||
func (tapp *TestApp) MultiStoreCheck() sdk.MultiStore {
|
||||
return tapp.BaseApp.msCheck
|
||||
}
|
||||
|
||||
// return a cache-wrap DeliverTx state of multistore
|
||||
func (tapp *TestApp) MultiStoreDeliver() sdk.MultiStore {
|
||||
return tapp.BaseApp.msDeliver
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package types
|
||||
|
||||
import abci "github.com/tendermint/abci/types"
|
||||
|
||||
// initialize application state at genesis
|
||||
type InitChainer func(ctx Context, req abci.RequestInitChain) Error
|
|
@ -1,6 +0,0 @@
|
|||
package types
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
// function variable used to initialize application state at genesis
|
||||
type InitStater func(ctx Context, state json.RawMessage) Error
|
Loading…
Reference in New Issue