diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 941c0eaf49..63bf6f764f 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -16,30 +16,28 @@ import ( "github.com/cosmos/cosmos-sdk/store" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/auth" ) var mainHeaderKey = []byte("header") // The ABCI application type BaseApp struct { - logger log.Logger - name string // application name from abci.Info - 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 - defaultAnteHandler sdk.AnteHandler // ante handler for fee and auth - router Router // handle any kind of message + logger log.Logger + name string // application name from abci.Info + 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 + anteHandler sdk.AnteHandler // ante handler for fee and auth + router Router // handle any kind of message //-------------------- // Volatile - accountMapper sdk.AccountMapper // Manage getting and setting accounts - msCheck sdk.CacheMultiStore // CheckTx state, a cache-wrap of `.cms` - msDeliver sdk.CacheMultiStore // DeliverTx state, a cache-wrap of `.cms` - header *abci.Header // current block header - valUpdates []abci.Validator // cached validator changes from DeliverTx + msCheck sdk.CacheMultiStore // CheckTx state, a cache-wrap of `.cms` + msDeliver sdk.CacheMultiStore // DeliverTx state, a cache-wrap of `.cms` + header *abci.Header // current block header + valUpdates []abci.Validator // cached validator changes from DeliverTx } var _ abci.Application = &BaseApp{} @@ -59,40 +57,6 @@ func NewBaseApp(name string) *BaseApp { return baseapp } -// Create and name new BaseApp -func NewBaseAppExpanded(name string, accountMapper sdk.AccountMapper, keys []*sdk.KVStoreKey) *BaseApp { - var baseapp = &BaseApp{ - logger: makeDefaultLogger(), - name: name, - db: nil, - cms: nil, - defaultAnteHandler: auth.NewAnteHandler(app.AccountMapper()), - router: NewRouter(), - accountMapper: accountMapper, - } - baseapp.initDB() - baseapp.initMultiStore() - baseapp.initAccountMapper() - - for _, key := range keys { - baseApp.MountStore(key, sdk.StoreTypeIAVL) - } - - return baseapp -} - -// Initialize the AccountMapper. -func (app *BaseApp) initAccountMapper() { - - // Register all interfaces and concrete types that - // implement those interfaces, here. - cdc := accountMapper.WireCodec() - auth.RegisterWireBaseAccount(cdc) - - // Make accountMapper's WireCodec() inaccessible. - app.accountMapper = accountMapper.Seal() -} - // Create the underlying leveldb datastore which will // persist the Merkle tree inner & leaf nodes. func (app *BaseApp) initDB() { @@ -114,6 +78,13 @@ func (app *BaseApp) Name() string { return app.name } +// Mount a store to the provided key in the BaseApp multistore +func (app *BaseApp) MountStoresIAVL(keys ...*sdk.KVStoreKey) { + for _, key := range keys { + app.MountStore(key, sdk.StoreTypeIAVL) + } +} + // Mount a store to the provided key in the BaseApp multistore func (app *BaseApp) MountStore(key sdk.StoreKey, typ sdk.StoreType) { app.cms.MountStoreWithDB(key, typ, app.db) @@ -126,14 +97,13 @@ func (app *BaseApp) SetTxDecoder(txDecoder sdk.TxDecoder) { func (app *BaseApp) SetInitStater(initStater sdk.InitStater) { app.InitStater = initStater } -func (app *BaseApp) SetDefaultAnteHandler(ah sdk.AnteHandler) { +func (app *BaseApp) SetAnteHandler(ah sdk.AnteHandler) { // deducts fee from payer, verifies signatures and nonces, sets Signers to ctx. - app.defaultAnteHandler = ah + app.anteHandler = ah } // nolint - Get functions -func (app *BaseApp) Router() Router { return app.router } -func (app *BaseApp) AccountMapper() sdk.AccountMapper { return app.accountMapper } +func (app *BaseApp) Router() Router { return app.router } /* TODO consider: func (app *BaseApp) SetBeginBlocker(...) {} @@ -224,7 +194,15 @@ 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 + // TODO: Use req.AppState in InitStater + + app.msDeliver = app.cms.CacheMultiStore() + ctx := app.GenesisContext(nil) + + err := app.InitStater(ctx, nil) + if err != nil { + cmn.Exit(fmt.Sprintf("error initializing application genesis state: %v", err)) + } return } @@ -338,7 +316,7 @@ func (app *BaseApp) runTx(isCheckTx bool, txBytes []byte, tx sdk.Tx) (result sdk // TODO: override default ante handler w/ custom ante handler. // Run the ante handler. - newCtx, result, abort := app.defaultAnteHandler(ctx, tx) + newCtx, result, abort := app.anteHandler(ctx, tx) if isCheckTx || abort { return result } diff --git a/baseapp/baseapp_test.go b/baseapp/baseapp_test.go index 7ceaacd203..695115729d 100644 --- a/baseapp/baseapp_test.go +++ b/baseapp/baseapp_test.go @@ -44,7 +44,7 @@ func TestBasic(t *testing.T) { return ttx, nil }) - app.SetDefaultAnteHandler(func(ctx sdk.Context, tx sdk.Tx) (newCtx sdk.Context, res sdk.Result, abort bool) { return }) + app.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx) (newCtx sdk.Context, res sdk.Result, abort bool) { return }) app.Router().AddRoute(msgType, func(ctx sdk.Context, msg sdk.Msg) sdk.Result { // TODO return sdk.Result{} diff --git a/baseapp/context.go b/baseapp/context.go index e5a60f9674..8ac10bce7d 100644 --- a/baseapp/context.go +++ b/baseapp/context.go @@ -2,6 +2,7 @@ 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. @@ -22,12 +23,14 @@ func (app *BaseApp) NewContext(isCheckTx bool, txBytes []byte) sdk.Context { panic("BaseApp.NewContext() requires BeginBlock(): missing header") } - // Initialize arguments to Handler. - var ctx = sdk.NewContext( - store, - *app.header, - isCheckTx, - txBytes, - ) - return ctx + 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) } diff --git a/baseapp/genesis.go b/baseapp/genesis.go index c18d5e3589..acd7d76888 100644 --- a/baseapp/genesis.go +++ b/baseapp/genesis.go @@ -13,7 +13,7 @@ type GenesisDoc struct { } // GenesisDocFromFile reads JSON data from a file and unmarshalls it into a GenesisDoc. -func ReadGenesisAppState(genesisPath string) (state json.RawMessage, err error) { +func LoadGenesisAppState(genesisPath string) (state json.RawMessage, err error) { if genesisPath == "" { return } diff --git a/baseapp/testapp.go b/baseapp/testapp/testapp.go similarity index 77% rename from baseapp/testapp.go rename to baseapp/testapp/testapp.go index c4067ef3c7..a80c494f43 100644 --- a/baseapp/testapp.go +++ b/baseapp/testapp/testapp.go @@ -1,23 +1,24 @@ -package baseapp +package testapp import ( abci "github.com/tendermint/abci/types" - "github.com/tendermint/go-crypto" + bam "github.com/cosmos/cosmos-sdk/baseapp" + x "github.com/cosmos/cosmos-sdk/baseapp/testapp/x" sdk "github.com/cosmos/cosmos-sdk/types" ) // TestApp wraps BaseApp with helper methods, // and exposes more functionality than otherwise needed. type TestApp struct { - *BaseApp + *bam.BaseApp // These get set as we receive them. *abci.ResponseBeginBlock *abci.ResponseEndBlock } -func NewTestApp(bapp *BaseApp) *TestApp { +func NewTestApp(bapp *bam.BaseApp) *TestApp { app := &TestApp{ BaseApp: bapp, } @@ -75,16 +76,16 @@ func (tapp *TestApp) RunDeliverTx(tx sdk.Tx) sdk.Result { } // run tx through CheckTx of TestApp -// NOTE: Skips authentication by wrapping msg in testTx{}. +// NOTE: Skips authentication by wrapping msg in TestTx{}. func (tapp *TestApp) RunCheckMsg(msg sdk.Msg) sdk.Result { - var tx = testTx{msg} + var tx = x.TestTx{msg} return tapp.RunCheckTx(tx) } // run tx through DeliverTx of TestApp -// NOTE: Skips authentication by wrapping msg in testTx{}. +// NOTE: Skips authentication by wrapping msg in TestTx{}. func (tapp *TestApp) RunDeliverMsg(msg sdk.Msg) sdk.Result { - var tx = testTx{msg} + var tx = x.TestTx{msg} return tapp.RunDeliverTx(tx) } @@ -102,20 +103,3 @@ func (tapp *TestApp) MultiStoreCheck() sdk.MultiStore { func (tapp *TestApp) MultiStoreDeliver() sdk.MultiStore { return tapp.BaseApp.msDeliver } - -//---------------------------------------- -// testTx - -type testTx struct { - sdk.Msg -} - -// nolint -func (tx testTx) GetMsg() sdk.Msg { return tx.Msg } -func (tx testTx) GetSigners() []crypto.Address { return nil } -func (tx testTx) GetFeePayer() crypto.Address { return nil } -func (tx testTx) GetSignatures() []sdk.StdSignature { return nil } -func IsTestAppTx(tx sdk.Tx) bool { - _, ok := tx.(testTx) - return ok -} diff --git a/baseapp/testapp/x/tx.go b/baseapp/testapp/x/tx.go new file mode 100644 index 0000000000..d99e56049b --- /dev/null +++ b/baseapp/testapp/x/tx.go @@ -0,0 +1,22 @@ +package baseapp + +import ( + "github.com/tendermint/go-crypto" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// testing transaction +type TestTx struct { + sdk.Msg +} + +// nolint +func (tx TestTx) GetMsg() sdk.Msg { return tx.Msg } +func (tx TestTx) GetSigners() []crypto.Address { return nil } +func (tx TestTx) GetFeePayer() crypto.Address { return nil } +func (tx TestTx) GetSignatures() []sdk.StdSignature { return nil } +func IsTestAppTx(tx sdk.Tx) bool { + _, ok := tx.(TestTx) + return ok +} diff --git a/examples/basecoin/app/app.go b/examples/basecoin/app/app.go index ead962e12a..b420021310 100644 --- a/examples/basecoin/app/app.go +++ b/examples/basecoin/app/app.go @@ -11,7 +11,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/x/sketchy" - abci "github.com/tendermint/abci/types" crypto "github.com/tendermint/go-crypto" "github.com/tendermint/go-wire" cmn "github.com/tendermint/tmlibs/common" @@ -27,27 +26,43 @@ type BasecoinApp struct { // keys to access the substores capKeyMainStore *sdk.KVStoreKey capKeyIBCStore *sdk.KVStoreKey + + // Manage getting and setting accounts + accountMapper sdk.AccountMapper } func NewBasecoinApp(genesisPath string) *BasecoinApp { - var app = &BasecoinApp{ - cdc: makeCodex(), - capKeyMainStore: sdk.NewKVStoreKey("main"), - capKeyIBCStore: sdk.NewKVStoreKey("ibc"), - } + // define some keys + mainKey := sdk.NewKVStoreKey("main") + ibcKey := sdk.NewKVStoreKey("ibc") - var accMapper = auth.NewAccountMapper( - app.capKeyMainStore, // target store + // define a mapper + accountMapper := auth.NewAccountMapper( + mainKey, // target store &types.AppAccount{}, // prototype ) + cdc := accountMapper.WireCodec() + auth.RegisterWireBaseAccount(cdc) + // Make accountMapper's WireCodec() inaccessible. + app.accountMapper = accountMapper.Seal() + + // create your application object + var app = &BasecoinApp{ + BaseApp: bam.NewBaseApp(appName, accountMapper), + cdc: makeTxCodec(), + capKeyMainStore: mainKey, + capKeyIBCStore: ibcKey, + } - app.BaseApp = bam.NewBaseAppExpanded(appName, accMapper) app.initBaseAppTxDecoder() app.initBaseAppInitStater(genesisPath) - // Add the handlers - app.Router().AddRoute("bank", bank.NewHandler(bank.NewCoinKeeper(app.AccountMapper()))) + app.MountStoresIAVL(app.capKeyMainStore, app.capKeyIBCStore) + + // add handlers + app.SetAnteHandler(auth.NewAnteHandler(accountMapper)) + app.Router().AddRoute("bank", bank.NewHandler(bank.NewCoinKeeper(accountMapper))) app.Router().AddRoute("sketchy", sketchy.NewHandler()) // load the stores @@ -89,20 +104,11 @@ func (app *BasecoinApp) initBaseAppTxDecoder() { // define the custom logic for basecoin initialization func (app *BasecoinApp) initBaseAppInitStater(genesisPath string) { - genesisAppState, err := bam.ReadGenesisAppState(genesisPath) + genesisAppState, err := bam.LoadGenesisAppState(genesisPath) if err != nil { panic(fmt.Errorf("error loading genesis state: %v", err)) } - // set up the cache store for ctx, get ctx - // TODO: combine with InitChain and let tendermint invoke it. - app.BaseApp.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{}}) - ctx := app.BaseApp.NewContext(false, nil) // context for DeliverTx - err = app.BaseApp.InitStater(ctx, genesisAppState) - if err != nil { - cmn.Exit(fmt.Sprintf("error initializing application genesis state: %v", err)) - } - app.BaseApp.SetInitStater(func(ctx sdk.Context, state json.RawMessage) sdk.Error { if state == nil { return nil @@ -119,7 +125,7 @@ func (app *BasecoinApp) initBaseAppInitStater(genesisPath string) { if err != nil { return sdk.ErrGenesisParse("").TraceCause(err, "") } - app.AccountMapper().SetAccount(ctx, acc) + app.accountMapper.SetAccount(ctx, acc) } return nil }) diff --git a/examples/basecoin/app/app_test.go b/examples/basecoin/app/app_test.go index 2014fef7c8..83e6edbd04 100644 --- a/examples/basecoin/app/app_test.go +++ b/examples/basecoin/app/app_test.go @@ -26,7 +26,7 @@ func newTestBasecoinApp() *testBasecoinApp { tba := &testBasecoinApp{ BasecoinApp: app, } - tba.TestApp = bam.NewTestApp(app.BaseApp) + tba.TestApp = testapp.NewTestApp(app.BaseApp) return tba } diff --git a/x/auth/ante.go b/x/auth/ante.go index a91fa55c28..0c0012522e 100644 --- a/x/auth/ante.go +++ b/x/auth/ante.go @@ -1,7 +1,7 @@ package auth import ( - bam "github.com/cosmos/cosmos-sdk/baseapp" + tax "github.com/cosmos/cosmos-sdk/baseapp/testapp/x" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -25,14 +25,14 @@ func NewAnteHandler(accountMapper sdk.AccountMapper) sdk.AnteHandler { // TODO: accountMapper.SetAccount(ctx, payerAddr) } else { // TODO: Ensure that some other spam prevention is used. - // NOTE: bam.TestApp.RunDeliverMsg/RunCheckMsg will - // create a Tx with no payer. + // NOTE: testapp.TestApp.RunDeliverMsg/RunCheckMsg will + // create a Tx with no payer. } var sigs = tx.GetSignatures() // Assert that there are signatures. - if !bam.IsTestAppTx(tx) { + if !tax.IsTestAppTx(tx) { if len(sigs) == 0 { return ctx, sdk.ErrUnauthorized("no signers").Result(), @@ -46,7 +46,7 @@ func NewAnteHandler(accountMapper sdk.AccountMapper) sdk.AnteHandler { var signerAccs = make([]sdk.Account, len(signerAddrs)) // Assert that number of signatures is correct. - if !bam.IsTestAppTx(tx) { + if !tax.IsTestAppTx(tx) { if len(sigs) != len(signerAddrs) { return ctx, sdk.ErrUnauthorized("wrong number of signers").Result(),