Add first Basecoin test harness
This commit is contained in:
@@ -6,6 +6,8 @@ build
|
||||
docs/guide/*.sh
|
||||
tools/bin/*
|
||||
examples/build/*
|
||||
examples/basecoin/glide.lock
|
||||
examples/basecoin/app/data
|
||||
baseapp/data/*
|
||||
|
||||
### Vagrant ###
|
||||
|
||||
@@ -56,6 +56,7 @@ TUTORIALS=$(shell find docs/guide -name "*md" -type f)
|
||||
test: test_unit # test_cli
|
||||
|
||||
test_unit:
|
||||
@rm -rf examples/basecoin/vendor/
|
||||
@go test $(PACKAGES)
|
||||
|
||||
test_cover:
|
||||
|
||||
+47
-53
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime/debug"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/pkg/errors"
|
||||
@@ -29,7 +30,7 @@ type BaseApp struct {
|
||||
db dbm.DB
|
||||
|
||||
// Main (uncached) state
|
||||
ms sdk.CommitMultiStore
|
||||
cms sdk.CommitMultiStore
|
||||
|
||||
// Unmarshal []byte into sdk.Tx
|
||||
txDecoder sdk.TxDecoder
|
||||
@@ -43,10 +44,10 @@ type BaseApp struct {
|
||||
//--------------------
|
||||
// Volatile
|
||||
|
||||
// CheckTx state, a cache-wrap of `.ms`.
|
||||
// CheckTx state, a cache-wrap of `.cms`.
|
||||
msCheck sdk.CacheMultiStore
|
||||
|
||||
// DeliverTx state, a cache-wrap of `.ms`.
|
||||
// DeliverTx state, a cache-wrap of `.cms`.
|
||||
msDeliver sdk.CacheMultiStore
|
||||
|
||||
// Current block header
|
||||
@@ -63,7 +64,7 @@ func NewBaseApp(name string) *BaseApp {
|
||||
logger: makeDefaultLogger(),
|
||||
name: name,
|
||||
db: nil,
|
||||
ms: nil,
|
||||
cms: nil,
|
||||
router: NewRouter(),
|
||||
}
|
||||
baseapp.initDB()
|
||||
@@ -83,8 +84,8 @@ func (app *BaseApp) initDB() {
|
||||
}
|
||||
|
||||
func (app *BaseApp) initMultiStore() {
|
||||
ms := store.NewCommitMultiStore(app.db)
|
||||
app.ms = ms
|
||||
cms := store.NewCommitMultiStore(app.db)
|
||||
app.cms = cms
|
||||
}
|
||||
|
||||
func (app *BaseApp) Name() string {
|
||||
@@ -92,37 +93,17 @@ func (app *BaseApp) Name() string {
|
||||
}
|
||||
|
||||
func (app *BaseApp) MountStore(key sdk.StoreKey, typ sdk.StoreType) {
|
||||
app.ms.MountStoreWithDB(key, typ, app.db)
|
||||
}
|
||||
|
||||
func (app *BaseApp) TxDecoder() sdk.TxDecoder {
|
||||
return app.txDecoder
|
||||
app.cms.MountStoreWithDB(key, typ, app.db)
|
||||
}
|
||||
|
||||
func (app *BaseApp) SetTxDecoder(txDecoder sdk.TxDecoder) {
|
||||
app.txDecoder = txDecoder
|
||||
}
|
||||
|
||||
func (app *BaseApp) DefaultAnteHandler() sdk.AnteHandler {
|
||||
return app.defaultAnteHandler
|
||||
}
|
||||
|
||||
func (app *BaseApp) SetDefaultAnteHandler(ah sdk.AnteHandler) {
|
||||
app.defaultAnteHandler = ah
|
||||
}
|
||||
|
||||
func (app *BaseApp) MultiStore() sdk.MultiStore {
|
||||
return app.ms
|
||||
}
|
||||
|
||||
func (app *BaseApp) MultiStoreCheck() sdk.MultiStore {
|
||||
return app.msCheck
|
||||
}
|
||||
|
||||
func (app *BaseApp) MultiStoreDeliver() sdk.MultiStore {
|
||||
return app.msDeliver
|
||||
}
|
||||
|
||||
func (app *BaseApp) Router() Router {
|
||||
return app.router
|
||||
}
|
||||
@@ -134,29 +115,29 @@ func (app *BaseApp) SetInitStater(...) {}
|
||||
*/
|
||||
|
||||
func (app *BaseApp) LoadLatestVersion(mainKey sdk.StoreKey) error {
|
||||
app.ms.LoadLatestVersion()
|
||||
app.cms.LoadLatestVersion()
|
||||
return app.initFromStore(mainKey)
|
||||
}
|
||||
|
||||
func (app *BaseApp) LoadVersion(version int64, mainKey sdk.StoreKey) error {
|
||||
app.ms.LoadVersion(version)
|
||||
app.cms.LoadVersion(version)
|
||||
return app.initFromStore(mainKey)
|
||||
}
|
||||
|
||||
// The last CommitID of the multistore.
|
||||
func (app *BaseApp) LastCommitID() sdk.CommitID {
|
||||
return app.ms.LastCommitID()
|
||||
return app.cms.LastCommitID()
|
||||
}
|
||||
|
||||
// The last commited block height.
|
||||
func (app *BaseApp) LastBlockHeight() int64 {
|
||||
return app.ms.LastCommitID().Version
|
||||
return app.cms.LastCommitID().Version
|
||||
}
|
||||
|
||||
// Initializes the remaining logic from app.ms.
|
||||
// Initializes the remaining logic from app.cms.
|
||||
func (app *BaseApp) initFromStore(mainKey sdk.StoreKey) error {
|
||||
var lastCommitID = app.ms.LastCommitID()
|
||||
var main = app.ms.GetKVStore(mainKey)
|
||||
var lastCommitID = app.cms.LastCommitID()
|
||||
var main = app.cms.GetKVStore(mainKey)
|
||||
var header *abci.Header
|
||||
|
||||
// Main store should exist.
|
||||
@@ -196,7 +177,7 @@ func (app *BaseApp) initFromStore(mainKey sdk.StoreKey) error {
|
||||
// Implements ABCI.
|
||||
func (app *BaseApp) Info(req abci.RequestInfo) abci.ResponseInfo {
|
||||
|
||||
lastCommitID := app.ms.LastCommitID()
|
||||
lastCommitID := app.cms.LastCommitID()
|
||||
|
||||
return abci.ResponseInfo{
|
||||
Data: app.name,
|
||||
@@ -227,8 +208,8 @@ func (app *BaseApp) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
|
||||
func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeginBlock) {
|
||||
// NOTE: For consistency we should unset these upon EndBlock.
|
||||
app.header = &req.Header
|
||||
app.msDeliver = app.ms.CacheMultiStore()
|
||||
app.msCheck = app.ms.CacheMultiStore()
|
||||
app.msDeliver = app.cms.CacheMultiStore()
|
||||
app.msCheck = app.cms.CacheMultiStore()
|
||||
app.valUpdates = nil
|
||||
return
|
||||
}
|
||||
@@ -236,7 +217,14 @@ func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeg
|
||||
// Implements ABCI.
|
||||
func (app *BaseApp) CheckTx(txBytes []byte) (res abci.ResponseCheckTx) {
|
||||
|
||||
result := app.runTx(true, txBytes)
|
||||
// Decode the Tx.
|
||||
var result sdk.Result
|
||||
var tx, err = app.txDecoder(txBytes)
|
||||
if err != nil {
|
||||
result = err.Result()
|
||||
} else {
|
||||
result = app.runTx(true, txBytes, tx)
|
||||
}
|
||||
|
||||
return abci.ResponseCheckTx{
|
||||
Code: result.Code,
|
||||
@@ -255,7 +243,14 @@ func (app *BaseApp) CheckTx(txBytes []byte) (res abci.ResponseCheckTx) {
|
||||
// Implements ABCI.
|
||||
func (app *BaseApp) DeliverTx(txBytes []byte) (res abci.ResponseDeliverTx) {
|
||||
|
||||
result := app.runTx(false, txBytes)
|
||||
// Decode the Tx.
|
||||
var result sdk.Result
|
||||
var tx, err = app.txDecoder(txBytes)
|
||||
if err != nil {
|
||||
result = err.Result()
|
||||
} else {
|
||||
result = app.runTx(false, txBytes, tx)
|
||||
}
|
||||
|
||||
// After-handler hooks.
|
||||
if result.Code == abci.CodeTypeOK {
|
||||
@@ -277,29 +272,28 @@ func (app *BaseApp) DeliverTx(txBytes []byte) (res abci.ResponseDeliverTx) {
|
||||
}
|
||||
}
|
||||
|
||||
func (app *BaseApp) runTx(isCheckTx bool, txBytes []byte) (result sdk.Result) {
|
||||
// txBytes may be nil in some cases, for example, when tx is
|
||||
// coming from TestApp. 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.
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
result = sdk.Result{
|
||||
Code: 1, // TODO
|
||||
Log: fmt.Sprintf("Recovered: %v\n", r),
|
||||
}
|
||||
log := fmt.Sprintf("Recovered: %v\nstack:\n%v", r, string(debug.Stack()))
|
||||
result = sdk.ErrInternal(log).Result()
|
||||
}
|
||||
}()
|
||||
|
||||
// Construct a Context.
|
||||
var ctx = app.NewContext(isCheckTx, txBytes)
|
||||
|
||||
// Decode the Tx.
|
||||
tx, err := app.txDecoder(txBytes)
|
||||
// Validate the Tx.Msg.
|
||||
err := tx.ValidateBasic()
|
||||
if err != nil {
|
||||
return sdk.Result{
|
||||
Code: 1, // TODO
|
||||
}
|
||||
return err.Result()
|
||||
}
|
||||
|
||||
// Construct a Context.
|
||||
var ctx = app.newContext(isCheckTx, txBytes)
|
||||
|
||||
// TODO: override default ante handler w/ custom ante handler.
|
||||
|
||||
// Run the ante handler.
|
||||
@@ -329,7 +323,7 @@ func (app *BaseApp) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBloc
|
||||
// Implements ABCI.
|
||||
func (app *BaseApp) Commit() (res abci.ResponseCommit) {
|
||||
app.msDeliver.Write()
|
||||
commitID := app.ms.Commit()
|
||||
commitID := app.cms.Commit()
|
||||
app.logger.Debug("Commit synced",
|
||||
"commit", commitID,
|
||||
)
|
||||
|
||||
+13
-13
@@ -17,28 +17,28 @@ import (
|
||||
)
|
||||
|
||||
// A mock transaction to update a validator's voting power.
|
||||
type testTx struct {
|
||||
type testUpdatePowerTx struct {
|
||||
Addr []byte
|
||||
NewPower int64
|
||||
}
|
||||
|
||||
const txType = "testTx"
|
||||
const txType = "testUpdatePowerTx"
|
||||
|
||||
func (tx testTx) Type() string { return txType }
|
||||
func (tx testTx) Get(key interface{}) (value interface{}) { return nil }
|
||||
func (tx testTx) GetSignBytes() []byte { return nil }
|
||||
func (tx testTx) ValidateBasic() error { return nil }
|
||||
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 (tx testUpdatePowerTx) Type() string { return txType }
|
||||
func (tx testUpdatePowerTx) Get(key interface{}) (value interface{}) { return nil }
|
||||
func (tx testUpdatePowerTx) GetSignBytes() []byte { return nil }
|
||||
func (tx testUpdatePowerTx) ValidateBasic() sdk.Error { return nil }
|
||||
func (tx testUpdatePowerTx) GetSigners() []crypto.Address { return nil }
|
||||
func (tx testUpdatePowerTx) GetFeePayer() crypto.Address { return nil }
|
||||
func (tx testUpdatePowerTx) GetSignatures() []sdk.StdSignature { return nil }
|
||||
|
||||
func TestBasic(t *testing.T) {
|
||||
|
||||
// Create app.
|
||||
app := NewBaseApp(t.Name())
|
||||
storeKeys := createMounts(app.ms)
|
||||
app.SetTxDecoder(func(txBytes []byte) (sdk.Tx, error) {
|
||||
var ttx testTx
|
||||
storeKeys := createMounts(app.cms)
|
||||
app.SetTxDecoder(func(txBytes []byte) (sdk.Tx, sdk.Error) {
|
||||
var ttx testUpdatePowerTx
|
||||
fromJSON(txBytes, &ttx)
|
||||
return ttx, nil
|
||||
})
|
||||
@@ -71,7 +71,7 @@ func TestBasic(t *testing.T) {
|
||||
|
||||
// Add 1 to each validator's voting power.
|
||||
for i, val := range valSet {
|
||||
tx := testTx{
|
||||
tx := testUpdatePowerTx{
|
||||
Addr: makePubKey(secret(i)).Address(),
|
||||
NewPower: val.Power + 1,
|
||||
}
|
||||
|
||||
+3
-2
@@ -2,9 +2,10 @@ package baseapp
|
||||
|
||||
import sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
// NOTE: Unstable.
|
||||
// Returns a new Context suitable for AnteHandler (and indirectly Handler) processing.
|
||||
func (app *BaseApp) NewContext(isCheckTx bool, txBytes []byte) sdk.Context {
|
||||
// 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
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
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
|
||||
}
|
||||
|
||||
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()")
|
||||
}
|
||||
}
|
||||
|
||||
func (tapp *TestApp) RunCheckTx(tx sdk.Tx) sdk.Result {
|
||||
tapp.ensureBeginBlock()
|
||||
return tapp.BaseApp.runTx(true, nil, tx)
|
||||
}
|
||||
|
||||
func (tapp *TestApp) RunDeliverTx(tx sdk.Tx) sdk.Result {
|
||||
tapp.ensureBeginBlock()
|
||||
return tapp.BaseApp.runTx(true, nil, tx)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// NOTE: Skips authentication by wrapping msg in testTx{}.
|
||||
func (tapp *TestApp) RunDeliverMsg(msg sdk.Msg) sdk.Result {
|
||||
var tx = testTx{msg}
|
||||
return tapp.RunCheckTx(tx)
|
||||
}
|
||||
|
||||
func (tapp *TestApp) CommitMultiStore() sdk.CommitMultiStore {
|
||||
return tapp.BaseApp.cms
|
||||
}
|
||||
|
||||
func (tapp *TestApp) MultiStoreCheck() sdk.MultiStore {
|
||||
return tapp.BaseApp.msCheck
|
||||
}
|
||||
|
||||
func (tapp *TestApp) MultiStoreDeliver() sdk.MultiStore {
|
||||
return tapp.BaseApp.msDeliver
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
// testTx
|
||||
|
||||
type testTx struct {
|
||||
sdk.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
|
||||
}
|
||||
@@ -2,6 +2,8 @@
|
||||
*.swo
|
||||
vendor
|
||||
build
|
||||
app/data
|
||||
|
||||
|
||||
### Vagrant ###
|
||||
.vagrant/
|
||||
|
||||
@@ -31,10 +31,10 @@ func NewBasecoinApp() *BasecoinApp {
|
||||
|
||||
// Create and configure app.
|
||||
var app = &BasecoinApp{}
|
||||
app.initCapKeys() // ./init_capkeys.go
|
||||
app.initBaseApp() // ./init_baseapp.go
|
||||
app.initStores() // ./init_stores.go
|
||||
app.initRoutes() // ./init_routes.go
|
||||
app.initCapKeys() // ./init_capkeys.go
|
||||
app.initBaseApp() // ./init_baseapp.go
|
||||
app.initStores() // ./init_stores.go
|
||||
app.initHandlers() // ./init_handlers.go
|
||||
|
||||
// TODO: Load genesis
|
||||
// TODO: InitChain with validators
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
"github.com/stretchr/testify/assert"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
func TestSendMsg(t *testing.T) {
|
||||
tba := newTestBasecoinApp()
|
||||
tba.RunBeginBlock()
|
||||
|
||||
// Construct a SendMsg.
|
||||
var msg = bank.SendMsg{
|
||||
Inputs: []bank.Input{
|
||||
{
|
||||
Address: crypto.Address([]byte("input")),
|
||||
Coins: sdk.Coins{{"atom", 10}},
|
||||
Sequence: 1,
|
||||
},
|
||||
},
|
||||
Outputs: []bank.Output{
|
||||
{
|
||||
Address: crypto.Address([]byte("output")),
|
||||
Coins: sdk.Coins{{"atom", 10}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Run a SendMsg.
|
||||
res := tba.RunCheckMsg(msg)
|
||||
assert.Equal(t, sdk.CodeOK, res.Code, res.Log)
|
||||
}
|
||||
@@ -3,26 +3,24 @@ package app
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
)
|
||||
|
||||
// initCapKeys, initBaseApp, initStores, initRoutes.
|
||||
// initCapKeys, initBaseApp, initStores, initHandlers.
|
||||
func (app *BasecoinApp) initBaseApp() {
|
||||
app.BaseApp = baseapp.NewBaseApp(appName)
|
||||
app.initBaseAppTxDecoder()
|
||||
app.initBaseAppAnteHandler()
|
||||
}
|
||||
|
||||
func (app *BasecoinApp) initBaseAppTxDecoder() {
|
||||
cdc := makeTxCodec()
|
||||
app.BaseApp.SetTxDecoder(func(txBytes []byte) (sdk.Tx, error) {
|
||||
var 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)
|
||||
return tx, err
|
||||
if err != nil {
|
||||
return nil, sdk.ErrTxParse("").TraceCause(err, "")
|
||||
}
|
||||
return tx, nil
|
||||
})
|
||||
}
|
||||
|
||||
func (app *BasecoinApp) initBaseAppAnteHandler() {
|
||||
var authAnteHandler = auth.NewAnteHandler(app.accountMapper)
|
||||
app.BaseApp.SetDefaultAnteHandler(authAnteHandler)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// initCapKeys, initBaseApp, initStores, initRoutes.
|
||||
// initCapKeys, initBaseApp, initStores, initHandlers.
|
||||
func (app *BasecoinApp) initCapKeys() {
|
||||
|
||||
// All top-level capabilities keys
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
)
|
||||
|
||||
// initCapKeys, initBaseApp, initStores, initHandlers.
|
||||
func (app *BasecoinApp) initHandlers() {
|
||||
app.initDefaultAnteHandler()
|
||||
app.initRouterHandlers()
|
||||
}
|
||||
|
||||
func (app *BasecoinApp) initDefaultAnteHandler() {
|
||||
var authAnteHandler = auth.NewAnteHandler(app.accountMapper)
|
||||
app.BaseApp.SetDefaultAnteHandler(authAnteHandler)
|
||||
}
|
||||
|
||||
func (app *BasecoinApp) initRouterHandlers() {
|
||||
var router = app.BaseApp.Router()
|
||||
var accountMapper = app.accountMapper
|
||||
|
||||
// All handlers must be added here.
|
||||
// The order matters.
|
||||
router.AddRoute("bank", bank.NewHandler(accountMapper))
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
)
|
||||
|
||||
// initCapKeys, initBaseApp, initStores, initRoutes.
|
||||
func (app *BasecoinApp) initRoutes() {
|
||||
var router = app.BaseApp.Router()
|
||||
var accountMapper = app.accountMapper
|
||||
|
||||
// All handlers must be added here.
|
||||
// The order matters.
|
||||
router.AddRoute("bank", bank.NewHandler(accountMapper))
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
)
|
||||
|
||||
// initCapKeys, initBaseApp, initStores, initRoutes.
|
||||
// initCapKeys, initBaseApp, initStores, initHandlers.
|
||||
func (app *BasecoinApp) initStores() {
|
||||
app.mountStores()
|
||||
app.initAccountMapper()
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
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
|
||||
}
|
||||
Generated
-153
@@ -1,153 +0,0 @@
|
||||
hash: 80794a3459988a7eb794baf7688c71dad4f6c26653d7b707ac0ada93f21e0776
|
||||
updated: 2018-01-23T19:03:56.956668196-08:00
|
||||
imports:
|
||||
- name: github.com/btcsuite/btcd
|
||||
version: 2e60448ffcc6bf78332d1fe590260095f554dd78
|
||||
subpackages:
|
||||
- btcec
|
||||
- name: github.com/cosmos/cosmos-sdk
|
||||
version: 8650fd70c92686a192585e95413915b4302156b7
|
||||
subpackages:
|
||||
- baseapp
|
||||
- examples/basecoin/types
|
||||
- store
|
||||
- types
|
||||
- x/auth
|
||||
- x/bank
|
||||
- name: github.com/davecgh/go-spew
|
||||
version: 04cdfd42973bb9c8589fd6a731800cf222fde1a9
|
||||
subpackages:
|
||||
- spew
|
||||
- name: github.com/go-kit/kit
|
||||
version: e2b298466b32c7cd5579a9b9b07e968fc9d9452c
|
||||
subpackages:
|
||||
- log
|
||||
- log/level
|
||||
- log/term
|
||||
- name: github.com/go-logfmt/logfmt
|
||||
version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5
|
||||
- name: github.com/go-stack/stack
|
||||
version: 817915b46b97fd7bb80e8ab6b69f01a53ac3eebf
|
||||
- name: github.com/gogo/protobuf
|
||||
version: 342cbe0a04158f6dcb03ca0079991a51a4248c02
|
||||
subpackages:
|
||||
- gogoproto
|
||||
- jsonpb
|
||||
- proto
|
||||
- protoc-gen-gogo/descriptor
|
||||
- sortkeys
|
||||
- types
|
||||
- name: github.com/golang/protobuf
|
||||
version: 1e59b77b52bf8e4b449a57e6f79f21226d571845
|
||||
subpackages:
|
||||
- proto
|
||||
- ptypes
|
||||
- ptypes/any
|
||||
- ptypes/duration
|
||||
- ptypes/timestamp
|
||||
- name: github.com/golang/snappy
|
||||
version: 553a641470496b2327abcac10b36396bd98e45c9
|
||||
- name: github.com/jmhodges/levigo
|
||||
version: c42d9e0ca023e2198120196f842701bb4c55d7b9
|
||||
- name: github.com/kr/logfmt
|
||||
version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0
|
||||
- name: github.com/pkg/errors
|
||||
version: 645ef00459ed84a119197bfb8d8205042c6df63d
|
||||
- name: github.com/rigelrozanski/common
|
||||
version: f691f115798593d783b9999b1263c2f4ffecc439
|
||||
- name: github.com/syndtr/goleveldb
|
||||
version: b89cc31ef7977104127d34c1bd31ebd1a9db2199
|
||||
subpackages:
|
||||
- leveldb
|
||||
- leveldb/cache
|
||||
- leveldb/comparer
|
||||
- leveldb/errors
|
||||
- leveldb/filter
|
||||
- leveldb/iterator
|
||||
- leveldb/journal
|
||||
- leveldb/memdb
|
||||
- leveldb/opt
|
||||
- leveldb/storage
|
||||
- leveldb/table
|
||||
- leveldb/util
|
||||
- name: github.com/tendermint/abci
|
||||
version: 4243954d8d940f9ee0646a83d48ea7a1a907529e
|
||||
subpackages:
|
||||
- server
|
||||
- types
|
||||
- name: github.com/tendermint/ed25519
|
||||
version: d8387025d2b9d158cf4efb07e7ebf814bcce2057
|
||||
subpackages:
|
||||
- edwards25519
|
||||
- extra25519
|
||||
- name: github.com/tendermint/go-crypto
|
||||
version: 12142af1cb4e3479ea4ac98a3171debff87519c6
|
||||
subpackages:
|
||||
- keys
|
||||
- name: github.com/tendermint/go-wire
|
||||
version: c7801c1586f51bb28028cd420c599516d7ac9c36
|
||||
subpackages:
|
||||
- data
|
||||
- name: github.com/tendermint/iavl
|
||||
version: ae2ea4a62f60c72dae81ca6642944ca28cf59889
|
||||
- name: github.com/tendermint/tmlibs
|
||||
version: 80029abc6e20f85079cd751e659a05508773288c
|
||||
subpackages:
|
||||
- cli
|
||||
- cli/flags
|
||||
- common
|
||||
- db
|
||||
- events
|
||||
- log
|
||||
- logger
|
||||
- merkle
|
||||
- name: golang.org/x/crypto
|
||||
version: edd5e9b0879d13ee6970a50153d85b8fec9f7686
|
||||
subpackages:
|
||||
- nacl/secretbox
|
||||
- openpgp/armor
|
||||
- openpgp/errors
|
||||
- poly1305
|
||||
- ripemd160
|
||||
- salsa20/salsa
|
||||
- name: golang.org/x/net
|
||||
version: 5ccada7d0a7ba9aeb5d3aca8d3501b4c2a509fec
|
||||
subpackages:
|
||||
- context
|
||||
- http2
|
||||
- http2/hpack
|
||||
- idna
|
||||
- internal/timeseries
|
||||
- lex/httplex
|
||||
- trace
|
||||
- name: golang.org/x/text
|
||||
version: c01e4764d870b77f8abe5096ee19ad20d80e8075
|
||||
subpackages:
|
||||
- secure/bidirule
|
||||
- transform
|
||||
- unicode/bidi
|
||||
- unicode/norm
|
||||
- name: google.golang.org/genproto
|
||||
version: a8101f21cf983e773d0c1133ebc5424792003214
|
||||
subpackages:
|
||||
- googleapis/rpc/status
|
||||
- name: google.golang.org/grpc
|
||||
version: 401e0e00e4bb830a10496d64cd95e068c5bf50de
|
||||
subpackages:
|
||||
- balancer
|
||||
- codes
|
||||
- connectivity
|
||||
- credentials
|
||||
- grpclb/grpc_lb_v1/messages
|
||||
- grpclog
|
||||
- internal
|
||||
- keepalive
|
||||
- metadata
|
||||
- naming
|
||||
- peer
|
||||
- resolver
|
||||
- stats
|
||||
- status
|
||||
- tap
|
||||
- transport
|
||||
testImports: []
|
||||
@@ -2,7 +2,6 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
@@ -36,7 +35,7 @@ func (tx dummyTx) GetSignBytes() []byte {
|
||||
}
|
||||
|
||||
// Should the app be calling this? Or only handlers?
|
||||
func (tx dummyTx) ValidateBasic() error {
|
||||
func (tx dummyTx) ValidateBasic() sdk.Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -52,7 +51,7 @@ func (tx dummyTx) GetFeePayer() crypto.Address {
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeTx(txBytes []byte) (sdk.Tx, error) {
|
||||
func decodeTx(txBytes []byte) (sdk.Tx, sdk.Error) {
|
||||
var tx sdk.Tx
|
||||
|
||||
split := bytes.Split(txBytes, []byte("="))
|
||||
@@ -63,7 +62,7 @@ func decodeTx(txBytes []byte) (sdk.Tx, error) {
|
||||
k, v := split[0], split[1]
|
||||
tx = dummyTx{k, v, txBytes}
|
||||
} else {
|
||||
return nil, fmt.Errorf("too many =")
|
||||
return nil, sdk.ErrTxParse("too many =")
|
||||
}
|
||||
|
||||
return tx, nil
|
||||
|
||||
@@ -10,16 +10,14 @@ import (
|
||||
// cacheMultiStore holds many cache-wrapped stores.
|
||||
// Implements MultiStore.
|
||||
type cacheMultiStore struct {
|
||||
db CacheKVStore
|
||||
lastCommitID CommitID
|
||||
stores map[StoreKey]CacheWrap
|
||||
db CacheKVStore
|
||||
stores map[StoreKey]CacheWrap
|
||||
}
|
||||
|
||||
func newCacheMultiStoreFromRMS(rms *rootMultiStore) cacheMultiStore {
|
||||
cms := cacheMultiStore{
|
||||
db: NewCacheKVStore(dbStoreAdapter{rms.db}),
|
||||
lastCommitID: rms.lastCommitID,
|
||||
stores: make(map[StoreKey]CacheWrap, len(rms.stores)),
|
||||
db: NewCacheKVStore(dbStoreAdapter{rms.db}),
|
||||
stores: make(map[StoreKey]CacheWrap, len(rms.stores)),
|
||||
}
|
||||
for key, store := range rms.stores {
|
||||
cms.stores[key] = store.CacheWrap()
|
||||
@@ -29,9 +27,8 @@ func newCacheMultiStoreFromRMS(rms *rootMultiStore) cacheMultiStore {
|
||||
|
||||
func newCacheMultiStoreFromCMS(cms cacheMultiStore) cacheMultiStore {
|
||||
cms2 := cacheMultiStore{
|
||||
db: NewCacheKVStore(cms.db),
|
||||
lastCommitID: cms.lastCommitID,
|
||||
stores: make(map[StoreKey]CacheWrap, len(cms.stores)),
|
||||
db: NewCacheKVStore(cms.db),
|
||||
stores: make(map[StoreKey]CacheWrap, len(cms.stores)),
|
||||
}
|
||||
for key, store := range cms.stores {
|
||||
cms2.stores[key] = store.CacheWrap()
|
||||
@@ -44,11 +41,6 @@ func (cms cacheMultiStore) GetStoreType() StoreType {
|
||||
return sdk.StoreTypeMulti
|
||||
}
|
||||
|
||||
// Implements MultiStore.
|
||||
func (cms cacheMultiStore) LastCommitID() CommitID {
|
||||
return cms.lastCommitID
|
||||
}
|
||||
|
||||
// Implements CacheMultiStore.
|
||||
func (cms cacheMultiStore) Write() {
|
||||
cms.db.Write()
|
||||
|
||||
@@ -119,7 +119,12 @@ func (rs *rootMultiStore) LoadVersion(ver int64) error {
|
||||
//----------------------------------------
|
||||
// +CommitStore
|
||||
|
||||
// Implements CommitStore.
|
||||
// Implements Committer/CommitStore.
|
||||
func (rs *rootMultiStore) LastCommitID() CommitID {
|
||||
return rs.lastCommitID
|
||||
}
|
||||
|
||||
// Implements Committer/CommitStore.
|
||||
func (rs *rootMultiStore) Commit() CommitID {
|
||||
|
||||
// Commit stores.
|
||||
@@ -141,7 +146,7 @@ func (rs *rootMultiStore) Commit() CommitID {
|
||||
return commitID
|
||||
}
|
||||
|
||||
// Implements CommitStore.
|
||||
// Implements CacheWrapper/Store/CommitStore.
|
||||
func (rs *rootMultiStore) CacheWrap() CacheWrap {
|
||||
return rs.CacheMultiStore().(CacheWrap)
|
||||
}
|
||||
@@ -149,11 +154,6 @@ func (rs *rootMultiStore) CacheWrap() CacheWrap {
|
||||
//----------------------------------------
|
||||
// +MultiStore
|
||||
|
||||
// Implements MultiStore.
|
||||
func (rs *rootMultiStore) LastCommitID() CommitID {
|
||||
return rs.lastCommitID
|
||||
}
|
||||
|
||||
// Implements MultiStore.
|
||||
func (rs *rootMultiStore) CacheMultiStore() CacheMultiStore {
|
||||
return newCacheMultiStoreFromRMS(rs)
|
||||
|
||||
+63
-41
@@ -2,26 +2,29 @@ package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
const (
|
||||
// ABCI Response Codes
|
||||
// Base SDK reserves 0 ~ 99.
|
||||
CodeInternalError uint32 = 1
|
||||
CodeTxParseError = 2
|
||||
CodeOK uint32 = 0
|
||||
CodeInternal = 1
|
||||
CodeTxParse = 2
|
||||
CodeBadNonce = 3
|
||||
CodeUnauthorized = 4
|
||||
CodeInsufficientFunds = 5
|
||||
CodeUnknownRequest = 6
|
||||
CodeUnrecognizedAddress = 7
|
||||
CodeInvalidSequence = 8
|
||||
)
|
||||
|
||||
// NOTE: Don't stringer this, we'll put better messages in later.
|
||||
func CodeToDefaultLog(code uint32) string {
|
||||
func CodeToDefaultMsg(code uint32) string {
|
||||
switch code {
|
||||
case CodeInternalError:
|
||||
case CodeInternal:
|
||||
return "Internal error"
|
||||
case CodeTxParseError:
|
||||
case CodeTxParse:
|
||||
return "Tx parse error"
|
||||
case CodeBadNonce:
|
||||
return "Bad nonce"
|
||||
@@ -33,6 +36,8 @@ func CodeToDefaultLog(code uint32) string {
|
||||
return "Unknown request"
|
||||
case CodeUnrecognizedAddress:
|
||||
return "Unrecognized address"
|
||||
case CodeInvalidSequence:
|
||||
return "Invalid sequence"
|
||||
default:
|
||||
return fmt.Sprintf("Unknown code %d", code)
|
||||
}
|
||||
@@ -42,32 +47,36 @@ func CodeToDefaultLog(code uint32) string {
|
||||
// All errors are created via constructors so as to enable us to hijack them
|
||||
// and inject stack traces if we really want to.
|
||||
|
||||
func ErrInternal(log string) Error {
|
||||
return newError(CodeInternalError, log)
|
||||
func ErrInternal(msg string) Error {
|
||||
return newError(CodeInternal, msg)
|
||||
}
|
||||
|
||||
func ErrTxParse(log string) Error {
|
||||
return newError(CodeTxParseError, log)
|
||||
func ErrTxParse(msg string) Error {
|
||||
return newError(CodeTxParse, msg)
|
||||
}
|
||||
|
||||
func ErrBadNonce(log string) Error {
|
||||
return newError(CodeBadNonce, log)
|
||||
func ErrBadNonce(msg string) Error {
|
||||
return newError(CodeBadNonce, msg)
|
||||
}
|
||||
|
||||
func ErrUnauthorized(log string) Error {
|
||||
return newError(CodeUnauthorized, log)
|
||||
func ErrUnauthorized(msg string) Error {
|
||||
return newError(CodeUnauthorized, msg)
|
||||
}
|
||||
|
||||
func ErrInsufficientFunds(log string) Error {
|
||||
return newError(CodeInsufficientFunds, log)
|
||||
func ErrInsufficientFunds(msg string) Error {
|
||||
return newError(CodeInsufficientFunds, msg)
|
||||
}
|
||||
|
||||
func ErrUnknownRequest(log string) Error {
|
||||
return newError(CodeUnknownRequest, log)
|
||||
func ErrUnknownRequest(msg string) Error {
|
||||
return newError(CodeUnknownRequest, msg)
|
||||
}
|
||||
|
||||
func ErrUnrecognizedAddress(log string) Error {
|
||||
return newError(CodeUnrecognizedAddress, log)
|
||||
func ErrUnrecognizedAddress(msg string) Error {
|
||||
return newError(CodeUnrecognizedAddress, msg)
|
||||
}
|
||||
|
||||
func ErrInvalidSequence(msg string) Error {
|
||||
return newError(CodeInvalidSequence, msg)
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
@@ -83,8 +92,8 @@ type Error interface {
|
||||
Result() Result
|
||||
}
|
||||
|
||||
func NewError(code uint32, log string) Error {
|
||||
return newError(code, log)
|
||||
func NewError(code uint32, msg string) Error {
|
||||
return newError(code, msg)
|
||||
}
|
||||
|
||||
type traceItem struct {
|
||||
@@ -93,21 +102,25 @@ type traceItem struct {
|
||||
lineno int
|
||||
}
|
||||
|
||||
func (ti traceItem) String() string {
|
||||
return fmt.Sprintf("%v:%v %v", ti.filename, ti.lineno, ti.msg)
|
||||
}
|
||||
|
||||
type sdkError struct {
|
||||
code uint32
|
||||
log string
|
||||
msg string
|
||||
cause error
|
||||
trace []traceItem
|
||||
}
|
||||
|
||||
func newError(code uint32, log string) *sdkError {
|
||||
func newError(code uint32, msg string) *sdkError {
|
||||
// TODO capture stacktrace if ENV is set.
|
||||
if log == "" {
|
||||
log = CodeToDefaultLog(code)
|
||||
if msg == "" {
|
||||
msg = CodeToDefaultMsg(code)
|
||||
}
|
||||
return &sdkError{
|
||||
code: code,
|
||||
log: log,
|
||||
msg: msg,
|
||||
cause: nil,
|
||||
trace: nil,
|
||||
}
|
||||
@@ -115,7 +128,7 @@ func newError(code uint32, log string) *sdkError {
|
||||
|
||||
// Implements ABCIError.
|
||||
func (err *sdkError) Error() string {
|
||||
return fmt.Sprintf("Error{%d:%s,%v,%v}", err.code, err.log, err.cause, len(err.trace))
|
||||
return fmt.Sprintf("Error{%d:%s,%v,%v}", err.code, err.msg, err.cause, len(err.trace))
|
||||
}
|
||||
|
||||
// Implements ABCIError.
|
||||
@@ -125,32 +138,41 @@ func (err *sdkError) ABCICode() uint32 {
|
||||
|
||||
// Implements ABCIError.
|
||||
func (err *sdkError) ABCILog() string {
|
||||
return err.log
|
||||
traceLog := ""
|
||||
for _, ti := range err.trace {
|
||||
traceLog += ti.String() + "\n"
|
||||
}
|
||||
return fmt.Sprintf("msg: %v\ntrace:\n%v",
|
||||
err.msg,
|
||||
traceLog,
|
||||
)
|
||||
}
|
||||
|
||||
// Add tracing information to log with msg.
|
||||
// Add tracing information with msg.
|
||||
func (err *sdkError) Trace(msg string) Error {
|
||||
// Include file & line number & msg to log.
|
||||
_, fn, line, ok := runtime.Caller(1)
|
||||
if !ok {
|
||||
if fn == "" {
|
||||
fn = "<unknown>"
|
||||
}
|
||||
if line <= 0 {
|
||||
line = -1
|
||||
}
|
||||
}
|
||||
// Include file & line number & msg.
|
||||
// Do not include the whole stack trace.
|
||||
err.trace = append(err.trace, traceItem{
|
||||
filename: "todo", // TODO
|
||||
lineno: -1, // TODO
|
||||
filename: fn,
|
||||
lineno: line,
|
||||
msg: msg,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// Add tracing information to log with cause and msg.
|
||||
// Add tracing information with cause and msg.
|
||||
func (err *sdkError) TraceCause(cause error, msg string) Error {
|
||||
err.cause = cause
|
||||
// Include file & line number & cause & msg to log.
|
||||
// Do not include the whole stack trace.
|
||||
err.trace = append(err.trace, traceItem{
|
||||
filename: "todo", // TODO
|
||||
lineno: -1, // TODO
|
||||
msg: msg,
|
||||
})
|
||||
return err
|
||||
return err.Trace(msg)
|
||||
}
|
||||
|
||||
func (err *sdkError) Cause() error {
|
||||
|
||||
+2
-2
@@ -18,7 +18,7 @@ type Msg interface {
|
||||
|
||||
// ValidateBasic does a simple validation check that
|
||||
// doesn't require access to any other information.
|
||||
ValidateBasic() error
|
||||
ValidateBasic() Error
|
||||
|
||||
// Signers returns the addrs of signers that must sign.
|
||||
// CONTRACT: All signatures must be present to be valid.
|
||||
@@ -53,4 +53,4 @@ type StdTx struct {
|
||||
func (tx StdTx) GetFeePayer() crypto.Address { return tx.Signatures[0].PubKey.Address() }
|
||||
func (tx StdTx) GetSignatures() []StdSignature { return tx.Signatures }
|
||||
|
||||
type TxDecoder func(txBytes []byte) (Tx, error)
|
||||
type TxDecoder func(txBytes []byte) (Tx, Error)
|
||||
|
||||
+34
-23
@@ -1,6 +1,7 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
bam "github.com/cosmos/cosmos-sdk/baseapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
@@ -13,30 +14,40 @@ func NewAnteHandler(accountMapper sdk.AccountMapper) sdk.AnteHandler {
|
||||
// This is done first because it only
|
||||
// requires fetching 1 account.
|
||||
payerAddr := tx.GetFeePayer()
|
||||
payerAcc := accountMapper.GetAccount(ctx, payerAddr)
|
||||
if payerAcc == nil {
|
||||
return ctx, sdk.Result{
|
||||
Code: 1, // TODO
|
||||
}, true
|
||||
if payerAddr != nil {
|
||||
payerAcc := accountMapper.GetAccount(ctx, payerAddr)
|
||||
if payerAcc == nil {
|
||||
return ctx,
|
||||
sdk.ErrUnrecognizedAddress("").Result(),
|
||||
true
|
||||
}
|
||||
// TODO: Charge fee from payerAcc.
|
||||
// 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.
|
||||
}
|
||||
|
||||
// payerAcc.Subtract ?
|
||||
|
||||
// Ensure that signatures are correct.
|
||||
var signerAddrs = tx.GetSigners()
|
||||
var signerAccs = make([]sdk.Account, len(signerAddrs))
|
||||
var signatures = tx.GetSignatures()
|
||||
|
||||
// Assert that there are signers.
|
||||
if len(signatures) == 0 {
|
||||
return ctx, sdk.Result{
|
||||
Code: 1, // TODO
|
||||
}, true
|
||||
if len(signerAddrs) == 0 {
|
||||
if !bam.IsTestAppTx(tx) {
|
||||
return ctx,
|
||||
sdk.ErrUnauthorized("no signers").Result(),
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
// Assert that number of signatures is correct.
|
||||
if len(signatures) != len(signerAddrs) {
|
||||
return ctx, sdk.Result{
|
||||
Code: 1, // TODO
|
||||
}, true
|
||||
return ctx,
|
||||
sdk.ErrUnauthorized("wrong number of signers").Result(),
|
||||
true
|
||||
}
|
||||
|
||||
// Check each nonce and sig.
|
||||
@@ -49,26 +60,26 @@ func NewAnteHandler(accountMapper sdk.AccountMapper) sdk.AnteHandler {
|
||||
if signerAcc.GetPubKey() == nil {
|
||||
err := signerAcc.SetPubKey(sig.PubKey)
|
||||
if err != nil {
|
||||
return ctx, sdk.Result{
|
||||
Code: 1, // TODO
|
||||
}, true
|
||||
return ctx,
|
||||
sdk.ErrInternal("setting PubKey on signer").Result(),
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
// Check and increment sequence number.
|
||||
seq := signerAcc.GetSequence()
|
||||
if seq != sig.Sequence {
|
||||
return ctx, sdk.Result{
|
||||
Code: 1, // TODO
|
||||
}, true
|
||||
return ctx,
|
||||
sdk.ErrInvalidSequence("").Result(),
|
||||
true
|
||||
}
|
||||
signerAcc.SetSequence(seq + 1)
|
||||
|
||||
// Check sig.
|
||||
if !sig.PubKey.VerifyBytes(tx.GetSignBytes(), sig.Signature) {
|
||||
return ctx, sdk.Result{
|
||||
Code: 1, // TODO
|
||||
}, true
|
||||
return ctx,
|
||||
sdk.ErrUnauthorized("").Result(),
|
||||
true
|
||||
}
|
||||
|
||||
// Save the account.
|
||||
|
||||
+25
-28
@@ -13,12 +13,11 @@ const (
|
||||
CodeUnknownAddress uint32 = 104
|
||||
CodeInsufficientCoins uint32 = 105
|
||||
CodeInvalidCoins uint32 = 106
|
||||
CodeInvalidSequence uint32 = 107
|
||||
CodeUnknownRequest uint32 = sdk.CodeUnknownRequest
|
||||
)
|
||||
|
||||
// NOTE: Don't stringer this, we'll put better messages in later.
|
||||
func codeToDefaultLog(code uint32) string {
|
||||
func codeToDefaultMsg(code uint32) string {
|
||||
switch code {
|
||||
case CodeInvalidInput:
|
||||
return "Invalid input coins"
|
||||
@@ -32,69 +31,67 @@ func codeToDefaultLog(code uint32) string {
|
||||
return "Insufficient coins"
|
||||
case CodeInvalidCoins:
|
||||
return "Invalid coins"
|
||||
case CodeInvalidSequence:
|
||||
return "Invalid sequence"
|
||||
case CodeUnknownRequest:
|
||||
return "Unknown request"
|
||||
default:
|
||||
return sdk.CodeToDefaultLog(code)
|
||||
return sdk.CodeToDefaultMsg(code)
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
// Error constructors
|
||||
|
||||
func ErrInvalidInput(log string) sdk.Error {
|
||||
return newError(CodeInvalidInput, log)
|
||||
func ErrInvalidInput(msg string) sdk.Error {
|
||||
return newError(CodeInvalidInput, msg)
|
||||
}
|
||||
|
||||
func ErrNoInputs() sdk.Error {
|
||||
return newError(CodeInvalidInput, "")
|
||||
}
|
||||
|
||||
func ErrInvalidOutput(log string) sdk.Error {
|
||||
return newError(CodeInvalidOutput, log)
|
||||
func ErrInvalidOutput(msg string) sdk.Error {
|
||||
return newError(CodeInvalidOutput, msg)
|
||||
}
|
||||
|
||||
func ErrNoOutputs() sdk.Error {
|
||||
return newError(CodeInvalidOutput, "")
|
||||
}
|
||||
|
||||
func ErrInvalidSequence(seq int64) sdk.Error {
|
||||
return newError(CodeInvalidSequence, "")
|
||||
func ErrInvalidSequence(msg string) sdk.Error {
|
||||
return sdk.ErrInvalidSequence(msg)
|
||||
}
|
||||
|
||||
func ErrInvalidAddress(log string) sdk.Error {
|
||||
return newError(CodeInvalidAddress, log)
|
||||
func ErrInvalidAddress(msg string) sdk.Error {
|
||||
return newError(CodeInvalidAddress, msg)
|
||||
}
|
||||
|
||||
func ErrUnknownAddress(log string) sdk.Error {
|
||||
return newError(CodeUnknownAddress, log)
|
||||
func ErrUnknownAddress(msg string) sdk.Error {
|
||||
return newError(CodeUnknownAddress, msg)
|
||||
}
|
||||
|
||||
func ErrInsufficientCoins(log string) sdk.Error {
|
||||
return newError(CodeInsufficientCoins, log)
|
||||
func ErrInsufficientCoins(msg string) sdk.Error {
|
||||
return newError(CodeInsufficientCoins, msg)
|
||||
}
|
||||
|
||||
func ErrInvalidCoins(log string) sdk.Error {
|
||||
return newError(CodeInvalidCoins, log)
|
||||
func ErrInvalidCoins(msg string) sdk.Error {
|
||||
return newError(CodeInvalidCoins, msg)
|
||||
}
|
||||
|
||||
func ErrUnknownRequest(log string) sdk.Error {
|
||||
return newError(CodeUnknownRequest, log)
|
||||
func ErrUnknownRequest(msg string) sdk.Error {
|
||||
return newError(CodeUnknownRequest, msg)
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
func logOrDefaultLog(log string, code uint32) string {
|
||||
if log != "" {
|
||||
return log
|
||||
func msgOrDefaultMsg(msg string, code uint32) string {
|
||||
if msg != "" {
|
||||
return msg
|
||||
} else {
|
||||
return codeToDefaultLog(code)
|
||||
return codeToDefaultMsg(code)
|
||||
}
|
||||
}
|
||||
|
||||
func newError(code uint32, log string) sdk.Error {
|
||||
log = logOrDefaultLog(log, code)
|
||||
return sdk.NewError(code, log)
|
||||
func newError(code uint32, msg string) sdk.Error {
|
||||
msg = msgOrDefaultMsg(msg, code)
|
||||
return sdk.NewError(code, msg)
|
||||
}
|
||||
|
||||
+4
-10
@@ -17,10 +17,8 @@ func NewHandler(am sdk.AccountMapper) sdk.Handler {
|
||||
case IssueMsg:
|
||||
return handleIssueMsg(ctx, cm, msg)
|
||||
default:
|
||||
return sdk.Result{
|
||||
Code: 1, // TODO
|
||||
Log: "Unrecognized bank Tx type: " + reflect.TypeOf(tx).Name(),
|
||||
}
|
||||
errMsg := "Unrecognized bank Tx type: " + reflect.TypeOf(tx).Name()
|
||||
return sdk.ErrUnknownRequest(errMsg).Result()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,18 +31,14 @@ func handleSendMsg(ctx sdk.Context, cm CoinMapper, msg SendMsg) sdk.Result {
|
||||
for _, in := range msg.Inputs {
|
||||
_, err := cm.SubtractCoins(ctx, in.Address, in.Coins)
|
||||
if err != nil {
|
||||
return sdk.Result{
|
||||
Code: 1, // TODO
|
||||
}
|
||||
return ErrInvalidInput("").TraceCause(err, "").Result()
|
||||
}
|
||||
}
|
||||
|
||||
for _, out := range msg.Outputs {
|
||||
_, err := cm.AddCoins(ctx, out.Address, out.Coins)
|
||||
if err != nil {
|
||||
return sdk.Result{
|
||||
Code: 1, // TODO
|
||||
}
|
||||
return ErrInvalidOutput("").TraceCause(err, "").Result()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
-19
@@ -6,7 +6,7 @@ import (
|
||||
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// SendMsg - high level transaction of the coin module
|
||||
@@ -24,32 +24,32 @@ func NewSendMsg(in []Input, out []Output) SendMsg {
|
||||
func (msg SendMsg) Type() string { return "bank" } // TODO: "bank/send"
|
||||
|
||||
// Implements Msg.
|
||||
func (msg SendMsg) ValidateBasic() error {
|
||||
func (msg SendMsg) ValidateBasic() sdk.Error {
|
||||
// this just makes sure all the inputs and outputs are properly formatted,
|
||||
// not that they actually have the money inside
|
||||
if len(msg.Inputs) == 0 {
|
||||
return ErrNoInputs()
|
||||
return ErrNoInputs().Trace("")
|
||||
}
|
||||
if len(msg.Outputs) == 0 {
|
||||
return ErrNoOutputs()
|
||||
return ErrNoOutputs().Trace("")
|
||||
}
|
||||
// make sure all inputs and outputs are individually valid
|
||||
var totalIn, totalOut types.Coins
|
||||
var totalIn, totalOut sdk.Coins
|
||||
for _, in := range msg.Inputs {
|
||||
if err := in.ValidateBasic(); err != nil {
|
||||
return err
|
||||
return err.Trace("")
|
||||
}
|
||||
totalIn = totalIn.Plus(in.Coins)
|
||||
}
|
||||
for _, out := range msg.Outputs {
|
||||
if err := out.ValidateBasic(); err != nil {
|
||||
return err
|
||||
return err.Trace("")
|
||||
}
|
||||
totalOut = totalOut.Plus(out.Coins)
|
||||
}
|
||||
// make sure inputs and outputs match
|
||||
if !totalIn.IsEqual(totalOut) {
|
||||
return ErrInvalidCoins(totalIn.String()) // TODO
|
||||
return ErrInvalidCoins(totalIn.String()).Trace("inputs and outputs don't match")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -99,14 +99,14 @@ func NewIssueMsg(banker crypto.Address, out []Output) IssueMsg {
|
||||
func (msg IssueMsg) Type() string { return "bank" } // TODO: "bank/send"
|
||||
|
||||
// Implements Msg.
|
||||
func (msg IssueMsg) ValidateBasic() error {
|
||||
func (msg IssueMsg) ValidateBasic() sdk.Error {
|
||||
// XXX
|
||||
if len(msg.Outputs) == 0 {
|
||||
return ErrNoOutputs()
|
||||
return ErrNoOutputs().Trace("")
|
||||
}
|
||||
for _, out := range msg.Outputs {
|
||||
if err := out.ValidateBasic(); err != nil {
|
||||
return err
|
||||
return err.Trace("")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -140,19 +140,19 @@ func (msg IssueMsg) GetSigners() []crypto.Address {
|
||||
|
||||
type Input struct {
|
||||
Address crypto.Address `json:"address"`
|
||||
Coins types.Coins `json:"coins"`
|
||||
Coins sdk.Coins `json:"coins"`
|
||||
Sequence int64 `json:"sequence"`
|
||||
|
||||
signature crypto.Signature
|
||||
}
|
||||
|
||||
// ValidateBasic - validate transaction input
|
||||
func (in Input) ValidateBasic() error {
|
||||
func (in Input) ValidateBasic() sdk.Error {
|
||||
if len(in.Address) == 0 {
|
||||
return ErrInvalidAddress(in.Address.String())
|
||||
}
|
||||
if in.Sequence < 0 {
|
||||
return ErrInvalidSequence(in.Sequence)
|
||||
return ErrInvalidSequence("negative sequence")
|
||||
}
|
||||
if !in.Coins.IsValid() {
|
||||
return ErrInvalidCoins(in.Coins.String())
|
||||
@@ -168,7 +168,7 @@ func (in Input) String() string {
|
||||
}
|
||||
|
||||
// NewInput - create a transaction input, used with SendMsg
|
||||
func NewInput(addr crypto.Address, coins types.Coins) Input {
|
||||
func NewInput(addr crypto.Address, coins sdk.Coins) Input {
|
||||
input := Input{
|
||||
Address: addr,
|
||||
Coins: coins,
|
||||
@@ -177,7 +177,7 @@ func NewInput(addr crypto.Address, coins types.Coins) Input {
|
||||
}
|
||||
|
||||
// NewInputWithSequence - create a transaction input, used with SendMsg
|
||||
func NewInputWithSequence(addr crypto.Address, coins types.Coins, seq int64) Input {
|
||||
func NewInputWithSequence(addr crypto.Address, coins sdk.Coins, seq int64) Input {
|
||||
input := NewInput(addr, coins)
|
||||
input.Sequence = seq
|
||||
return input
|
||||
@@ -188,11 +188,11 @@ func NewInputWithSequence(addr crypto.Address, coins types.Coins, seq int64) Inp
|
||||
|
||||
type Output struct {
|
||||
Address crypto.Address `json:"address"`
|
||||
Coins types.Coins `json:"coins"`
|
||||
Coins sdk.Coins `json:"coins"`
|
||||
}
|
||||
|
||||
// ValidateBasic - validate transaction output
|
||||
func (out Output) ValidateBasic() error {
|
||||
func (out Output) ValidateBasic() sdk.Error {
|
||||
if len(out.Address) == 0 {
|
||||
return ErrInvalidAddress(out.Address.String())
|
||||
}
|
||||
@@ -210,7 +210,7 @@ func (out Output) String() string {
|
||||
}
|
||||
|
||||
// NewOutput - create a transaction output, used with SendMsg
|
||||
func NewOutput(addr crypto.Address, coins types.Coins) Output {
|
||||
func NewOutput(addr crypto.Address, coins sdk.Coins) Output {
|
||||
output := Output{
|
||||
Address: addr,
|
||||
Coins: coins,
|
||||
|
||||
Reference in New Issue
Block a user