Merge pull request #470 from cosmos/basecoin-refactor-more
Basecoin refactor more
This commit is contained in:
commit
3b826455c6
|
@ -1,13 +1,12 @@
|
|||
package baseapp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime/debug"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
dbm "github.com/tendermint/tmlibs/db"
|
||||
|
@ -22,75 +21,38 @@ var mainHeaderKey = []byte("header")
|
|||
// The ABCI application
|
||||
type BaseApp struct {
|
||||
logger log.Logger
|
||||
|
||||
// Application name from abci.Info
|
||||
name string
|
||||
|
||||
// Common DB backend
|
||||
db dbm.DB
|
||||
|
||||
// Main (uncached) state
|
||||
cms sdk.CommitMultiStore
|
||||
|
||||
// unmarshal []byte into sdk.Tx
|
||||
txDecoder sdk.TxDecoder
|
||||
|
||||
// unmarshal rawjsonbytes to initialize the application
|
||||
// TODO unexpose and call from InitChain
|
||||
InitStater sdk.InitStater
|
||||
|
||||
// ante handler for fee and auth
|
||||
defaultAnteHandler sdk.AnteHandler
|
||||
|
||||
// handle any kind of message
|
||||
router Router
|
||||
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
|
||||
initChainer sdk.InitChainer //
|
||||
anteHandler sdk.AnteHandler // ante handler for fee and auth
|
||||
router Router // handle any kind of message
|
||||
|
||||
//--------------------
|
||||
// Volatile
|
||||
// .msCheck and .header are set on initialization.
|
||||
// .msDeliver is only set (and reset) in BeginBlock.
|
||||
// .header and .valUpdates are also reset in BeginBlock.
|
||||
// .msCheck is only reset in Commit.
|
||||
|
||||
// CheckTx state, a cache-wrap of `.cms`
|
||||
msCheck sdk.CacheMultiStore
|
||||
|
||||
// DeliverTx state, a cache-wrap of `.cms`
|
||||
msDeliver sdk.CacheMultiStore
|
||||
|
||||
// current block header
|
||||
header *abci.Header
|
||||
|
||||
// cached validator changes from DeliverTx
|
||||
valUpdates []abci.Validator
|
||||
header abci.Header // current block header
|
||||
msCheck sdk.CacheMultiStore // CheckTx state, a cache-wrap of `.cms`
|
||||
msDeliver sdk.CacheMultiStore // DeliverTx state, a cache-wrap of `.cms`
|
||||
valUpdates []abci.Validator // cached validator changes from DeliverTx
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -98,71 +60,79 @@ 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)
|
||||
}
|
||||
|
||||
// nolint
|
||||
// nolint - Set functions
|
||||
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) SetDefaultAnteHandler(ah sdk.AnteHandler) {
|
||||
app.defaultAnteHandler = ah
|
||||
}
|
||||
func (app *BaseApp) Router() Router {
|
||||
return app.router
|
||||
func (app *BaseApp) SetAnteHandler(ah sdk.AnteHandler) {
|
||||
// deducts fee from payer, verifies signatures and nonces, sets Signers to ctx.
|
||||
app.anteHandler = ah
|
||||
}
|
||||
|
||||
// nolint - Get functions
|
||||
func (app *BaseApp) Router() Router { return app.router }
|
||||
|
||||
/* TODO consider:
|
||||
func (app *BaseApp) SetBeginBlocker(...) {}
|
||||
func (app *BaseApp) SetEndBlocker(...) {}
|
||||
*/
|
||||
|
||||
// TODO add description
|
||||
// load latest application version
|
||||
func (app *BaseApp) LoadLatestVersion(mainKey sdk.StoreKey) error {
|
||||
app.cms.LoadLatestVersion()
|
||||
return app.initFromStore(mainKey)
|
||||
}
|
||||
|
||||
// Load application version
|
||||
// load application version
|
||||
func (app *BaseApp) LoadVersion(version int64, mainKey sdk.StoreKey) error {
|
||||
app.cms.LoadVersion(version)
|
||||
return app.initFromStore(mainKey)
|
||||
}
|
||||
|
||||
// The last CommitID of the multistore.
|
||||
// the last CommitID of the multistore
|
||||
func (app *BaseApp) LastCommitID() sdk.CommitID {
|
||||
return app.cms.LastCommitID()
|
||||
}
|
||||
|
||||
// The last commited block height.
|
||||
// the last commited block height
|
||||
func (app *BaseApp) LastBlockHeight() int64 {
|
||||
return app.cms.LastCommitID().Version
|
||||
}
|
||||
|
||||
// Initializes the remaining logic from app.cms.
|
||||
// initializes the remaining logic from app.cms
|
||||
func (app *BaseApp) initFromStore(mainKey sdk.StoreKey) error {
|
||||
var lastCommitID = app.cms.LastCommitID()
|
||||
var main = app.cms.GetKVStore(mainKey)
|
||||
var header *abci.Header
|
||||
var header abci.Header
|
||||
|
||||
// Main store should exist.
|
||||
// main store should exist.
|
||||
if main == nil {
|
||||
return errors.New("BaseApp expects MultiStore with 'main' KVStore")
|
||||
}
|
||||
|
||||
// If we've committed before, we expect main://<mainHeaderKey>.
|
||||
// if we've committed before, we expect main://<mainHeaderKey>
|
||||
if !lastCommitID.IsZero() {
|
||||
headerBytes := main.Get(mainHeaderKey)
|
||||
if len(headerBytes) == 0 {
|
||||
errStr := fmt.Sprintf("Version > 0 but missing key %s", mainHeaderKey)
|
||||
return errors.New(errStr)
|
||||
}
|
||||
err := proto.Unmarshal(headerBytes, header)
|
||||
err := proto.Unmarshal(headerBytes, &header)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to parse Header")
|
||||
}
|
||||
|
@ -173,16 +143,27 @@ func (app *BaseApp) initFromStore(mainKey sdk.StoreKey) error {
|
|||
}
|
||||
}
|
||||
|
||||
// Set BaseApp state.
|
||||
// set BaseApp state
|
||||
app.header = header
|
||||
app.msCheck = nil
|
||||
app.msCheck = app.cms.CacheMultiStore()
|
||||
app.msDeliver = nil
|
||||
app.valUpdates = nil
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewContext returns a new Context suitable for AnteHandler and Handler processing.
|
||||
// NOTE: header is empty for checkTx
|
||||
// NOTE: txBytes may be nil, for instance in tests (using app.Check or app.Deliver directly).
|
||||
func (app *BaseApp) NewContext(isCheckTx bool, txBytes []byte) sdk.Context {
|
||||
store := app.getMultiStore(isCheckTx)
|
||||
// XXX CheckTx can't safely get the header
|
||||
header := abci.Header{}
|
||||
return sdk.NewContext(store, header, isCheckTx, txBytes)
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
// ABCI
|
||||
|
||||
// Implements ABCI
|
||||
func (app *BaseApp) Info(req abci.RequestInfo) abci.ResponseInfo {
|
||||
|
@ -203,9 +184,27 @@ func (app *BaseApp) SetOption(req abci.RequestSetOption) (res abci.ResponseSetOp
|
|||
}
|
||||
|
||||
// Implements ABCI
|
||||
// InitChain runs the initialization logic directly on the CommitMultiStore and commits it.
|
||||
func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitChain) {
|
||||
// TODO: Use req.Validators
|
||||
// TODO: Use req.AppStateJSON (?)
|
||||
if app.initChainer == nil {
|
||||
// TODO: should we have some default handling of validators?
|
||||
return
|
||||
}
|
||||
|
||||
// make a context for the initialization.
|
||||
// NOTE: we're writing to the cms directly, without a CacheWrap
|
||||
ctx := sdk.NewContext(app.cms, abci.Header{}, false, 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))
|
||||
}
|
||||
|
||||
// XXX this commits everything and bumps the version.
|
||||
// https://github.com/cosmos/cosmos-sdk/issues/442#issuecomment-366470148
|
||||
app.cms.Commit()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -223,9 +222,8 @@ func (app *BaseApp) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
|
|||
// Implements ABCI
|
||||
func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeginBlock) {
|
||||
// NOTE: For consistency we should unset these upon EndBlock.
|
||||
app.header = &req.Header
|
||||
app.header = req.Header
|
||||
app.msDeliver = app.cms.CacheMultiStore()
|
||||
app.msCheck = app.cms.CacheMultiStore()
|
||||
app.valUpdates = nil
|
||||
return
|
||||
}
|
||||
|
@ -253,7 +251,6 @@ func (app *BaseApp) CheckTx(txBytes []byte) (res abci.ResponseCheckTx) {
|
|||
},
|
||||
Tags: result.Tags,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Implements ABCI
|
||||
|
@ -288,9 +285,16 @@ func (app *BaseApp) DeliverTx(txBytes []byte) (res abci.ResponseDeliverTx) {
|
|||
}
|
||||
}
|
||||
|
||||
// txBytes may be nil in some cases, for example, when tx is
|
||||
// coming from TestApp. Also, in the future we may support
|
||||
// "internal" transactions.
|
||||
// Mostly for testing
|
||||
func (app *BaseApp) Check(tx sdk.Tx) (result sdk.Result) {
|
||||
return app.runTx(true, nil, tx)
|
||||
}
|
||||
func (app *BaseApp) Deliver(tx sdk.Tx) (result sdk.Result) {
|
||||
return app.runTx(false, nil, tx)
|
||||
}
|
||||
|
||||
// txBytes may be nil in some cases, eg. in tests.
|
||||
// Also, in the future we may support "internal" transactions.
|
||||
func (app *BaseApp) runTx(isCheckTx bool, txBytes []byte, tx sdk.Tx) (result sdk.Result) {
|
||||
|
||||
// Handle any panics.
|
||||
|
@ -319,7 +323,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
|
||||
}
|
||||
|
@ -328,7 +332,7 @@ func (app *BaseApp) runTx(isCheckTx bool, txBytes []byte, tx sdk.Tx) (result sdk
|
|||
}
|
||||
|
||||
// CacheWrap app.msDeliver in case it fails.
|
||||
msCache := app.getMultiStore(isCheckTx).CacheMultiStore()
|
||||
msCache := app.getMultiStore(false).CacheMultiStore()
|
||||
ctx = ctx.WithMultiStore(msCache)
|
||||
|
||||
// Match and run route.
|
||||
|
@ -348,9 +352,7 @@ func (app *BaseApp) runTx(isCheckTx bool, txBytes []byte, tx sdk.Tx) (result sdk
|
|||
func (app *BaseApp) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBlock) {
|
||||
res.ValidatorUpdates = app.valUpdates
|
||||
app.valUpdates = nil
|
||||
app.header = nil
|
||||
app.msDeliver = nil
|
||||
app.msCheck = nil
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -367,7 +369,7 @@ func (app *BaseApp) Commit() (res abci.ResponseCommit) {
|
|||
}
|
||||
|
||||
//----------------------------------------
|
||||
// Misc.
|
||||
// Helpers
|
||||
|
||||
func (app *BaseApp) getMultiStore(isCheckTx bool) sdk.MultiStore {
|
||||
if isCheckTx {
|
||||
|
@ -375,20 +377,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,10 +13,83 @@ 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) {
|
||||
name := t.Name()
|
||||
app := newBaseApp(name)
|
||||
assert.Equal(t, name, app.Name())
|
||||
|
||||
// make some cap keys
|
||||
capKey1 := sdk.NewKVStoreKey("key1")
|
||||
capKey2 := sdk.NewKVStoreKey("key2")
|
||||
|
||||
// no stores are mounted
|
||||
assert.Panics(t, func() { app.LoadLatestVersion(capKey1) })
|
||||
|
||||
app.MountStoresIAVL(capKey1, capKey2)
|
||||
|
||||
// both stores are mounted
|
||||
err := app.LoadLatestVersion(capKey1)
|
||||
assert.Nil(t, err)
|
||||
err = app.LoadLatestVersion(capKey2)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestLoadVersion(t *testing.T) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
func TestInitChainer(t *testing.T) {
|
||||
app := newBaseApp(t.Name())
|
||||
|
||||
// make a cap key and mount the store
|
||||
capKey := sdk.NewKVStoreKey("main")
|
||||
app.MountStoresIAVL(capKey)
|
||||
err := app.LoadLatestVersion(capKey) // needed to make stores non-nil
|
||||
assert.Nil(t, err)
|
||||
|
||||
key, value := []byte("hello"), []byte("goodbye")
|
||||
|
||||
// initChainer sets a value in the store
|
||||
var initChainer sdk.InitChainer = func(ctx sdk.Context, req abci.RequestInitChain) sdk.Error {
|
||||
store := ctx.KVStore(capKey)
|
||||
store.Set(key, value)
|
||||
return nil
|
||||
}
|
||||
|
||||
query := abci.RequestQuery{
|
||||
Path: "/main/key",
|
||||
Data: key,
|
||||
}
|
||||
|
||||
// initChainer is nil - nothing happens
|
||||
app.InitChain(abci.RequestInitChain{})
|
||||
res := app.Query(query)
|
||||
assert.Equal(t, 0, len(res.Value))
|
||||
|
||||
// set initChainer and try again - should see the value
|
||||
app.SetInitChainer(initChainer)
|
||||
app.InitChain(abci.RequestInitChain{})
|
||||
res = app.Query(query)
|
||||
assert.Equal(t, value, res.Value)
|
||||
}
|
||||
|
||||
//----------------------
|
||||
|
||||
// A mock transaction to update a validator's voting power.
|
||||
type testUpdatePowerTx struct {
|
||||
Addr []byte
|
||||
|
@ -33,10 +107,10 @@ func (tx testUpdatePowerTx) GetSigners() []crypto.Address { return ni
|
|||
func (tx testUpdatePowerTx) GetFeePayer() crypto.Address { return nil }
|
||||
func (tx testUpdatePowerTx) GetSignatures() []sdk.StdSignature { return nil }
|
||||
|
||||
func TestBasic(t *testing.T) {
|
||||
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
|
||||
|
@ -44,7 +118,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{}
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
package baseapp
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/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")
|
||||
}
|
||||
|
||||
// Initialize arguments to Handler.
|
||||
var ctx = sdk.NewContext(
|
||||
store,
|
||||
*app.header,
|
||||
isCheckTx,
|
||||
txBytes,
|
||||
)
|
||||
return ctx
|
||||
}
|
|
@ -1,32 +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 GenesisDocFromFile(genDocFile string) (*GenesisDoc, error) {
|
||||
if genDocFile == "" {
|
||||
var g GenesisDoc
|
||||
return &g, nil
|
||||
}
|
||||
jsonBlob, err := ioutil.ReadFile(genDocFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
genDoc := GenesisDoc{}
|
||||
err = json.Unmarshal(jsonBlob, &genDoc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &genDoc, nil
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package baseapp
|
||||
|
||||
import (
|
||||
"github.com/tendermint/abci/server"
|
||||
abci "github.com/tendermint/abci/types"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
)
|
||||
|
||||
// RunForever - BasecoinApp execution and cleanup
|
||||
func RunForever(app abci.Application) {
|
||||
|
||||
// Start the ABCI server
|
||||
srv, err := server.NewServer("0.0.0.0:46658", "socket", app)
|
||||
if err != nil {
|
||||
cmn.Exit(err.Error())
|
||||
}
|
||||
srv.Start()
|
||||
|
||||
// Wait forever
|
||||
cmn.TrapSignal(func() {
|
||||
// Cleanup
|
||||
srv.Stop()
|
||||
})
|
||||
}
|
|
@ -6,12 +6,13 @@ import (
|
|||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// Router - TODO add description
|
||||
// Router provides handlers for each transaction type.
|
||||
type Router interface {
|
||||
AddRoute(r string, h sdk.Handler)
|
||||
Route(path string) (h sdk.Handler)
|
||||
}
|
||||
|
||||
// map a transaction type to a handler
|
||||
type route struct {
|
||||
r string
|
||||
h sdk.Handler
|
||||
|
|
|
@ -1,116 +0,0 @@
|
|||
package baseapp
|
||||
|
||||
import (
|
||||
abci "github.com/tendermint/abci/types"
|
||||
"github.com/tendermint/go-crypto"
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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{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{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
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
// 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
|
||||
}
|
|
@ -1,41 +1,19 @@
|
|||
PACKAGES=$(shell go list ./... | grep -v '/vendor/')
|
||||
BUILD_FLAGS = -ldflags "-X github.com/cosmos/cosmos-sdk/examples/basecoin/version.GitCommit=`git rev-parse --short HEAD`"
|
||||
|
||||
all: check_tools get_vendor_deps build test
|
||||
|
||||
########################################
|
||||
### Build
|
||||
all: get_vendor_deps build test
|
||||
|
||||
build:
|
||||
go build $(BUILD_FLAGS) -o build/basecoin ./cmd/...
|
||||
|
||||
|
||||
########################################
|
||||
### Tools & dependencies
|
||||
|
||||
check_tools:
|
||||
cd tools && $(MAKE) check
|
||||
|
||||
get_tools:
|
||||
cd tools && $(MAKE)
|
||||
|
||||
get_vendor_deps:
|
||||
@rm -rf vendor/
|
||||
@echo "--> Running glide install"
|
||||
@glide install
|
||||
|
||||
|
||||
########################################
|
||||
### Testing
|
||||
|
||||
test:
|
||||
@go test $(PACKAGES)
|
||||
|
||||
benchmark:
|
||||
@go test -bench=. $(PACKAGES)
|
||||
|
||||
|
||||
# To avoid unintended conflicts with file names, always add to .PHONY
|
||||
# unless there is a reason not to.
|
||||
# https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html
|
||||
.PHONY: build check_tools get_tools get_vendor_deps test benchmark
|
||||
.PHONY: build get_vendor_deps test benchmark
|
||||
|
|
|
@ -1,95 +1,114 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"encoding/json"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
"github.com/tendermint/go-wire"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
dbm "github.com/tendermint/tmlibs/db"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
||||
bam "github.com/cosmos/cosmos-sdk/baseapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
|
||||
"github.com/tendermint/abci/server"
|
||||
abci "github.com/tendermint/abci/types"
|
||||
"github.com/tendermint/go-wire"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
"github.com/cosmos/cosmos-sdk/examples/basecoin/types"
|
||||
"github.com/cosmos/cosmos-sdk/examples/basecoin/x/sketchy"
|
||||
)
|
||||
|
||||
const appName = "BasecoinApp"
|
||||
const (
|
||||
appName = "BasecoinApp"
|
||||
)
|
||||
|
||||
// BasecoinApp - extended ABCI application
|
||||
// Extended ABCI application
|
||||
type BasecoinApp struct {
|
||||
*bam.BaseApp
|
||||
router bam.Router
|
||||
cdc *wire.Codec
|
||||
multiStore sdk.CommitMultiStore //TODO distinguish this store from *bam.BaseApp.cms <- is this one master?? confused
|
||||
|
||||
// The key to access the substores.
|
||||
// keys to access the substores
|
||||
capKeyMainStore *sdk.KVStoreKey
|
||||
capKeyIBCStore *sdk.KVStoreKey
|
||||
|
||||
// Object mappers:
|
||||
// Manage getting and setting accounts
|
||||
accountMapper sdk.AccountMapper
|
||||
}
|
||||
|
||||
// NewBasecoinApp - create new BasecoinApp
|
||||
// TODO: This should take in more configuration options.
|
||||
// TODO: This should be moved into baseapp to isolate complexity
|
||||
func NewBasecoinApp(genesisPath string) *BasecoinApp {
|
||||
|
||||
// Create and configure app.
|
||||
var app = &BasecoinApp{}
|
||||
|
||||
// TODO open up out of functions, or introduce clarity,
|
||||
// interdependancies are a nightmare to debug
|
||||
app.initCapKeys() // ./init_capkeys.go
|
||||
app.initBaseApp() // ./init_baseapp.go
|
||||
app.initStores() // ./init_stores.go
|
||||
app.initBaseAppInitStater()
|
||||
app.initHandlers() // ./init_handlers.go
|
||||
|
||||
genesisiDoc, err := bam.GenesisDocFromFile(genesisPath)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("error loading genesis state: %v", err))
|
||||
func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp {
|
||||
// create your application object
|
||||
var app = &BasecoinApp{
|
||||
BaseApp: bam.NewBaseApp(appName, logger, db),
|
||||
cdc: MakeTxCodec(),
|
||||
capKeyMainStore: sdk.NewKVStoreKey("main"),
|
||||
capKeyIBCStore: sdk.NewKVStoreKey("ibc"),
|
||||
}
|
||||
|
||||
// set up the cache store for ctx, get ctx
|
||||
// TODO: can InitChain handle this too ?
|
||||
app.BaseApp.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{}})
|
||||
ctx := app.BaseApp.NewContext(false, nil) // context for DeliverTx
|
||||
// define the accountMapper
|
||||
app.accountMapper = auth.NewAccountMapperSealed(
|
||||
app.capKeyMainStore, // target store
|
||||
&types.AppAccount{}, // prototype
|
||||
)
|
||||
|
||||
// TODO: combine with InitChain and let tendermint invoke it.
|
||||
err = app.BaseApp.InitStater(ctx, genesisiDoc.AppState)
|
||||
// add handlers
|
||||
coinKeeper := bank.NewCoinKeeper(app.accountMapper)
|
||||
app.Router().AddRoute("bank", bank.NewHandler(coinKeeper))
|
||||
app.Router().AddRoute("sketchy", sketchy.NewHandler())
|
||||
|
||||
// initialize BaseApp
|
||||
app.SetTxDecoder()
|
||||
app.SetInitChainer()
|
||||
app.MountStoresIAVL(app.capKeyMainStore, app.capKeyIBCStore)
|
||||
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper))
|
||||
err := app.LoadLatestVersion(app.capKeyMainStore)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("error initializing application genesis state: %v", err))
|
||||
cmn.Exit(err.Error())
|
||||
}
|
||||
|
||||
app.loadStores()
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
// RunForever - BasecoinApp execution and cleanup
|
||||
func (app *BasecoinApp) RunForever() {
|
||||
// custom tx codec
|
||||
func MakeTxCodec() *wire.Codec {
|
||||
cdc := wire.NewCodec()
|
||||
crypto.RegisterWire(cdc) // Register crypto.[PubKey,PrivKey,Signature] types.
|
||||
bank.RegisterWire(cdc) // Register bank.[SendMsg,IssueMsg] types.
|
||||
return cdc
|
||||
}
|
||||
|
||||
// Start the ABCI server
|
||||
srv, err := server.NewServer("0.0.0.0:46658", "socket", app)
|
||||
// custom logic for transaction decoding
|
||||
func (app *BasecoinApp) SetTxDecoder() {
|
||||
app.BaseApp.SetTxDecoder(func(txBytes []byte) (sdk.Tx, sdk.Error) {
|
||||
var tx = sdk.StdTx{}
|
||||
// StdTx.Msg is an interface whose concrete
|
||||
// types are registered in app/msgs.go.
|
||||
err := app.cdc.UnmarshalBinary(txBytes, &tx)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
return nil, sdk.ErrTxParse("").TraceCause(err, "")
|
||||
}
|
||||
srv.Start()
|
||||
|
||||
// Wait forever
|
||||
cmn.TrapSignal(func() {
|
||||
// Cleanup
|
||||
srv.Stop()
|
||||
return tx, nil
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// Load the stores
|
||||
func (app *BasecoinApp) loadStores() {
|
||||
if err := app.LoadLatestVersion(app.capKeyMainStore); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
// custom logic for basecoin initialization
|
||||
func (app *BasecoinApp) SetInitChainer() {
|
||||
app.BaseApp.SetInitChainer(func(ctx sdk.Context, req abci.RequestInitChain) sdk.Error {
|
||||
stateJSON := req.AppStateBytes
|
||||
|
||||
genesisState := new(types.GenesisState)
|
||||
err := json.Unmarshal(stateJSON, genesisState)
|
||||
if err != nil {
|
||||
return sdk.ErrGenesisParse("").TraceCause(err, "")
|
||||
}
|
||||
|
||||
for _, gacc := range genesisState.Accounts {
|
||||
acc, err := gacc.ToAppAccount()
|
||||
if err != nil {
|
||||
return sdk.ErrGenesisParse("").TraceCause(err, "")
|
||||
}
|
||||
app.accountMapper.SetAccount(ctx, acc)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package app
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -12,12 +13,20 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
dbm "github.com/tendermint/tmlibs/db"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
)
|
||||
|
||||
func newBasecoinApp() *BasecoinApp {
|
||||
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app")
|
||||
db := dbm.NewMemDB()
|
||||
return NewBasecoinApp(logger, db)
|
||||
}
|
||||
|
||||
func TestSendMsg(t *testing.T) {
|
||||
tba := newTestBasecoinApp()
|
||||
tba.RunBeginBlock()
|
||||
bapp := newBasecoinApp()
|
||||
|
||||
// Construct a SendMsg.
|
||||
var msg = bank.SendMsg{
|
||||
|
@ -36,15 +45,25 @@ func TestSendMsg(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
// Run a Check on SendMsg.
|
||||
res := tba.RunCheckMsg(msg)
|
||||
assert.Equal(t, sdk.CodeOK, res.Code, res.Log)
|
||||
priv := crypto.GenPrivKeyEd25519()
|
||||
sig := priv.Sign(msg.GetSignBytes())
|
||||
tx := sdk.NewStdTx(msg, []sdk.StdSignature{{
|
||||
PubKey: priv.PubKey(),
|
||||
Signature: sig,
|
||||
}})
|
||||
|
||||
// Run a Deliver on SendMsg.
|
||||
res = tba.RunDeliverMsg(msg)
|
||||
// Run a Check
|
||||
res := bapp.Check(tx)
|
||||
assert.Equal(t, sdk.CodeUnrecognizedAddress, res.Code, res.Log)
|
||||
|
||||
// TODO seperate this test, need a closer on db? keep getting resource unavailable
|
||||
// Simulate a Block
|
||||
bapp.BeginBlock(abci.RequestBeginBlock{})
|
||||
res = bapp.Deliver(tx)
|
||||
assert.Equal(t, sdk.CodeUnrecognizedAddress, res.Code, res.Log)
|
||||
}
|
||||
|
||||
func TestGenesis(t *testing.T) {
|
||||
bapp := newBasecoinApp()
|
||||
|
||||
// construct some genesis bytes to reflect basecoin/types/AppAccount
|
||||
pk := crypto.GenPrivKeyEd25519().PubKey()
|
||||
|
@ -57,18 +76,19 @@ func TestSendMsg(t *testing.T) {
|
|||
}
|
||||
acc := &types.AppAccount{baseAcc, "foobart"}
|
||||
|
||||
genesisState := GenesisState{
|
||||
Accounts: []*GenesisAccount{
|
||||
NewGenesisAccount(acc),
|
||||
genesisState := types.GenesisState{
|
||||
Accounts: []*types.GenesisAccount{
|
||||
types.NewGenesisAccount(acc),
|
||||
},
|
||||
}
|
||||
bytes, err := json.MarshalIndent(genesisState, "", "\t")
|
||||
stateBytes, err := json.MarshalIndent(genesisState, "", "\t")
|
||||
|
||||
app := tba.BasecoinApp
|
||||
ctx := app.BaseApp.NewContext(false, nil) // context for DeliverTx
|
||||
err = app.BaseApp.InitStater(ctx, bytes)
|
||||
require.Nil(t, err)
|
||||
vals := []abci.Validator{}
|
||||
bapp.InitChain(abci.RequestInitChain{vals, stateBytes})
|
||||
|
||||
res1 := app.accountMapper.GetAccount(ctx, baseAcc.Address)
|
||||
// a checkTx context
|
||||
ctx := bapp.BaseApp.NewContext(true, nil)
|
||||
|
||||
res1 := bapp.accountMapper.GetAccount(ctx, baseAcc.Address)
|
||||
assert.Equal(t, acc, res1)
|
||||
}
|
||||
|
|
|
@ -1,93 +0,0 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/examples/basecoin/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
// initCapKeys, initBaseApp, initStores, initHandlers.
|
||||
func (app *BasecoinApp) initBaseApp() {
|
||||
bapp := baseapp.NewBaseApp(appName)
|
||||
app.BaseApp = bapp
|
||||
app.router = bapp.Router()
|
||||
app.initBaseAppTxDecoder()
|
||||
app.initBaseAppInitStater()
|
||||
}
|
||||
|
||||
func (app *BasecoinApp) initBaseAppTxDecoder() {
|
||||
cdc := makeTxCodec()
|
||||
app.BaseApp.SetTxDecoder(func(txBytes []byte) (sdk.Tx, sdk.Error) {
|
||||
var tx = sdk.StdTx{}
|
||||
// StdTx.Msg is an interface whose concrete
|
||||
// types are registered in app/msgs.go.
|
||||
err := cdc.UnmarshalBinary(txBytes, &tx)
|
||||
if err != nil {
|
||||
return nil, sdk.ErrTxParse("").TraceCause(err, "")
|
||||
}
|
||||
return tx, nil
|
||||
})
|
||||
}
|
||||
|
||||
// define the custom logic for basecoin initialization
|
||||
func (app *BasecoinApp) initBaseAppInitStater() {
|
||||
accountMapper := app.accountMapper
|
||||
|
||||
app.BaseApp.SetInitStater(func(ctx sdk.Context, state json.RawMessage) sdk.Error {
|
||||
if state == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
genesisState := new(GenesisState)
|
||||
err := json.Unmarshal(state, genesisState)
|
||||
if err != nil {
|
||||
return sdk.ErrGenesisParse("").TraceCause(err, "")
|
||||
}
|
||||
|
||||
for _, gacc := range genesisState.Accounts {
|
||||
acc, err := gacc.toAppAccount()
|
||||
if err != nil {
|
||||
return sdk.ErrGenesisParse("").TraceCause(err, "")
|
||||
}
|
||||
accountMapper.SetAccount(ctx, acc)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
|
||||
type GenesisState struct {
|
||||
Accounts []*GenesisAccount `accounts`
|
||||
}
|
||||
|
||||
// GenesisAccount doesn't need pubkey or sequence
|
||||
type GenesisAccount struct {
|
||||
Name string `json:"name"`
|
||||
Address crypto.Address `json:"address"`
|
||||
Coins sdk.Coins `json:"coins"`
|
||||
}
|
||||
|
||||
func NewGenesisAccount(aa *types.AppAccount) *GenesisAccount {
|
||||
return &GenesisAccount{
|
||||
Name: aa.Name,
|
||||
Address: aa.Address,
|
||||
Coins: aa.Coins,
|
||||
}
|
||||
}
|
||||
|
||||
// convert GenesisAccount to AppAccount
|
||||
func (ga *GenesisAccount) toAppAccount() (acc *types.AppAccount, err error) {
|
||||
baseAcc := auth.BaseAccount{
|
||||
Address: ga.Address,
|
||||
Coins: ga.Coins,
|
||||
}
|
||||
return &types.AppAccount{
|
||||
BaseAccount: baseAcc,
|
||||
Name: ga.Name,
|
||||
}, nil
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// initCapKeys, initBaseApp, initStores, initHandlers.
|
||||
func (app *BasecoinApp) initCapKeys() {
|
||||
|
||||
// All top-level capabilities keys
|
||||
// should be constructed here.
|
||||
// For more information, see http://www.erights.org/elib/capability/ode/ode.pdf.
|
||||
app.capKeyMainStore = sdk.NewKVStoreKey("main")
|
||||
app.capKeyIBCStore = sdk.NewKVStoreKey("ibc")
|
||||
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
"github.com/cosmos/cosmos-sdk/x/sketchy"
|
||||
)
|
||||
|
||||
// initCapKeys, initBaseApp, initStores, initHandlers.
|
||||
func (app *BasecoinApp) initHandlers() {
|
||||
app.initDefaultAnteHandler()
|
||||
app.initRouterHandlers()
|
||||
}
|
||||
|
||||
func (app *BasecoinApp) initDefaultAnteHandler() {
|
||||
|
||||
// Deducts fee from payer.
|
||||
// Verifies signatures and nonces.
|
||||
// Sets Signers to ctx.
|
||||
app.BaseApp.SetDefaultAnteHandler(
|
||||
auth.NewAnteHandler(app.accountMapper))
|
||||
}
|
||||
|
||||
func (app *BasecoinApp) initRouterHandlers() {
|
||||
|
||||
// All handlers must be added here.
|
||||
// The order matters.
|
||||
app.router.AddRoute("bank", bank.NewHandler(bank.NewCoinKeeper(app.accountMapper)))
|
||||
app.router.AddRoute("sketchy", sketchy.NewHandler())
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/examples/basecoin/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
)
|
||||
|
||||
// initCapKeys, initBaseApp, initStores, initHandlers.
|
||||
func (app *BasecoinApp) initStores() {
|
||||
app.mountStores()
|
||||
app.initAccountMapper()
|
||||
}
|
||||
|
||||
// Initialize root stores.
|
||||
func (app *BasecoinApp) mountStores() {
|
||||
|
||||
// Create MultiStore mounts.
|
||||
app.BaseApp.MountStore(app.capKeyMainStore, sdk.StoreTypeIAVL)
|
||||
app.BaseApp.MountStore(app.capKeyIBCStore, sdk.StoreTypeIAVL)
|
||||
}
|
||||
|
||||
// Initialize the AccountMapper.
|
||||
func (app *BasecoinApp) initAccountMapper() {
|
||||
|
||||
var accountMapper = auth.NewAccountMapper(
|
||||
app.capKeyMainStore, // target store
|
||||
&types.AppAccount{}, // prototype
|
||||
)
|
||||
|
||||
// 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()
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
wire "github.com/tendermint/go-wire"
|
||||
)
|
||||
|
||||
// Wire requires registration of interfaces & concrete types. All
|
||||
// interfaces to be encoded/decoded in a Msg must be registered
|
||||
// here, along with all the concrete types that implement them.
|
||||
func makeTxCodec() (cdc *wire.Codec) {
|
||||
cdc = wire.NewCodec()
|
||||
|
||||
// Register crypto.[PubKey,PrivKey,Signature] types.
|
||||
crypto.RegisterWire(cdc)
|
||||
|
||||
// Register bank.[SendMsg,IssueMsg] types.
|
||||
bank.RegisterWire(cdc)
|
||||
|
||||
return
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
bam "github.com/cosmos/cosmos-sdk/baseapp"
|
||||
)
|
||||
|
||||
type testBasecoinApp struct {
|
||||
*BasecoinApp
|
||||
*bam.TestApp
|
||||
}
|
||||
|
||||
func newTestBasecoinApp() *testBasecoinApp {
|
||||
app := NewBasecoinApp("")
|
||||
tba := &testBasecoinApp{
|
||||
BasecoinApp: app,
|
||||
}
|
||||
tba.TestApp = bam.NewTestApp(app.BaseApp)
|
||||
return tba
|
||||
}
|
|
@ -1,10 +1,27 @@
|
|||
package main
|
||||
|
||||
import "github.com/cosmos/cosmos-sdk/examples/basecoin/app"
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
dbm "github.com/tendermint/tmlibs/db"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/examples/basecoin/app"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// TODO CREATE CLI
|
||||
|
||||
bapp := app.NewBasecoinApp("")
|
||||
bapp.RunForever()
|
||||
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "main")
|
||||
|
||||
db, err := dbm.NewGoLevelDB("basecoind", "data")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
bapp := app.NewBasecoinApp(logger, db)
|
||||
baseapp.RunForever(bapp)
|
||||
}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
bin/*
|
|
@ -1,62 +0,0 @@
|
|||
all: install_glide check get_vendor_deps install
|
||||
|
||||
|
||||
########################################
|
||||
### Glide
|
||||
|
||||
GLIDE = github.com/tendermint/glide
|
||||
GLIDE_CHECK := $(shell command -v glide 2> /dev/null)
|
||||
|
||||
check:
|
||||
ifndef GLIDE_CHECK
|
||||
@echo "No glide in path. Install with 'make install_glide'."
|
||||
else
|
||||
@echo "Found glide in path."
|
||||
endif
|
||||
|
||||
install_glide:
|
||||
ifdef GLIDE_CHECK
|
||||
@echo "Glide is already installed. Run 'make update_glide' to update."
|
||||
else
|
||||
@echo "$(ansi_grn)Installing glide$(ansi_end)"
|
||||
go get -v $(GLIDE)
|
||||
endif
|
||||
|
||||
update_glide:
|
||||
@echo "$(ansi_grn)Updating glide$(ansi_end)"
|
||||
go get -u -v $(GLIDE)
|
||||
|
||||
|
||||
########################################
|
||||
### Install tools
|
||||
|
||||
|
||||
get_vendor_deps: check
|
||||
@rm -rf vendor/
|
||||
@echo "--> Running glide install"
|
||||
@glide install
|
||||
|
||||
install: get_vendor_deps
|
||||
@echo "$(ansi_grn)Installing tools$(ansi_end)"
|
||||
@echo "$(ansi_yel)Install go-vendorinstall$(ansi_end)"
|
||||
go build -o bin/go-vendorinstall go-vendorinstall/*.go
|
||||
|
||||
@echo "$(ansi_yel)Install gometalinter.v2$(ansi_end)"
|
||||
GOBIN=$(CURDIR)/bin ./bin/go-vendorinstall gopkg.in/alecthomas/gometalinter.v2
|
||||
|
||||
@echo "$(ansi_grn)Done installing tools$(ansi_end)"
|
||||
|
||||
|
||||
########################################
|
||||
# ANSI colors
|
||||
|
||||
ansi_red=\033[0;31m
|
||||
ansi_grn=\033[0;32m
|
||||
ansi_yel=\033[0;33m
|
||||
ansi_end=\033[0m
|
||||
|
||||
|
||||
# To avoid unintended conflicts with file names, always add to .PHONY
|
||||
# unless there is a reason not to.
|
||||
# https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html
|
||||
.PHONY: check install_glide update_glide get_vendor_deps install
|
|
@ -1,18 +0,0 @@
|
|||
hash: a163b1c4806024cfc9062db75a0abed285ec40461243e59af0e147db2c4bf0ce
|
||||
updated: 2018-01-15T19:02:49.834182027-08:00
|
||||
imports:
|
||||
- name: github.com/inconshreveable/mousetrap
|
||||
version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
|
||||
- name: github.com/rigelrozanski/common
|
||||
version: f691f115798593d783b9999b1263c2f4ffecc439
|
||||
- name: github.com/rigelrozanski/shelldown
|
||||
version: 2e18b6eb9bf428aa524e71433296e0b7c73ae0a3
|
||||
subpackages:
|
||||
- cmd/shelldown
|
||||
- name: github.com/spf13/cobra
|
||||
version: 7b2c5ac9fc04fc5efafb60700713d4fa609b777b
|
||||
- name: github.com/spf13/pflag
|
||||
version: 97afa5e7ca8a08a383cb259e06636b5e2cc7897f
|
||||
- name: gopkg.in/alecthomas/gometalinter.v2
|
||||
version: 88d47c66988c5a5cb3945925da47c883800a94df
|
||||
testImports: []
|
|
@ -1,6 +0,0 @@
|
|||
package: github.com/cosmos/cosmos-sdk/tools
|
||||
import:
|
||||
- package: github.com/rigelrozanski/shelldown
|
||||
subpackages:
|
||||
- cmd/shelldown
|
||||
- package: gopkg.in/alecthomas/gometalinter.v2
|
|
@ -1,129 +0,0 @@
|
|||
// https://raw.githubusercontent.com/roboll/go-vendorinstall/a3e9f0a5d5861b3bb16b93200b2c359c9846b3c5/main.go
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
source = flag.String("source", "vendor", "source directory")
|
||||
target = flag.String("target", "", "target directory (defaults to $GOBIN, if not set $GOPATH/bin)")
|
||||
commands = flag.String("commands", "", "comma separated list of commands to execute after go install in temporary environment")
|
||||
quiet = flag.Bool("quiet", false, "disable output")
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
packages := flag.Args()
|
||||
if len(packages) < 1 {
|
||||
fail(errors.New("no packages: specify a package"))
|
||||
}
|
||||
|
||||
gopath, err := ioutil.TempDir("", "go-vendorinstall-gopath")
|
||||
if err != nil {
|
||||
fail(err)
|
||||
}
|
||||
print(fmt.Sprintf("gopath: %s", gopath))
|
||||
defer func() {
|
||||
if err := os.RemoveAll(gopath); err != nil {
|
||||
fail(err)
|
||||
}
|
||||
}()
|
||||
|
||||
if len(*target) == 0 {
|
||||
if gobin := os.Getenv("GOBIN"); len(gobin) > 0 {
|
||||
target = &gobin
|
||||
} else {
|
||||
bin := fmt.Sprintf("%s/bin", os.Getenv("GOPATH"))
|
||||
target = &bin
|
||||
}
|
||||
}
|
||||
|
||||
gobin, err := filepath.Abs(*target)
|
||||
if err != nil {
|
||||
fail(err)
|
||||
}
|
||||
print(fmt.Sprintf("gobin: %s", gobin))
|
||||
|
||||
if err := link(gopath, *source); err != nil {
|
||||
fail(err)
|
||||
}
|
||||
|
||||
oldpath := os.Getenv("PATH")
|
||||
path := fmt.Sprintf("%s%s%s", gobin, string(os.PathListSeparator), os.Getenv("PATH"))
|
||||
os.Setenv("PATH", fmt.Sprintf("%s%s%s", gobin, string(os.PathListSeparator), os.Getenv("PATH")))
|
||||
defer os.Setenv("PATH", oldpath)
|
||||
|
||||
env := []string{fmt.Sprintf("PATH=%s", path), fmt.Sprintf("GOPATH=%s", gopath), fmt.Sprintf("GOBIN=%s", gobin)}
|
||||
args := append([]string{"install"}, packages...)
|
||||
if out, err := doexec("go", gopath, args, env); err != nil {
|
||||
print(string(out))
|
||||
fail(err)
|
||||
}
|
||||
|
||||
if len(*commands) > 0 {
|
||||
for _, cmd := range strings.Split(*commands, ",") {
|
||||
split := strings.Split(cmd, " ")
|
||||
if out, err := doexec(split[0], gopath, split[1:], env); err != nil {
|
||||
print(string(out))
|
||||
fail(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func print(msg string) {
|
||||
if !*quiet {
|
||||
fmt.Println(msg)
|
||||
}
|
||||
}
|
||||
|
||||
func fail(err error) {
|
||||
fmt.Printf("error: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func link(gopath, source string) error {
|
||||
srcdir, err := filepath.Abs(source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
linkto := filepath.Join(gopath, "src")
|
||||
if err := os.MkdirAll(linkto, 0777); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
files, err := ioutil.ReadDir(srcdir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
real := filepath.Join(srcdir, file.Name())
|
||||
link := filepath.Join(linkto, file.Name())
|
||||
if err := os.Symlink(real, link); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func doexec(bin, dir string, args []string, env []string) ([]byte, error) {
|
||||
print(fmt.Sprintf("%s %s", bin, strings.Join(args, " ")))
|
||||
cmd := exec.Command(bin, args...)
|
||||
cmd.Env = env
|
||||
cmd.Dir = dir
|
||||
|
||||
return cmd.CombinedOutput()
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
// Include dependencies here so glide picks them up
|
||||
// and installs sub-dependencies.
|
||||
|
||||
// TODO: Ideally this gets auto-imported on glide update.
|
||||
// Any way to make that happen?
|
||||
_ "github.com/rigelrozanski/common"
|
||||
)
|
||||
|
||||
func main() {}
|
|
@ -3,25 +3,55 @@ package types
|
|||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
var _ sdk.Account = (*AppAccount)(nil)
|
||||
|
||||
// Custom extensions for this application. This is just an example of
|
||||
// extending auth.BaseAccount with custom fields.
|
||||
//
|
||||
// This is compatible with the stock auth.AccountStore, since
|
||||
// auth.AccountStore uses the flexible go-wire library.
|
||||
type AppAccount struct {
|
||||
auth.BaseAccount
|
||||
|
||||
// Custom extensions for this application. This is just an example of
|
||||
// extending auth.BaseAccount with custom fields.
|
||||
//
|
||||
// This is compatible with the stock auth.AccountStore, since
|
||||
// auth.AccountStore uses the flexible go-wire library.
|
||||
Name string
|
||||
}
|
||||
|
||||
func (acc AppAccount) GetName() string {
|
||||
return acc.Name
|
||||
// nolint
|
||||
func (acc AppAccount) GetName() string { return acc.Name }
|
||||
func (acc *AppAccount) SetName(name string) { acc.Name = name }
|
||||
|
||||
//___________________________________________________________________________________
|
||||
|
||||
// State to Unmarshal
|
||||
type GenesisState struct {
|
||||
Accounts []*GenesisAccount `json:"accounts"`
|
||||
}
|
||||
|
||||
func (acc *AppAccount) SetName(name string) {
|
||||
acc.Name = name
|
||||
// GenesisAccount doesn't need pubkey or sequence
|
||||
type GenesisAccount struct {
|
||||
Name string `json:"name"`
|
||||
Address crypto.Address `json:"address"`
|
||||
Coins sdk.Coins `json:"coins"`
|
||||
}
|
||||
|
||||
func NewGenesisAccount(aa *AppAccount) *GenesisAccount {
|
||||
return &GenesisAccount{
|
||||
Name: aa.Name,
|
||||
Address: aa.Address,
|
||||
Coins: aa.Coins,
|
||||
}
|
||||
}
|
||||
|
||||
// convert GenesisAccount to AppAccount
|
||||
func (ga *GenesisAccount) ToAppAccount() (acc *AppAccount, err error) {
|
||||
baseAcc := auth.BaseAccount{
|
||||
Address: ga.Address,
|
||||
Coins: ga.Coins,
|
||||
}
|
||||
return &AppAccount{
|
||||
BaseAccount: baseAcc,
|
||||
Name: ga.Name,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ import (
|
|||
|
||||
"github.com/tendermint/abci/server"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
dbm "github.com/tendermint/tmlibs/db"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
||||
bam "github.com/cosmos/cosmos-sdk/baseapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
@ -13,11 +15,19 @@ import (
|
|||
|
||||
func main() {
|
||||
|
||||
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "main")
|
||||
|
||||
db, err := dbm.NewGoLevelDB("basecoind", "data")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Capabilities key to access the main KVStore.
|
||||
var capKeyMainStore = sdk.NewKVStoreKey("main")
|
||||
|
||||
// Create BaseApp.
|
||||
var baseApp = bam.NewBaseApp("dummy")
|
||||
var baseApp = bam.NewBaseApp("dummy", logger, db)
|
||||
|
||||
// Set mounts for BaseApp's MultiStore.
|
||||
baseApp.MountStore(capKeyMainStore, sdk.StoreTypeIAVL)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
hash: 2b4ad3bf1489a7cb5e62c6cb4c1fa976d4ae21993743e4968418c4e81925fb99
|
||||
updated: 2018-02-13T08:33:22.402132782-05:00
|
||||
hash: 4d523b19f5b2f54caca37e196582c85d459fdfa5d5383d7e97ee81639b46129d
|
||||
updated: 2018-02-16T19:52:42.711474619-05:00
|
||||
imports:
|
||||
- name: github.com/btcsuite/btcd
|
||||
version: 50de9da05b50eb15658bb350f6ea24368a111ab7
|
||||
|
@ -82,7 +82,7 @@ imports:
|
|||
- name: github.com/spf13/viper
|
||||
version: 25b30aa063fc18e48662b86996252eabdcf2f0c7
|
||||
- name: github.com/syndtr/goleveldb
|
||||
version: 211f780988068502fe874c44dae530528ebd840f
|
||||
version: 34011bf325bce385408353a30b101fe5e923eb6e
|
||||
subpackages:
|
||||
- leveldb
|
||||
- leveldb/cache
|
||||
|
@ -97,7 +97,7 @@ imports:
|
|||
- leveldb/table
|
||||
- leveldb/util
|
||||
- name: github.com/tendermint/abci
|
||||
version: bf70f5e273bd7dd6e22e64186cd1ccc4e3a03df1
|
||||
version: a6be687088a7158e9e431931c3769d6706f90c4c
|
||||
subpackages:
|
||||
- server
|
||||
- types
|
||||
|
@ -113,7 +113,7 @@ imports:
|
|||
- name: github.com/tendermint/iavl
|
||||
version: 1a59ec0c82dc940c25339dd7c834df5cb76a95cb
|
||||
- name: github.com/tendermint/tmlibs
|
||||
version: c858b3ba78316fdd9096a11409a7e7a493e7d974
|
||||
version: a0f652dc2e131be86fc8d9e4e2beec9831a8a6ec
|
||||
subpackages:
|
||||
- cli
|
||||
- common
|
||||
|
|
|
@ -8,7 +8,7 @@ import:
|
|||
version: ^0.8.0
|
||||
- package: github.com/rigelrozanski/common
|
||||
- package: github.com/tendermint/abci
|
||||
version: develop
|
||||
version: feature/init-chain-app-state
|
||||
subpackages:
|
||||
- server
|
||||
- types
|
||||
|
|
|
@ -19,7 +19,6 @@ const (
|
|||
|
||||
func LoadIAVLStore(db dbm.DB, id CommitID) (CommitStore, error) {
|
||||
tree := iavl.NewVersionedTree(db, defaultIAVLCacheSize)
|
||||
fmt.Println("LoadIAVLStore Version ", id.Version)
|
||||
err := tree.LoadVersion(id.Version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -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
|
|
@ -61,7 +61,8 @@ type CommitMultiStore interface {
|
|||
Committer
|
||||
MultiStore
|
||||
|
||||
// Mount a store of type.
|
||||
// Mount a store of type using the given db.
|
||||
// If db == nil, the new store will use the CommitMultiStore db.
|
||||
MountStoreWithDB(key StoreKey, typ StoreType, db dbm.DB)
|
||||
|
||||
// Panics on a nil key.
|
||||
|
|
|
@ -49,15 +49,23 @@ type Tx interface {
|
|||
|
||||
var _ Tx = (*StdTx)(nil)
|
||||
|
||||
// standard transaction form
|
||||
// StdTx is a standard way to wrap a Msg with Signatures.
|
||||
// NOTE: the first signature is the FeePayer (Signatures must not be nil).
|
||||
type StdTx struct {
|
||||
Msg
|
||||
Signatures []StdSignature
|
||||
}
|
||||
|
||||
func NewStdTx(msg Msg, sigs []StdSignature) StdTx {
|
||||
return StdTx{
|
||||
Msg: msg,
|
||||
Signatures: sigs,
|
||||
}
|
||||
}
|
||||
|
||||
//nolint
|
||||
func (tx StdTx) GetMsg() Msg { return tx.Msg }
|
||||
func (tx StdTx) GetFeePayer() crypto.Address { return tx.Signatures[0].PubKey.Address() }
|
||||
func (tx StdTx) GetFeePayer() crypto.Address { return tx.Signatures[0].PubKey.Address() } // XXX but PubKey is optional!
|
||||
func (tx StdTx) GetSignatures() []StdSignature { return tx.Signatures }
|
||||
|
||||
//-------------------------------------
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package auth
|
||||
|
||||
import (
|
||||
bam "github.com/cosmos/cosmos-sdk/baseapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
|
@ -25,20 +24,16 @@ 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.
|
||||
}
|
||||
|
||||
var sigs = tx.GetSignatures()
|
||||
|
||||
// Assert that there are signatures.
|
||||
if !bam.IsTestAppTx(tx) {
|
||||
if len(sigs) == 0 {
|
||||
return ctx,
|
||||
sdk.ErrUnauthorized("no signers").Result(),
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that sigs are correct.
|
||||
var msg = tx.GetMsg()
|
||||
|
@ -46,7 +41,6 @@ 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 len(sigs) != len(signerAddrs) {
|
||||
return ctx,
|
||||
sdk.ErrUnauthorized("wrong number of signers").Result(),
|
||||
|
@ -89,7 +83,6 @@ func NewAnteHandler(accountMapper sdk.AccountMapper) sdk.AnteHandler {
|
|||
// Save the account.
|
||||
accountMapper.SetAccount(ctx, signerAcc)
|
||||
}
|
||||
}
|
||||
|
||||
ctx = WithSigners(ctx, signerAccs)
|
||||
return ctx, sdk.Result{}, false // continue...
|
||||
|
|
|
@ -36,6 +36,20 @@ func NewAccountMapper(key sdk.StoreKey, proto sdk.Account) accountMapper {
|
|||
}
|
||||
}
|
||||
|
||||
// Create and return a sealed account mapper
|
||||
func NewAccountMapperSealed(key sdk.StoreKey, proto sdk.Account) sealedAccountMapper {
|
||||
cdc := wire.NewCodec()
|
||||
am := accountMapper{
|
||||
key: key,
|
||||
proto: proto,
|
||||
cdc: cdc,
|
||||
}
|
||||
RegisterWireBaseAccount(cdc)
|
||||
|
||||
// make accountMapper's WireCodec() inaccessible, return
|
||||
return am.Seal()
|
||||
}
|
||||
|
||||
// Returns the go-wire codec. You may need to register interfaces
|
||||
// and concrete types here, if your app's sdk.Account
|
||||
// implementation includes interface fields.
|
||||
|
|
Loading…
Reference in New Issue