Merge branch 'develop' into fedekunze/2819-fix-tx-search

This commit is contained in:
Federico Kunze 2018-11-20 14:16:38 +01:00 committed by GitHub
commit b7301b5927
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
115 changed files with 2077 additions and 1593 deletions

3
Gopkg.lock generated
View File

@ -165,12 +165,13 @@
version = "v1.2.0"
[[projects]]
digest = "1:ea40c24cdbacd054a6ae9de03e62c5f252479b96c716375aace5c120d68647c8"
digest = "1:c0d19ab64b32ce9fe5cf4ddceba78d5bc9807f0016db6b1183599da3dcc24d10"
name = "github.com/hashicorp/hcl"
packages = [
".",
"hcl/ast",
"hcl/parser",
"hcl/printer",
"hcl/scanner",
"hcl/strconv",
"hcl/token",

View File

@ -32,6 +32,7 @@ FEATURES
* [gov][cli] [\#2479](https://github.com/cosmos/cosmos-sdk/issues/2479) Added governance
parameter query commands.
* [stake][cli] [\#2027] Add CLI query command for getting all delegations to a specific validator.
* [\#2840](https://github.com/cosmos/cosmos-sdk/pull/2840) Standardize CLI exports from modules
* Gaia
* [app] \#2791 Support export at a specific height, with `gaiad export --height=HEIGHT`.
@ -50,16 +51,23 @@ IMPROVEMENTS
* Gaia REST API (`gaiacli advanced rest-server`)
* [gaia-lite] [\#2819](https://github.com/cosmos/cosmos-sdk/pull/2819) Tx search now supports multiple tags as query parameters
* [\#2836](https://github.com/cosmos/cosmos-sdk/pull/2836) Expose LCD router to allow users to register routes there.
* Gaia CLI (`gaiacli`)
* [\#2749](https://github.com/cosmos/cosmos-sdk/pull/2749) Add --chain-id flag to gaiad testnet
* Gaia
- #2773 Require moniker to be provided on `gaiad init`.
- #2672 [Makefile] Updated for better Windows compatibility and ledger support logic, get_tools was rewritten as a cross-compatible Makefile.
- [#110](https://github.com/tendermint/devops/issues/110) Updated CircleCI job to trigger website build when cosmos docs are updated.
- #2772 Update BaseApp to not persist state when the ante handler fails on DeliverTx.
- #2773 Require moniker to be provided on `gaiad init`.
- #2672 [Makefile] Updated for better Windows compatibility and ledger support logic, get_tools was rewritten as a cross-compatible Makefile.
- [#110](https://github.com/tendermint/devops/issues/110) Updated CircleCI job to trigger website build when cosmos docs are updated.
* SDK
- [x/mock/simulation] [\#2720] major cleanup, introduction of helper objects, reorganization
- \#2821 Codespaces are now strings
- [types] #2776 Improve safety of `Coin` and `Coins` types. Various functions
and methods will panic when a negative amount is discovered.
- #2815 Gas unit fields changed from `int64` to `uint64`.
* Tendermint
- #2796 Update to go-amino 0.14.1
@ -78,6 +86,7 @@ BUG FIXES
* SDK
- \#2733 [x/gov, x/mock/simulation] Fix governance simulation, update x/gov import/export
- \#2854 [x/bank] Remove unused bank.MsgIssue, prevent possible panic
* Tendermint
* [\#2797](https://github.com/tendermint/tendermint/pull/2797) AddressBook requires addresses to have IDs; Do not crap out immediately after sending pex addrs in seed mode

View File

@ -10,7 +10,6 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/tmhash"
cmn "github.com/tendermint/tendermint/libs/common"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/libs/log"
@ -47,7 +46,6 @@ type BaseApp struct {
cms sdk.CommitMultiStore // Main (uncached) state
router Router // handle any kind of message
queryRouter QueryRouter // router for redirecting query calls
codespacer *sdk.Codespacer // handle module codespacing
txDecoder sdk.TxDecoder // unmarshal []byte into sdk.Tx
anteHandler sdk.AnteHandler // ante handler for fee and auth
@ -94,13 +92,9 @@ func NewBaseApp(name string, logger log.Logger, db dbm.DB, txDecoder sdk.TxDecod
cms: store.NewCommitMultiStore(db),
router: NewRouter(),
queryRouter: NewQueryRouter(),
codespacer: sdk.NewCodespacer(),
txDecoder: txDecoder,
}
// Register the undefined & root codespaces, which should not be used by
// any modules.
app.codespacer.RegisterOrPanic(sdk.CodespaceRoot)
for _, option := range options {
option(app)
}
@ -118,11 +112,6 @@ func (app *BaseApp) SetCommitMultiStoreTracer(w io.Writer) {
app.cms.WithTracer(w)
}
// Register the next available codespace through the baseapp's codespacer, starting from a default
func (app *BaseApp) RegisterCodespace(codespace sdk.CodespaceType) sdk.CodespaceType {
return app.codespacer.RegisterNext(codespace)
}
// Mount IAVL stores to the provided keys in the BaseApp multistore
func (app *BaseApp) MountStoresIAVL(keys ...*sdk.KVStoreKey) {
for _, key := range keys {
@ -211,6 +200,10 @@ func (st *state) CacheMultiStore() sdk.CacheMultiStore {
return st.ms.CacheMultiStore()
}
func (st *state) Context() sdk.Context {
return st.ctx
}
func (app *BaseApp) setCheckState(header abci.Header) {
ms := app.cms.CacheMultiStore()
app.checkState = &state{
@ -329,8 +322,9 @@ func handleQueryApp(app *BaseApp, path []string, req abci.RequestQuery) (res abc
}
case "version":
return abci.ResponseQuery{
Code: uint32(sdk.ABCICodeOK),
Value: []byte(version.GetVersion()),
Code: uint32(sdk.CodeOK),
Codespace: string(sdk.CodespaceRoot),
Value: []byte(version.GetVersion()),
}
default:
result = sdk.ErrUnknownRequest(fmt.Sprintf("Unknown query: %s", path)).Result()
@ -339,8 +333,9 @@ func handleQueryApp(app *BaseApp, path []string, req abci.RequestQuery) (res abc
// Encode with json
value := codec.Cdc.MustMarshalBinaryLengthPrefixed(result)
return abci.ResponseQuery{
Code: uint32(sdk.ABCICodeOK),
Value: value,
Code: uint32(sdk.CodeOK),
Codespace: string(sdk.CodespaceRoot),
Value: value,
}
}
msg := "Expected second parameter to be either simulate or version, neither was present"
@ -392,6 +387,7 @@ func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res
return sdk.ErrUnknownRequest(fmt.Sprintf("no custom querier found for route %s", path[1])).QueryResult()
}
// Cache wrap the commit-multistore for safety.
ctx := sdk.NewContext(app.cms.CacheMultiStore(), app.checkState.ctx.BlockHeader(), true, app.Logger).
WithMinimumFees(app.minimumFees)
@ -400,12 +396,13 @@ func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res
resBytes, err := querier(ctx, path[2:], req)
if err != nil {
return abci.ResponseQuery{
Code: uint32(err.ABCICode()),
Log: err.ABCILog(),
Code: uint32(err.Code()),
Codespace: string(err.Codespace()),
Log: err.ABCILog(),
}
}
return abci.ResponseQuery{
Code: uint32(sdk.ABCICodeOK),
Code: uint32(sdk.CodeOK),
Value: resBytes,
}
}
@ -459,8 +456,8 @@ func (app *BaseApp) CheckTx(txBytes []byte) (res abci.ResponseCheckTx) {
Code: uint32(result.Code),
Data: result.Data,
Log: result.Log,
GasWanted: result.GasWanted,
GasUsed: result.GasUsed,
GasWanted: int64(result.GasWanted), // TODO: Should type accept unsigned ints?
GasUsed: int64(result.GasUsed), // TODO: Should type accept unsigned ints?
Tags: result.Tags,
}
}
@ -482,10 +479,11 @@ func (app *BaseApp) DeliverTx(txBytes []byte) (res abci.ResponseDeliverTx) {
// Tell the blockchain engine (i.e. Tendermint).
return abci.ResponseDeliverTx{
Code: uint32(result.Code),
Codespace: string(result.Codespace),
Data: result.Data,
Log: result.Log,
GasWanted: result.GasWanted,
GasUsed: result.GasUsed,
GasWanted: int64(result.GasWanted), // TODO: Should type accept unsigned ints?
GasUsed: int64(result.GasUsed), // TODO: Should type accept unsigned ints?
Tags: result.Tags,
}
}
@ -501,7 +499,6 @@ func validateBasicTxMsgs(msgs []sdk.Msg) sdk.Error {
// Validate the Msg.
err := msg.ValidateBasic()
if err != nil {
err = err.WithDefaultCodespace(sdk.CodespaceRoot)
return err
}
}
@ -509,13 +506,13 @@ func validateBasicTxMsgs(msgs []sdk.Msg) sdk.Error {
return nil
}
// retrieve the context for the ante handler and store the tx bytes; store
// the vote infos if the tx runs within the deliverTx() state.
func (app *BaseApp) getContextForAnte(mode runTxMode, txBytes []byte) (ctx sdk.Context) {
// Get the context
ctx = getState(app, mode).ctx.WithTxBytes(txBytes)
if mode == runTxModeDeliver {
ctx = ctx.WithVoteInfos(app.voteInfos)
// retrieve the context for the tx w/ txBytes and other memoized values.
func (app *BaseApp) getContextForTx(mode runTxMode, txBytes []byte) (ctx sdk.Context) {
ctx = app.getState(mode).ctx.
WithTxBytes(txBytes).
WithVoteInfos(app.voteInfos)
if mode == runTxModeSimulate {
ctx, _ = ctx.CacheContext()
}
return
}
@ -526,7 +523,8 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (re
logs := make([]string, 0, len(msgs))
var data []byte // NOTE: we just append them all (?!)
var tags sdk.Tags // also just append them all
var code sdk.ABCICodeType
var code sdk.CodeType
var codespace sdk.CodespaceType
for msgIdx, msg := range msgs {
// Match route.
msgRoute := msg.Route()
@ -553,6 +551,7 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (re
if !msgResult.IsOK() {
logs = append(logs, fmt.Sprintf("Msg %d failed: %s", msgIdx, msgResult.Log))
code = msgResult.Code
codespace = msgResult.Codespace
break
}
@ -562,10 +561,11 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (re
// Set the final gas values.
result = sdk.Result{
Code: code,
Data: data,
Log: strings.Join(logs, "\n"),
GasUsed: ctx.GasMeter().GasConsumed(),
Code: code,
Codespace: codespace,
Data: data,
Log: strings.Join(logs, "\n"),
GasUsed: ctx.GasMeter().GasConsumed(),
// TODO: FeeAmount/FeeDenom
Tags: tags,
}
@ -575,7 +575,7 @@ func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (re
// Returns the applicantion's deliverState if app is in runTxModeDeliver,
// otherwise it returns the application's checkstate.
func getState(app *BaseApp, mode runTxMode) *state {
func (app *BaseApp) getState(mode runTxMode) *state {
if mode == runTxModeCheck || mode == runTxModeSimulate {
return app.checkState
}
@ -583,24 +583,39 @@ func getState(app *BaseApp, mode runTxMode) *state {
return app.deliverState
}
func (app *BaseApp) initializeContext(ctx sdk.Context, mode runTxMode) sdk.Context {
if mode == runTxModeSimulate {
ctx = ctx.WithMultiStore(getState(app, runTxModeSimulate).CacheMultiStore())
// cacheTxContext returns a new context based off of the provided context with
// a cache wrapped multi-store.
func (app *BaseApp) cacheTxContext(ctx sdk.Context, txBytes []byte) (
sdk.Context, sdk.CacheMultiStore) {
ms := ctx.MultiStore()
// TODO: https://github.com/cosmos/cosmos-sdk/issues/2824
msCache := ms.CacheMultiStore()
if msCache.TracingEnabled() {
msCache = msCache.WithTracingContext(
sdk.TraceContext(
map[string]interface{}{
"txHash": fmt.Sprintf("%X", tmhash.Sum(txBytes)),
},
),
).(sdk.CacheMultiStore)
}
return ctx
return ctx.WithMultiStore(msCache), msCache
}
// runTx processes a transaction. The transactions is proccessed via an
// anteHandler. txBytes may be nil in some cases, eg. in tests. Also, in the
// future we may support "internal" transactions.
// anteHandler. The provided txBytes may be nil in some cases, eg. in tests. For
// further details on transaction execution, reference the BaseApp SDK
// documentation.
func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk.Result) {
// NOTE: GasWanted should be returned by the AnteHandler. GasUsed is
// determined by the GasMeter. We need access to the context to get the gas
// meter so we initialize upfront.
var gasWanted int64
var msCache sdk.CacheMultiStore
ctx := app.getContextForAnte(mode, txBytes)
ctx = app.initializeContext(ctx, mode)
var gasWanted uint64
ctx := app.getContextForTx(mode, txBytes)
ms := ctx.MultiStore()
defer func() {
if r := recover(); r != nil {
@ -623,38 +638,48 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk
return err.Result()
}
// run the ante handler
// Execute the ante handler if one is defined.
if app.anteHandler != nil {
newCtx, result, abort := app.anteHandler(ctx, tx, (mode == runTxModeSimulate))
var anteCtx sdk.Context
var msCache sdk.CacheMultiStore
// Cache wrap context before anteHandler call in case it aborts.
// This is required for both CheckTx and DeliverTx.
// https://github.com/cosmos/cosmos-sdk/issues/2772
// NOTE: Alternatively, we could require that anteHandler ensures that
// writes do not happen if aborted/failed. This may have some
// performance benefits, but it'll be more difficult to get right.
anteCtx, msCache = app.cacheTxContext(ctx, txBytes)
newCtx, result, abort := app.anteHandler(anteCtx, tx, (mode == runTxModeSimulate))
if abort {
return result
}
if !newCtx.IsZero() {
ctx = newCtx
// At this point, newCtx.MultiStore() is cache wrapped,
// or something else replaced by anteHandler.
// We want the original ms, not one which was cache-wrapped
// for the ante handler.
ctx = newCtx.WithMultiStore(ms)
}
msCache.Write()
gasWanted = result.GasWanted
}
if mode == runTxModeSimulate {
result = app.runMsgs(ctx, msgs, mode)
result.GasWanted = gasWanted
if mode == runTxModeCheck {
return
}
// Keep the state in a transient CacheWrap in case processing the messages
// fails.
msCache = getState(app, mode).CacheMultiStore()
if msCache.TracingEnabled() {
msCache = msCache.WithTracingContext(sdk.TraceContext(
map[string]interface{}{"txHash": cmn.HexBytes(tmhash.Sum(txBytes)).String()},
)).(sdk.CacheMultiStore)
}
ctx = ctx.WithMultiStore(msCache)
result = app.runMsgs(ctx, msgs, mode)
// Create a new context based off of the existing context with a cache wrapped
// multi-store in case message processing fails.
runMsgCtx, msCache := app.cacheTxContext(ctx, txBytes)
result = app.runMsgs(runMsgCtx, msgs, mode)
result.GasWanted = gasWanted
if mode == runTxModeSimulate {
return
}
// only update state if all messages pass
if result.IsOK() {
msCache.Write()

View File

@ -282,8 +282,19 @@ func TestInitChainer(t *testing.T) {
// Simple tx with a list of Msgs.
type txTest struct {
Msgs []sdk.Msg
Counter int64
Msgs []sdk.Msg
Counter int64
FailOnAnte bool
}
func (tx *txTest) setFailOnAnte(fail bool) {
tx.FailOnAnte = fail
}
func (tx *txTest) setFailOnHandler(fail bool) {
for i, msg := range tx.Msgs {
tx.Msgs[i] = msgCounter{msg.(msgCounter).Counter, fail}
}
}
// Implements Tx
@ -297,7 +308,8 @@ const (
// ValidateBasic() fails on negative counters.
// Otherwise it's up to the handlers
type msgCounter struct {
Counter int64
Counter int64
FailOnHandler bool
}
// Implements Msg
@ -315,9 +327,9 @@ func (msg msgCounter) ValidateBasic() sdk.Error {
func newTxCounter(txInt int64, msgInts ...int64) *txTest {
var msgs []sdk.Msg
for _, msgInt := range msgInts {
msgs = append(msgs, msgCounter{msgInt})
msgs = append(msgs, msgCounter{msgInt, false})
}
return &txTest{msgs, txInt}
return &txTest{msgs, txInt, false}
}
// a msg we dont know how to route
@ -369,8 +381,13 @@ func testTxDecoder(cdc *codec.Codec) sdk.TxDecoder {
func anteHandlerTxTest(t *testing.T, capKey *sdk.KVStoreKey, storeKey []byte) sdk.AnteHandler {
return func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, res sdk.Result, abort bool) {
store := ctx.KVStore(capKey)
msgCounter := tx.(txTest).Counter
res = incrementingCounter(t, store, storeKey, msgCounter)
txTest := tx.(txTest)
if txTest.FailOnAnte {
return newCtx, sdk.ErrInternal("ante handler failure").Result(), true
}
res = incrementingCounter(t, store, storeKey, txTest.Counter)
return
}
}
@ -381,10 +398,15 @@ func handlerMsgCounter(t *testing.T, capKey *sdk.KVStoreKey, deliverKey []byte)
var msgCount int64
switch m := msg.(type) {
case *msgCounter:
if m.FailOnHandler {
return sdk.ErrInternal("message handler failure").Result()
}
msgCount = m.Counter
case *msgCounter2:
msgCount = m.Counter
}
return incrementingCounter(t, store, deliverKey, msgCount)
}
}
@ -596,7 +618,7 @@ func TestConcurrentCheckDeliver(t *testing.T) {
// Simulate() and Query("/app/simulate", txBytes) should give
// the same results.
func TestSimulateTx(t *testing.T) {
gasConsumed := int64(5)
gasConsumed := uint64(5)
anteOpt := func(bapp *BaseApp) {
bapp.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, res sdk.Result, abort bool) {
@ -678,7 +700,8 @@ func TestRunInvalidTransaction(t *testing.T) {
{
emptyTx := &txTest{}
err := app.Deliver(emptyTx)
require.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeInternal), err.Code)
require.EqualValues(t, sdk.CodeInternal, err.Code)
require.EqualValues(t, sdk.CodespaceRoot, err.Codespace)
}
// Transaction where ValidateBasic fails
@ -701,7 +724,8 @@ func TestRunInvalidTransaction(t *testing.T) {
tx := testCase.tx
res := app.Deliver(tx)
if testCase.fail {
require.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeInvalidSequence), res.Code)
require.EqualValues(t, sdk.CodeInvalidSequence, res.Code)
require.EqualValues(t, sdk.CodespaceRoot, res.Codespace)
} else {
require.True(t, res.IsOK(), fmt.Sprintf("%v", res))
}
@ -710,13 +734,15 @@ func TestRunInvalidTransaction(t *testing.T) {
// Transaction with no known route
{
unknownRouteTx := txTest{[]sdk.Msg{msgNoRoute{}}, 0}
unknownRouteTx := txTest{[]sdk.Msg{msgNoRoute{}}, 0, false}
err := app.Deliver(unknownRouteTx)
require.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnknownRequest), err.Code)
require.EqualValues(t, sdk.CodeUnknownRequest, err.Code)
require.EqualValues(t, sdk.CodespaceRoot, err.Codespace)
unknownRouteTx = txTest{[]sdk.Msg{msgCounter{}, msgNoRoute{}}, 0}
unknownRouteTx = txTest{[]sdk.Msg{msgCounter{}, msgNoRoute{}}, 0, false}
err = app.Deliver(unknownRouteTx)
require.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnknownRequest), err.Code)
require.EqualValues(t, sdk.CodeUnknownRequest, err.Code)
require.EqualValues(t, sdk.CodespaceRoot, err.Codespace)
}
// Transaction with an unregistered message
@ -732,13 +758,14 @@ func TestRunInvalidTransaction(t *testing.T) {
txBytes, err := newCdc.MarshalBinaryLengthPrefixed(tx)
require.NoError(t, err)
res := app.DeliverTx(txBytes)
require.EqualValues(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeTxDecode), res.Code)
require.EqualValues(t, sdk.CodeTxDecode, res.Code)
require.EqualValues(t, sdk.CodespaceRoot, res.Codespace)
}
}
// Test that transactions exceeding gas limits fail
func TestTxGasLimits(t *testing.T) {
gasGranted := int64(10)
gasGranted := uint64(10)
anteOpt := func(bapp *BaseApp) {
bapp.SetAnteHandler(func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, res sdk.Result, abort bool) {
newCtx = ctx.WithGasMeter(sdk.NewGasMeter(gasGranted))
@ -763,7 +790,7 @@ func TestTxGasLimits(t *testing.T) {
}()
count := tx.(*txTest).Counter
newCtx.GasMeter().ConsumeGas(count, "counter-ante")
newCtx.GasMeter().ConsumeGas(uint64(count), "counter-ante")
res = sdk.Result{
GasWanted: gasGranted,
}
@ -775,7 +802,7 @@ func TestTxGasLimits(t *testing.T) {
routerOpt := func(bapp *BaseApp) {
bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
count := msg.(msgCounter).Counter
ctx.GasMeter().ConsumeGas(count, "counter-handler")
ctx.GasMeter().ConsumeGas(uint64(count), "counter-handler")
return sdk.Result{}
})
}
@ -786,7 +813,7 @@ func TestTxGasLimits(t *testing.T) {
testCases := []struct {
tx *txTest
gasUsed int64
gasUsed uint64
fail bool
}{
{newTxCounter(0, 0), 0, false},
@ -819,7 +846,77 @@ func TestTxGasLimits(t *testing.T) {
if !tc.fail {
require.True(t, res.IsOK(), fmt.Sprintf("%d: %v, %v", i, tc, res))
} else {
require.Equal(t, res.Code, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeOutOfGas), fmt.Sprintf("%d: %v, %v", i, tc, res))
require.Equal(t, sdk.CodeOutOfGas, res.Code, fmt.Sprintf("%d: %v, %v", i, tc, res))
require.Equal(t, sdk.CodespaceRoot, res.Codespace)
}
}
}
func TestBaseAppAnteHandler(t *testing.T) {
anteKey := []byte("ante-key")
anteOpt := func(bapp *BaseApp) {
bapp.SetAnteHandler(anteHandlerTxTest(t, capKey1, anteKey))
}
deliverKey := []byte("deliver-key")
routerOpt := func(bapp *BaseApp) {
bapp.Router().AddRoute(routeMsgCounter, handlerMsgCounter(t, capKey1, deliverKey))
}
cdc := codec.New()
app := setupBaseApp(t, anteOpt, routerOpt)
app.InitChain(abci.RequestInitChain{})
registerTestCodec(cdc)
app.BeginBlock(abci.RequestBeginBlock{})
// execute a tx that will fail ante handler execution
//
// NOTE: State should not be mutated here. This will be implicitly checked by
// the next txs ante handler execution (anteHandlerTxTest).
tx := newTxCounter(0, 0)
tx.setFailOnAnte(true)
txBytes, err := cdc.MarshalBinaryLengthPrefixed(tx)
require.NoError(t, err)
res := app.DeliverTx(txBytes)
require.False(t, res.IsOK(), fmt.Sprintf("%v", res))
ctx := app.getState(runTxModeDeliver).ctx
store := ctx.KVStore(capKey1)
require.Equal(t, int64(0), getIntFromStore(store, anteKey))
// execute at tx that will pass the ante handler (the checkTx state should
// mutate) but will fail the message handler
tx = newTxCounter(0, 0)
tx.setFailOnHandler(true)
txBytes, err = cdc.MarshalBinaryLengthPrefixed(tx)
require.NoError(t, err)
res = app.DeliverTx(txBytes)
require.False(t, res.IsOK(), fmt.Sprintf("%v", res))
ctx = app.getState(runTxModeDeliver).ctx
store = ctx.KVStore(capKey1)
require.Equal(t, int64(1), getIntFromStore(store, anteKey))
require.Equal(t, int64(0), getIntFromStore(store, deliverKey))
// execute a successful ante handler and message execution where state is
// implicitly checked by previous tx executions
tx = newTxCounter(1, 0)
txBytes, err = cdc.MarshalBinaryLengthPrefixed(tx)
require.NoError(t, err)
res = app.DeliverTx(txBytes)
require.True(t, res.IsOK(), fmt.Sprintf("%v", res))
ctx = app.getState(runTxModeDeliver).ctx
store = ctx.KVStore(capKey1)
require.Equal(t, int64(2), getIntFromStore(store, anteKey))
require.Equal(t, int64(1), getIntFromStore(store, deliverKey))
// commit
app.EndBlock(abci.RequestEndBlock{})
app.Commit()
}

View File

@ -175,10 +175,22 @@ func (ctx CLIContext) WithCodec(cdc *codec.Codec) CLIContext {
return ctx
}
// GetAccountDecoder gets the account decoder for auth.DefaultAccount.
func GetAccountDecoder(cdc *codec.Codec) auth.AccountDecoder {
return func(accBytes []byte) (acct auth.Account, err error) {
err = cdc.UnmarshalBinaryBare(accBytes, &acct)
if err != nil {
panic(err)
}
return acct, err
}
}
// WithAccountDecoder returns a copy of the context with an updated account
// decoder.
func (ctx CLIContext) WithAccountDecoder(decoder auth.AccountDecoder) CLIContext {
ctx.AccDecoder = decoder
func (ctx CLIContext) WithAccountDecoder(cdc *codec.Codec) CLIContext {
ctx.AccDecoder = GetAccountDecoder(cdc)
return ctx
}

View File

@ -17,25 +17,32 @@ const (
DefaultGasLimit = 200000
GasFlagSimulate = "simulate"
FlagUseLedger = "ledger"
FlagChainID = "chain-id"
FlagNode = "node"
FlagHeight = "height"
FlagGas = "gas"
FlagGasAdjustment = "gas-adjustment"
FlagTrustNode = "trust-node"
FlagFrom = "from"
FlagName = "name"
FlagAccountNumber = "account-number"
FlagSequence = "sequence"
FlagMemo = "memo"
FlagFee = "fee"
FlagAsync = "async"
FlagJson = "json"
FlagPrintResponse = "print-response"
FlagDryRun = "dry-run"
FlagGenerateOnly = "generate-only"
FlagIndentResponse = "indent"
FlagUseLedger = "ledger"
FlagChainID = "chain-id"
FlagNode = "node"
FlagHeight = "height"
FlagGas = "gas"
FlagGasAdjustment = "gas-adjustment"
FlagTrustNode = "trust-node"
FlagFrom = "from"
FlagName = "name"
FlagAccountNumber = "account-number"
FlagSequence = "sequence"
FlagMemo = "memo"
FlagFee = "fee"
FlagAsync = "async"
FlagJson = "json"
FlagPrintResponse = "print-response"
FlagDryRun = "dry-run"
FlagGenerateOnly = "generate-only"
FlagIndentResponse = "indent"
FlagListenAddr = "laddr"
FlagCORS = "cors"
FlagMaxOpenConnections = "max-open"
FlagInsecure = "insecure"
FlagSSLHosts = "ssl-hosts"
FlagSSLCertFile = "ssl-certfile"
FlagSSLKeyFile = "ssl-keyfile"
)
// LineBreak can be included in a command list to provide a blank line
@ -92,12 +99,32 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command {
return cmds
}
// RegisterRestServerFlags registers the flags required for rest server
func RegisterRestServerFlags(cmd *cobra.Command) *cobra.Command {
cmd.Flags().String(FlagListenAddr, "tcp://localhost:1317", "The address for the server to listen on")
cmd.Flags().Bool(FlagInsecure, false, "Do not set up SSL/TLS layer")
cmd.Flags().String(FlagSSLHosts, "", "Comma-separated hostnames and IPs to generate a certificate for")
cmd.Flags().String(FlagSSLCertFile, "", "Path to a SSL certificate file. If not supplied, a self-signed certificate will be generated.")
cmd.Flags().String(FlagSSLKeyFile, "", "Path to a key file; ignored if a certificate file is not supplied.")
cmd.Flags().String(FlagCORS, "", "Set the domains that can make CORS requests (* for all)")
cmd.Flags().String(FlagChainID, "", "Chain ID of Tendermint node")
cmd.Flags().String(FlagNode, "tcp://localhost:26657", "Address of the node to connect to")
cmd.Flags().Int(FlagMaxOpenConnections, 1000, "The number of maximum open connections")
cmd.Flags().Bool(FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
cmd.Flags().Bool(FlagIndentResponse, false, "Add indent to JSON response")
viper.BindPFlag(FlagTrustNode, cmd.Flags().Lookup(FlagTrustNode))
viper.BindPFlag(FlagChainID, cmd.Flags().Lookup(FlagChainID))
viper.BindPFlag(FlagNode, cmd.Flags().Lookup(FlagNode))
return cmd
}
// Gas flag parsing functions
// GasSetting encapsulates the possible values passed through the --gas flag.
type GasSetting struct {
Simulate bool
Gas int64
Gas uint64
}
// Type returns the flag's value type.
@ -113,18 +140,18 @@ func (v *GasSetting) String() string {
if v.Simulate {
return GasFlagSimulate
}
return strconv.FormatInt(v.Gas, 10)
return strconv.FormatUint(v.Gas, 10)
}
// ParseGasFlag parses the value of the --gas flag.
func ReadGasFlag(s string) (simulate bool, gas int64, err error) {
func ReadGasFlag(s string) (simulate bool, gas uint64, err error) {
switch s {
case "":
gas = DefaultGasLimit
case GasFlagSimulate:
simulate = true
default:
gas, err = strconv.ParseInt(s, 10, 64)
gas, err = strconv.ParseUint(s, 10, 64)
if err != nil {
err = fmt.Errorf("gas must be either integer or %q", GasFlagSimulate)
return

View File

@ -2,20 +2,17 @@ package keys
import (
"fmt"
"github.com/syndtr/goleveldb/leveldb/opt"
"net/http"
"path/filepath"
"github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/spf13/viper"
"github.com/syndtr/goleveldb/leveldb/opt"
"github.com/tendermint/tendermint/libs/cli"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"net/http"
)
// KeyDBName is the directory under root where we store the keys

View File

@ -284,7 +284,7 @@ func TestCoinSend(t *testing.T) {
// test failure with negative gas
res, body, _ = doSendWithGas(t, port, seed, name, password, addr, "-200", 0, "")
require.Equal(t, http.StatusInternalServerError, res.StatusCode, body)
require.Equal(t, http.StatusBadRequest, res.StatusCode, body)
// test failure with 0 gas
res, body, _ = doSendWithGas(t, port, seed, name, password, addr, "0", 0, "")
@ -390,8 +390,8 @@ func TestCoinSendGenerateSignAndBroadcast(t *testing.T) {
require.Nil(t, cdc.UnmarshalJSON([]byte(body), &resultTx))
require.Equal(t, uint32(0), resultTx.CheckTx.Code)
require.Equal(t, uint32(0), resultTx.DeliverTx.Code)
require.Equal(t, gasEstimate, resultTx.DeliverTx.GasWanted)
require.Equal(t, gasEstimate, resultTx.DeliverTx.GasUsed)
require.Equal(t, gasEstimate, uint64(resultTx.DeliverTx.GasWanted))
require.Equal(t, gasEstimate, uint64(resultTx.DeliverTx.GasUsed))
}
func TestTxs(t *testing.T) {

View File

@ -10,176 +10,169 @@ import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/client/rpc"
"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/cosmos/cosmos-sdk/codec"
keybase "github.com/cosmos/cosmos-sdk/crypto/keys"
"github.com/cosmos/cosmos-sdk/server"
auth "github.com/cosmos/cosmos-sdk/x/auth/client/rest"
bank "github.com/cosmos/cosmos-sdk/x/bank/client/rest"
gov "github.com/cosmos/cosmos-sdk/x/gov/client/rest"
slashing "github.com/cosmos/cosmos-sdk/x/slashing/client/rest"
stake "github.com/cosmos/cosmos-sdk/x/stake/client/rest"
"github.com/gorilla/mux"
"github.com/rakyll/statik/fs"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/tendermint/tendermint/libs/log"
tmserver "github.com/tendermint/tendermint/rpc/lib/server"
// Import statik for light client stuff
_ "github.com/cosmos/cosmos-sdk/client/lcd/statik"
)
const (
flagListenAddr = "laddr"
flagCORS = "cors"
flagMaxOpenConnections = "max-open"
flagInsecure = "insecure"
flagSSLHosts = "ssl-hosts"
flagSSLCertFile = "ssl-certfile"
flagSSLKeyFile = "ssl-keyfile"
)
// RestServer represents the Light Client Rest server
type RestServer struct {
Mux *mux.Router
CliCtx context.CLIContext
KeyBase keybase.Keybase
Cdc *codec.Codec
log log.Logger
listener net.Listener
fingerprint string
}
// NewRestServer creates a new rest server instance
func NewRestServer(cdc *codec.Codec) *RestServer {
r := mux.NewRouter()
cliCtx := context.NewCLIContext().WithCodec(cdc)
// Register version methods on the router
r.HandleFunc("/version", CLIVersionRequestHandler).Methods("GET")
r.HandleFunc("/node_version", NodeVersionRequestHandler(cliCtx)).Methods("GET")
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "rest-server")
return &RestServer{
Mux: r,
CliCtx: cliCtx,
Cdc: cdc,
log: logger,
}
}
func (rs *RestServer) setKeybase(kb keybase.Keybase) {
// If a keybase is passed in, set it and return
if kb != nil {
rs.KeyBase = kb
return
}
// Otherwise get the keybase and set it
kb, err := keys.GetKeyBase() //XXX
if err != nil {
fmt.Printf("Failed to open Keybase: %s, exiting...", err)
os.Exit(1)
}
rs.KeyBase = kb
}
// Start starts the rest server
func (rs *RestServer) Start(listenAddr string, sslHosts string,
certFile string, keyFile string, maxOpen int, insecure bool) (err error) {
server.TrapSignal(func() {
err := rs.listener.Close()
rs.log.Error("error closing listener", "err", err)
})
// TODO: re-enable insecure mode once #2715 has been addressed
if insecure {
fmt.Println(
"Insecure mode is temporarily disabled, please locally generate an " +
"SSL certificate to test. Support will be re-enabled soon!",
)
// listener, err = tmserver.StartHTTPServer(
// listenAddr, handler, logger,
// tmserver.Config{MaxOpenConnections: maxOpen},
// )
// if err != nil {
// return
// }
} else {
if certFile != "" {
// validateCertKeyFiles() is needed to work around tendermint/tendermint#2460
err = validateCertKeyFiles(certFile, keyFile)
if err != nil {
return err
}
// cert/key pair is provided, read the fingerprint
rs.fingerprint, err = fingerprintFromFile(certFile)
if err != nil {
return err
}
} else {
// if certificate is not supplied, generate a self-signed one
certFile, keyFile, rs.fingerprint, err = genCertKeyFilesAndReturnFingerprint(sslHosts)
if err != nil {
return err
}
defer func() {
os.Remove(certFile)
os.Remove(keyFile)
}()
}
rs.listener, err = tmserver.StartHTTPAndTLSServer(
listenAddr, rs.Mux,
certFile, keyFile,
rs.log,
tmserver.Config{MaxOpenConnections: maxOpen},
)
if err != nil {
return
}
rs.log.Info(rs.fingerprint)
rs.log.Info("REST server started")
}
// logger.Info("REST server started")
return nil
}
// ServeCommand will generate a long-running rest server
// (aka Light Client Daemon) that exposes functionality similar
// to the cli, but over rest
func ServeCommand(cdc *codec.Codec) *cobra.Command {
func (rs *RestServer) ServeCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "rest-server",
Short: "Start LCD (light-client daemon), a local REST server",
RunE: func(cmd *cobra.Command, args []string) (err error) {
listenAddr := viper.GetString(flagListenAddr)
handler := createHandler(cdc)
rs.setKeybase(nil)
// Start the rest server and return error if one exists
err = rs.Start(
viper.GetString(client.FlagListenAddr),
viper.GetString(client.FlagSSLHosts),
viper.GetString(client.FlagSSLCertFile),
viper.GetString(client.FlagSSLKeyFile),
viper.GetInt(client.FlagMaxOpenConnections),
viper.GetBool(client.FlagInsecure))
registerSwaggerUI(handler)
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "rest-server")
maxOpen := viper.GetInt(flagMaxOpenConnections)
sslHosts := viper.GetString(flagSSLHosts)
certFile := viper.GetString(flagSSLCertFile)
keyFile := viper.GetString(flagSSLKeyFile)
var listener net.Listener
var fingerprint string
server.TrapSignal(func() {
err := listener.Close()
logger.Error("error closing listener", "err", err)
})
var cleanupFunc func()
// TODO: re-enable insecure mode once #2715 has been addressed
if viper.GetBool(flagInsecure) {
fmt.Println(
"Insecure mode is temporarily disabled, please locally generate an " +
"SSL certificate to test. Support will be re-enabled soon!",
)
// listener, err = tmserver.StartHTTPServer(
// listenAddr, handler, logger,
// tmserver.Config{MaxOpenConnections: maxOpen},
// )
// if err != nil {
// return
// }
} else {
if certFile != "" {
// validateCertKeyFiles() is needed to work around tendermint/tendermint#2460
err = validateCertKeyFiles(certFile, keyFile)
if err != nil {
return err
}
// cert/key pair is provided, read the fingerprint
fingerprint, err = fingerprintFromFile(certFile)
if err != nil {
return err
}
} else {
// if certificate is not supplied, generate a self-signed one
certFile, keyFile, fingerprint, err = genCertKeyFilesAndReturnFingerprint(sslHosts)
if err != nil {
return err
}
cleanupFunc = func() {
os.Remove(certFile)
os.Remove(keyFile)
}
defer cleanupFunc()
}
listener, err = tmserver.StartHTTPAndTLSServer(
listenAddr, handler,
certFile, keyFile,
logger,
tmserver.Config{MaxOpenConnections: maxOpen},
)
if err != nil {
return
}
logger.Info(fingerprint)
logger.Info("REST server started")
}
// logger.Info("REST server started")
return nil
return err
},
}
cmd.Flags().String(flagListenAddr, "tcp://localhost:1317", "The address for the server to listen on")
cmd.Flags().Bool(flagInsecure, false, "Do not set up SSL/TLS layer")
cmd.Flags().String(flagSSLHosts, "", "Comma-separated hostnames and IPs to generate a certificate for")
cmd.Flags().String(flagSSLCertFile, "", "Path to a SSL certificate file. If not supplied, a self-signed certificate will be generated.")
cmd.Flags().String(flagSSLKeyFile, "", "Path to a key file; ignored if a certificate file is not supplied.")
cmd.Flags().String(flagCORS, "", "Set the domains that can make CORS requests (* for all)")
cmd.Flags().String(client.FlagChainID, "", "Chain ID of Tendermint node")
cmd.Flags().String(client.FlagNode, "tcp://localhost:26657", "Address of the node to connect to")
cmd.Flags().Int(flagMaxOpenConnections, 1000, "The number of maximum open connections")
cmd.Flags().Bool(client.FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
cmd.Flags().Bool(client.FlagIndentResponse, false, "Add indent to JSON response")
viper.BindPFlag(client.FlagTrustNode, cmd.Flags().Lookup(client.FlagTrustNode))
viper.BindPFlag(client.FlagChainID, cmd.Flags().Lookup(client.FlagChainID))
viper.BindPFlag(client.FlagNode, cmd.Flags().Lookup(client.FlagNode))
client.RegisterRestServerFlags(cmd)
return cmd
}
func createHandler(cdc *codec.Codec) *mux.Router {
r := mux.NewRouter()
kb, err := keys.GetKeyBase() //XXX
if err != nil {
panic(err)
}
cliCtx := context.NewCLIContext().WithCodec(cdc)
// TODO: make more functional? aka r = keys.RegisterRoutes(r)
r.HandleFunc("/version", CLIVersionRequestHandler).Methods("GET")
r.HandleFunc("/node_version", NodeVersionRequestHandler(cliCtx)).Methods("GET")
keys.RegisterRoutes(r, cliCtx.Indent)
rpc.RegisterRoutes(cliCtx, r)
tx.RegisterRoutes(cliCtx, r, cdc)
auth.RegisterRoutes(cliCtx, r, cdc, "acc")
bank.RegisterRoutes(cliCtx, r, cdc, kb)
stake.RegisterRoutes(cliCtx, r, cdc, kb)
slashing.RegisterRoutes(cliCtx, r, cdc, kb)
gov.RegisterRoutes(cliCtx, r, cdc)
return r
}
func registerSwaggerUI(r *mux.Router) {
func (rs *RestServer) registerSwaggerUI() {
statikFS, err := fs.New()
if err != nil {
panic(err)
}
staticServer := http.FileServer(statikFS)
r.PathPrefix("/swagger-ui/").Handler(http.StripPrefix("/swagger-ui/", staticServer))
rs.Mux.PathPrefix("/swagger-ui/").Handler(http.StripPrefix("/swagger-ui/", staticServer))
}
func validateCertKeyFiles(certFile, keyFile string) error {

View File

@ -19,6 +19,8 @@ import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/client/rpc"
"github.com/cosmos/cosmos-sdk/client/tx"
gapp "github.com/cosmos/cosmos-sdk/cmd/gaia/app"
"github.com/cosmos/cosmos-sdk/codec"
crkeys "github.com/cosmos/cosmos-sdk/crypto/keys"
@ -45,6 +47,12 @@ import (
"github.com/tendermint/tendermint/proxy"
tmrpc "github.com/tendermint/tendermint/rpc/lib/server"
tmtypes "github.com/tendermint/tendermint/types"
authRest "github.com/cosmos/cosmos-sdk/x/auth/client/rest"
bankRest "github.com/cosmos/cosmos-sdk/x/bank/client/rest"
govRest "github.com/cosmos/cosmos-sdk/x/gov/client/rest"
slashingRest "github.com/cosmos/cosmos-sdk/x/slashing/client/rest"
stakeRest "github.com/cosmos/cosmos-sdk/x/stake/client/rest"
)
// makePathname creates a unique pathname for each test. It will panic if it
@ -103,6 +111,13 @@ func GetKeyBase(t *testing.T) crkeys.Keybase {
return keybase
}
// GetTestKeyBase fetches the current testing keybase
func GetTestKeyBase(t *testing.T) crkeys.Keybase {
keybase, err := keys.GetKeyBaseWithWritePerm()
require.NoError(t, err)
return keybase
}
// CreateAddr adds an address to the key store and returns an address and seed.
// It also requires that the key could be created.
func CreateAddr(t *testing.T, name, password string, kb crkeys.Keybase) (sdk.AccAddress, string) {
@ -288,7 +303,7 @@ func InitializeTestLCD(
require.NoError(t, err)
tests.WaitForNextHeightTM(tests.ExtractPortFromAddress(config.RPC.ListenAddress))
lcd, err := startLCD(logger, listenAddr, cdc)
lcd, err := startLCD(logger, listenAddr, cdc, t)
require.NoError(t, err)
tests.WaitForLCDStart(port)
@ -347,8 +362,23 @@ func startTM(
// startLCD starts the LCD.
//
// NOTE: This causes the thread to block.
func startLCD(logger log.Logger, listenAddr string, cdc *codec.Codec) (net.Listener, error) {
return tmrpc.StartHTTPServer(listenAddr, createHandler(cdc), logger, tmrpc.Config{})
func startLCD(logger log.Logger, listenAddr string, cdc *codec.Codec, t *testing.T) (net.Listener, error) {
rs := NewRestServer(cdc)
rs.setKeybase(GetTestKeyBase(t))
registerRoutes(rs)
return tmrpc.StartHTTPServer(listenAddr, rs.Mux, logger, tmrpc.Config{})
}
// NOTE: If making updates here also update cmd/gaia/cmd/gaiacli/main.go
func registerRoutes(rs *RestServer) {
keys.RegisterRoutes(rs.Mux, rs.CliCtx.Indent)
rpc.RegisterRoutes(rs.CliCtx, rs.Mux)
tx.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc)
authRest.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, "acc")
bankRest.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
stakeRest.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
slashingRest.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
govRest.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc)
}
// Request makes a test LCD test request. It returns a response object and a

View File

@ -34,7 +34,7 @@ func WriteErrorResponse(w http.ResponseWriter, status int, err string) {
// WriteSimulationResponse prepares and writes an HTTP
// response for transactions simulations.
func WriteSimulationResponse(w http.ResponseWriter, gas int64) {
func WriteSimulationResponse(w http.ResponseWriter, gas uint64) {
w.WriteHeader(http.StatusOK)
w.Write([]byte(fmt.Sprintf(`{"gas_estimate":%v}`, gas)))
}

View File

@ -71,7 +71,7 @@ func EnrichCtxWithGas(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name
// CalculateGas simulates the execution of a transaction and returns
// both the estimate obtained by the query and the adjusted amount.
func CalculateGas(queryFunc func(string, common.HexBytes) ([]byte, error), cdc *amino.Codec, txBytes []byte, adjustment float64) (estimate, adjusted int64, err error) {
func CalculateGas(queryFunc func(string, common.HexBytes) ([]byte, error), cdc *amino.Codec, txBytes []byte, adjustment float64) (estimate, adjusted uint64, err error) {
// run a simulation (via /app/simulate query) to
// estimate gas and update TxBuilder accordingly
rawRes, err := queryFunc("/app/simulate", txBytes)
@ -152,7 +152,7 @@ func SignStdTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name string,
// nolint
// SimulateMsgs simulates the transaction and returns the gas estimate and the adjusted value.
func simulateMsgs(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg) (estimated, adjusted int64, err error) {
func simulateMsgs(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg) (estimated, adjusted uint64, err error) {
txBytes, err := txBldr.BuildWithPubKey(name, msgs)
if err != nil {
return
@ -161,11 +161,11 @@ func simulateMsgs(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name stri
return
}
func adjustGasEstimate(estimate int64, adjustment float64) int64 {
return int64(adjustment * float64(estimate))
func adjustGasEstimate(estimate uint64, adjustment float64) uint64 {
return uint64(adjustment * float64(estimate))
}
func parseQueryResponse(cdc *amino.Codec, rawRes []byte) (int64, error) {
func parseQueryResponse(cdc *amino.Codec, rawRes []byte) (uint64, error) {
var simulationResult sdk.Result
if err := cdc.UnmarshalBinaryLengthPrefixed(rawRes, &simulationResult); err != nil {
return 0, err

View File

@ -14,16 +14,16 @@ func TestParseQueryResponse(t *testing.T) {
cdc := app.MakeCodec()
sdkResBytes := cdc.MustMarshalBinaryLengthPrefixed(sdk.Result{GasUsed: 10})
gas, err := parseQueryResponse(cdc, sdkResBytes)
assert.Equal(t, gas, int64(10))
assert.Equal(t, gas, uint64(10))
assert.Nil(t, err)
gas, err = parseQueryResponse(cdc, []byte("fuzzy"))
assert.Equal(t, gas, int64(0))
assert.Equal(t, gas, uint64(0))
assert.NotNil(t, err)
}
func TestCalculateGas(t *testing.T) {
cdc := app.MakeCodec()
makeQueryFunc := func(gasUsed int64, wantErr bool) func(string, common.HexBytes) ([]byte, error) {
makeQueryFunc := func(gasUsed uint64, wantErr bool) func(string, common.HexBytes) ([]byte, error) {
return func(string, common.HexBytes) ([]byte, error) {
if wantErr {
return nil, errors.New("")
@ -32,15 +32,15 @@ func TestCalculateGas(t *testing.T) {
}
}
type args struct {
queryFuncGasUsed int64
queryFuncGasUsed uint64
queryFuncWantErr bool
adjustment float64
}
tests := []struct {
name string
args args
wantEstimate int64
wantAdjusted int64
wantEstimate uint64
wantAdjusted uint64
wantErr bool
}{
{"error", args{0, true, 1.2}, 0, 0, true},

View File

@ -113,7 +113,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
app.cdc,
app.keyStake, app.tkeyStake,
app.bankKeeper, app.paramsKeeper.Subspace(stake.DefaultParamspace),
app.RegisterCodespace(stake.DefaultCodespace),
stake.DefaultCodespace,
)
app.mintKeeper = mint.NewKeeper(app.cdc, app.keyMint,
app.paramsKeeper.Subspace(mint.DefaultParamspace),
@ -124,19 +124,19 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
app.keyDistr,
app.paramsKeeper.Subspace(distr.DefaultParamspace),
app.bankKeeper, &stakeKeeper, app.feeCollectionKeeper,
app.RegisterCodespace(stake.DefaultCodespace),
distr.DefaultCodespace,
)
app.slashingKeeper = slashing.NewKeeper(
app.cdc,
app.keySlashing,
&stakeKeeper, app.paramsKeeper.Subspace(slashing.DefaultParamspace),
app.RegisterCodespace(slashing.DefaultCodespace),
slashing.DefaultCodespace,
)
app.govKeeper = gov.NewKeeper(
app.cdc,
app.keyGov,
app.paramsKeeper, app.paramsKeeper.Subspace(gov.DefaultParamspace), app.bankKeeper, &stakeKeeper,
app.RegisterCodespace(gov.DefaultCodespace),
gov.DefaultCodespace,
)
// register the staking hooks

View File

@ -91,7 +91,6 @@ func (ga *GenesisAccount) ToAccount() (acc *auth.BaseAccount) {
}
}
// Create the core parameters for genesis initialization for gaia
// note that the pubkey input is this machines pubkey
func GaiaAppGenState(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []json.RawMessage) (
@ -279,11 +278,13 @@ func CollectStdTxs(cdc *codec.Codec, moniker string, genTxsDir string, genDoc tm
func NewDefaultGenesisAccount(addr sdk.AccAddress) GenesisAccount {
accAuth := auth.NewBaseAccountWithAddress(addr)
coins :=sdk.Coins{
{"fooToken", sdk.NewInt(1000)},
{bondDenom, freeFermionsAcc},
coins := sdk.Coins{
sdk.NewCoin("fooToken", sdk.NewInt(1000)),
sdk.NewCoin(bondDenom, freeFermionsAcc),
}
coins.Sort()
accAuth.Coins = coins
return NewGenesisAccount(&accAuth)
}

View File

@ -63,7 +63,7 @@ func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
// Randomly generate some genesis accounts
for _, acc := range accs {
coins := sdk.Coins{sdk.Coin{stakeTypes.DefaultBondDenom, sdk.NewInt(amount)}}
coins := sdk.Coins{sdk.NewCoin(stakeTypes.DefaultBondDenom, sdk.NewInt(amount))}
genesisAccounts = append(genesisAccounts, GenesisAccount{
Address: acc.Address,
Coins: coins,

View File

@ -480,7 +480,7 @@ func TestGaiaCLISendGenerateSignAndBroadcast(t *testing.T) {
require.True(t, success)
require.Empty(t, stderr)
msg := unmarshalStdTx(t, stdout)
require.Equal(t, msg.Fee.Gas, int64(client.DefaultGasLimit))
require.Equal(t, msg.Fee.Gas, uint64(client.DefaultGasLimit))
require.Equal(t, len(msg.Msgs), 1)
require.Equal(t, 0, len(msg.GetSignatures()))
@ -491,7 +491,7 @@ func TestGaiaCLISendGenerateSignAndBroadcast(t *testing.T) {
require.True(t, success)
require.Empty(t, stderr)
msg = unmarshalStdTx(t, stdout)
require.Equal(t, msg.Fee.Gas, int64(100))
require.Equal(t, msg.Fee.Gas, uint64(100))
require.Equal(t, len(msg.Msgs), 1)
require.Equal(t, 0, len(msg.GetSignatures()))
@ -542,16 +542,19 @@ func TestGaiaCLISendGenerateSignAndBroadcast(t *testing.T) {
success, stdout, _ = executeWriteRetStdStreams(t, fmt.Sprintf(
"gaiacli tx broadcast %v --json %v", flags, signedTxFile.Name()))
require.True(t, success)
var result struct {
Response abci.ResponseDeliverTx
}
require.Nil(t, app.MakeCodec().UnmarshalJSON([]byte(stdout), &result))
require.Equal(t, msg.Fee.Gas, result.Response.GasUsed)
require.Equal(t, msg.Fee.Gas, result.Response.GasWanted)
require.Equal(t, msg.Fee.Gas, uint64(result.Response.GasUsed))
require.Equal(t, msg.Fee.Gas, uint64(result.Response.GasWanted))
tests.WaitForNextNBlocksTM(2, port)
barAcc := executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", barAddr, flags))
require.Equal(t, int64(10), barAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli query account %s %v", fooAddr, flags))
require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom).Int64())
}

View File

@ -1,64 +1,98 @@
package main
import (
"fmt"
"net/http"
"os"
"path"
"github.com/rakyll/statik/fs"
"github.com/spf13/cobra"
"github.com/spf13/viper"
amino "github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/libs/cli"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/client/lcd"
"github.com/cosmos/cosmos-sdk/client/rpc"
"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/cosmos/cosmos-sdk/cmd/gaia/app"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/version"
auth "github.com/cosmos/cosmos-sdk/x/auth/client/rest"
bank "github.com/cosmos/cosmos-sdk/x/bank/client/rest"
gov "github.com/cosmos/cosmos-sdk/x/gov/client/rest"
slashing "github.com/cosmos/cosmos-sdk/x/slashing/client/rest"
stake "github.com/cosmos/cosmos-sdk/x/stake/client/rest"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
distClient "github.com/cosmos/cosmos-sdk/x/distribution/client"
govClient "github.com/cosmos/cosmos-sdk/x/gov/client"
slashingClient "github.com/cosmos/cosmos-sdk/x/slashing/client"
stakeClient "github.com/cosmos/cosmos-sdk/x/stake/client"
_ "github.com/cosmos/cosmos-sdk/client/lcd/statik"
)
const (
storeAcc = "acc"
storeGov = "gov"
storeSlashing = "slashing"
storeStake = "stake"
queryRouteStake = "stake"
)
// rootCmd is the entry point for this binary
var (
rootCmd = &cobra.Command{
Use: "gaiacli",
Short: "Command line interface for interacting with gaiad",
}
storeAcc = "acc"
storeGov = "gov"
storeSlashing = "slashing"
storeStake = "stake"
storeDist = "distr"
)
func main() {
// Configure cobra to sort commands
cobra.EnableCommandSorting = false
// Instantiate the codec for the command line application
cdc := app.MakeCodec()
// Read in the configuration file for the sdk
config := sdk.GetConfig()
config.SetBech32PrefixForAccount(sdk.Bech32PrefixAccAddr, sdk.Bech32PrefixAccPub)
config.SetBech32PrefixForValidator(sdk.Bech32PrefixValAddr, sdk.Bech32PrefixValPub)
config.SetBech32PrefixForConsensusNode(sdk.Bech32PrefixConsAddr, sdk.Bech32PrefixConsPub)
config.Seal()
// Create a new RestServer instance to serve the light client routes
rs := lcd.NewRestServer(cdc)
// registerRoutes registers the routes on the rest server
registerRoutes(rs)
// TODO: setup keybase, viper object, etc. to be passed into
// the below functions and eliminate global vars, like we do
// with the cdc
// Module clients hold cli commnads (tx,query) and lcd routes
// TODO: Make the lcd command take a list of ModuleClient
mc := []sdk.ModuleClients{
govClient.NewModuleClient(storeGov, cdc),
distClient.NewModuleClient(storeDist, cdc),
stakeClient.NewModuleClient(storeStake, cdc),
slashingClient.NewModuleClient(storeSlashing, cdc),
}
rootCmd := &cobra.Command{
Use: "gaiacli",
Short: "Command line interface for interacting with gaiad",
}
// Construct Root Command
rootCmd.AddCommand(
rpc.InitClientCommand(),
rpc.StatusCommand(),
client.ConfigCmd(),
queryCmd(cdc),
txCmd(cdc),
queryCmd(cdc, mc),
txCmd(cdc, mc),
client.LineBreak,
lcd.ServeCommand(cdc),
rs.ServeCommand(),
client.LineBreak,
keys.Commands(),
client.LineBreak,
@ -74,9 +108,77 @@ func main() {
err = executor.Execute()
if err != nil {
// handle with #870
fmt.Printf("Failed executing CLI command: %s, exiting...\n", err)
os.Exit(1)
}
}
func queryCmd(cdc *amino.Codec, mc []sdk.ModuleClients) *cobra.Command {
queryCmd := &cobra.Command{
Use: "query",
Aliases: []string{"q"},
Short: "Querying subcommands",
}
queryCmd.AddCommand(
rpc.ValidatorCommand(),
rpc.BlockCommand(),
tx.SearchTxCmd(cdc),
tx.QueryTxCmd(cdc),
client.LineBreak,
authcmd.GetAccountCmd(storeAcc, cdc),
)
for _, m := range mc {
queryCmd.AddCommand(m.GetQueryCmd())
}
return queryCmd
}
func txCmd(cdc *amino.Codec, mc []sdk.ModuleClients) *cobra.Command {
txCmd := &cobra.Command{
Use: "tx",
Short: "Transactions subcommands",
}
txCmd.AddCommand(
bankcmd.SendTxCmd(cdc),
client.LineBreak,
authcmd.GetSignCommand(cdc),
bankcmd.GetBroadcastCommand(cdc),
client.LineBreak,
)
for _, m := range mc {
txCmd.AddCommand(m.GetTxCmd())
}
return txCmd
}
// registerRoutes registers the routes from the different modules for the LCD.
// NOTE: details on the routes added for each module are in the module documentation
// NOTE: If making updates here you also need to update the test helper in client/lcd/test_helper.go
func registerRoutes(rs *lcd.RestServer) {
registerSwaggerUI(rs)
keys.RegisterRoutes(rs.Mux, rs.CliCtx.Indent)
rpc.RegisterRoutes(rs.CliCtx, rs.Mux)
tx.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc)
auth.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, storeAcc)
bank.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
stake.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
slashing.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
gov.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc)
}
func registerSwaggerUI(rs *lcd.RestServer) {
statikFS, err := fs.New()
if err != nil {
panic(err)
}
staticServer := http.FileServer(statikFS)
rs.Mux.PathPrefix("/swagger-ui/").Handler(http.StripPrefix("/swagger-ui/", staticServer))
}
func initConfig(cmd *cobra.Command) error {

View File

@ -1,83 +0,0 @@
package main
import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/rpc"
"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/spf13/cobra"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
govcmd "github.com/cosmos/cosmos-sdk/x/gov/client/cli"
slashingcmd "github.com/cosmos/cosmos-sdk/x/slashing/client/cli"
stakecmd "github.com/cosmos/cosmos-sdk/x/stake/client/cli"
amino "github.com/tendermint/go-amino"
)
func queryCmd(cdc *amino.Codec) *cobra.Command {
//Add query commands
queryCmd := &cobra.Command{
Use: "query",
Aliases: []string{"q"},
Short: "Querying subcommands",
}
// Group staking queries under a subcommand
stakeQueryCmd := &cobra.Command{
Use: "stake",
Short: "Querying commands for the staking module",
}
stakeQueryCmd.AddCommand(client.GetCommands(
stakecmd.GetCmdQueryDelegation(storeStake, cdc),
stakecmd.GetCmdQueryDelegations(storeStake, cdc),
stakecmd.GetCmdQueryUnbondingDelegation(storeStake, cdc),
stakecmd.GetCmdQueryUnbondingDelegations(storeStake, cdc),
stakecmd.GetCmdQueryRedelegation(storeStake, cdc),
stakecmd.GetCmdQueryRedelegations(storeStake, cdc),
stakecmd.GetCmdQueryValidator(storeStake, cdc),
stakecmd.GetCmdQueryValidators(storeStake, cdc),
stakecmd.GetCmdQueryValidatorDelegations(storeStake, cdc),
stakecmd.GetCmdQueryValidatorUnbondingDelegations(queryRouteStake, cdc),
stakecmd.GetCmdQueryValidatorRedelegations(queryRouteStake, cdc),
stakecmd.GetCmdQueryParams(storeStake, cdc),
stakecmd.GetCmdQueryPool(storeStake, cdc))...)
// Group gov queries under a subcommand
govQueryCmd := &cobra.Command{
Use: "gov",
Short: "Querying commands for the governance module",
}
govQueryCmd.AddCommand(client.GetCommands(
govcmd.GetCmdQueryProposal(storeGov, cdc),
govcmd.GetCmdQueryProposals(storeGov, cdc),
govcmd.GetCmdQueryVote(storeGov, cdc),
govcmd.GetCmdQueryVotes(storeGov, cdc),
govcmd.GetCmdQueryParams(storeGov, cdc),
govcmd.GetCmdQueryDeposit(storeGov, cdc),
govcmd.GetCmdQueryDeposits(storeGov, cdc))...)
// Group slashing queries under a subcommand
slashingQueryCmd := &cobra.Command{
Use: "slashing",
Short: "Querying commands for the slashing module",
}
slashingQueryCmd.AddCommand(client.GetCommands(
slashingcmd.GetCmdQuerySigningInfo(storeSlashing, cdc))...)
// Query commcmmand structure
queryCmd.AddCommand(
rpc.BlockCommand(),
rpc.ValidatorCommand(),
tx.SearchTxCmd(cdc),
tx.QueryTxCmd(cdc),
client.LineBreak,
client.GetCommands(authcmd.GetAccountCmd(storeAcc, cdc, authcmd.GetAccountDecoder(cdc)))[0],
stakeQueryCmd,
govQueryCmd,
slashingQueryCmd,
)
return queryCmd
}

View File

@ -1,83 +0,0 @@
package main
import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/spf13/cobra"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
distrcmd "github.com/cosmos/cosmos-sdk/x/distribution/client/cli"
govcmd "github.com/cosmos/cosmos-sdk/x/gov/client/cli"
slashingcmd "github.com/cosmos/cosmos-sdk/x/slashing/client/cli"
stakecmd "github.com/cosmos/cosmos-sdk/x/stake/client/cli"
amino "github.com/tendermint/go-amino"
)
func txCmd(cdc *amino.Codec) *cobra.Command {
//Add transaction generation commands
txCmd := &cobra.Command{
Use: "tx",
Short: "Transactions subcommands",
}
stakeTxCmd := &cobra.Command{
Use: "stake",
Short: "Staking transaction subcommands",
}
stakeTxCmd.AddCommand(client.PostCommands(
stakecmd.GetCmdCreateValidator(cdc),
stakecmd.GetCmdEditValidator(cdc),
stakecmd.GetCmdDelegate(cdc),
stakecmd.GetCmdRedelegate(storeStake, cdc),
stakecmd.GetCmdUnbond(storeStake, cdc),
)...)
distTxCmd := &cobra.Command{
Use: "dist",
Short: "Distribution transactions subcommands",
}
distTxCmd.AddCommand(client.PostCommands(
distrcmd.GetCmdWithdrawRewards(cdc),
distrcmd.GetCmdSetWithdrawAddr(cdc),
)...)
govTxCmd := &cobra.Command{
Use: "gov",
Short: "Governance transactions subcommands",
}
govTxCmd.AddCommand(client.PostCommands(
govcmd.GetCmdDeposit(cdc),
govcmd.GetCmdVote(cdc),
govcmd.GetCmdSubmitProposal(cdc),
)...)
slashingTxCmd := &cobra.Command{
Use: "slashing",
Short: "Slashing transactions subcommands",
}
slashingTxCmd.AddCommand(client.PostCommands(
slashingcmd.GetCmdUnjail(cdc),
)...)
txCmd.AddCommand(
//Add auth and bank commands
client.PostCommands(
bankcmd.SendTxCmd(cdc),
bankcmd.GetBroadcastCommand(cdc),
authcmd.GetSignCommand(cdc, authcmd.GetAccountDecoder(cdc)),
)...)
txCmd.AddCommand(
client.LineBreak,
stakeTxCmd,
distTxCmd,
govTxCmd,
slashingTxCmd,
)
return txCmd
}

View File

@ -175,8 +175,8 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.BaseAp
// add handlers
app.bankKeeper = bank.NewBaseKeeper(app.accountKeeper)
app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams, app.tkeyParams)
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.tkeyStake, app.bankKeeper, app.paramsKeeper.Subspace(stake.DefaultParamspace), app.RegisterCodespace(stake.DefaultCodespace))
app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Subspace(slashing.DefaultParamspace), app.RegisterCodespace(slashing.DefaultCodespace))
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.tkeyStake, app.bankKeeper, app.paramsKeeper.Subspace(stake.DefaultParamspace), stake.DefaultCodespace)
app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Subspace(slashing.DefaultParamspace), slashing.DefaultCodespace)
// register message routes
app.Router().

View File

@ -25,14 +25,14 @@ func TestAddGenesisAccount(t *testing.T) {
}{
{
"valid account",
args{
app.GenesisState{},
addr1,
sdk.Coins{},
},
false},
args{
app.GenesisState{},
addr1,
sdk.Coins{},
},
false},
{"dup account", args{
app.GenesisState{Accounts: []app.GenesisAccount{app.GenesisAccount{Address:addr1}}},
app.GenesisState{Accounts: []app.GenesisAccount{{Address: addr1}}},
addr1,
sdk.Coins{}}, true},
}

View File

@ -2,6 +2,10 @@ package init
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/cmd/gaia/app"
@ -17,9 +21,6 @@ import (
"github.com/tendermint/tendermint/crypto"
tmcli "github.com/tendermint/tendermint/libs/cli"
"github.com/tendermint/tendermint/libs/common"
"io/ioutil"
"os"
"path/filepath"
)
const (
@ -94,7 +95,7 @@ following delegation and commission default parameters:
w.Close()
prepareFlagsForTxSign()
signCmd := authcmd.GetSignCommand(cdc, authcmd.GetAccountDecoder(cdc))
signCmd := authcmd.GetSignCommand(cdc)
if w, err = prepareOutputFile(config.RootDir, nodeID); err != nil {
return err
}

View File

@ -12,7 +12,8 @@ import (
)
const (
app1Name = "App1"
app1Name = "App1"
bankCodespace = "BANK"
)
func NewApp1(logger log.Logger, db dbm.DB) *bapp.BaseApp {
@ -107,7 +108,7 @@ func handleMsgSend(key *sdk.KVStoreKey) sdk.Handler {
if !ok {
// Create custom error message and return result
// Note: Using unreserved error codespace
return sdk.NewError(2, 1, "MsgSend is malformed").Result()
return sdk.NewError(bankCodespace, 1, "MsgSend is malformed").Result()
}
// Load the store.
@ -137,7 +138,7 @@ func handleFrom(store sdk.KVStore, from sdk.AccAddress, amt sdk.Coins) sdk.Resul
accBytes := store.Get(from)
if accBytes == nil {
// Account was not added to store. Return the result of the error.
return sdk.NewError(2, 101, "Account not added to store").Result()
return sdk.NewError(bankCodespace, 101, "Account not added to store").Result()
}
// Unmarshal the JSON account bytes.

View File

@ -126,7 +126,7 @@ func handleMsgIssue(keyIssue *sdk.KVStoreKey, keyAcc *sdk.KVStoreKey) sdk.Handle
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
issueMsg, ok := msg.(MsgIssue)
if !ok {
return sdk.NewError(2, 1, "MsgIssue is malformed").Result()
return sdk.NewError(bankCodespace, 1, "MsgIssue is malformed").Result()
}
// Retrieve stores

View File

@ -20,7 +20,7 @@ func TestEncoding(t *testing.T) {
sendMsg := MsgSend{
From: addr1,
To: addr2,
Amount: sdk.Coins{{"testCoins", sdk.NewInt(100)}},
Amount: sdk.Coins{sdk.NewCoin("testCoins", sdk.NewInt(100))},
}
// Construct transaction

View File

@ -30,7 +30,7 @@ func InitTestChain(bc *bapp.BaseApp, chainID string, addrs ...sdk.AccAddress) {
for _, addr := range addrs {
acc := GenesisAccount{
Address: addr,
Coins: sdk.Coins{{"testCoin", sdk.NewInt(100)}},
Coins: sdk.Coins{sdk.NewCoin("testCoin", sdk.NewInt(100))},
}
accounts = append(accounts, &acc)
}
@ -61,12 +61,12 @@ func TestBadMsg(t *testing.T) {
addr2 := priv2.PubKey().Address().Bytes()
// Attempt to spend non-existent funds
msg := GenerateSpendMsg(addr1, addr2, sdk.Coins{{"testCoin", sdk.NewInt(100)}})
msg := GenerateSpendMsg(addr1, addr2, sdk.Coins{sdk.NewCoin("testCoin", sdk.NewInt(100))})
// Construct transaction
fee := auth.StdFee{
Gas: 1000000000000000,
Amount: sdk.Coins{{"testCoin", sdk.NewInt(0)}},
Amount: sdk.Coins{sdk.NewCoin("testCoin", sdk.NewInt(0))},
}
signBytes := auth.StdSignBytes("test-chain", 0, 0, fee, []sdk.Msg{msg}, "")
sig, err := priv1.Sign(signBytes)
@ -108,11 +108,11 @@ func TestMsgSend(t *testing.T) {
InitTestChain(bc, "test-chain", addr1)
// Send funds to addr2
msg := GenerateSpendMsg(addr1, addr2, sdk.Coins{{"testCoin", sdk.NewInt(100)}})
msg := GenerateSpendMsg(addr1, addr2, sdk.Coins{sdk.NewCoin("testCoin", sdk.NewInt(100))})
fee := auth.StdFee{
Gas: 1000000000000000,
Amount: sdk.Coins{{"testCoin", sdk.NewInt(0)}},
Amount: sdk.Coins{sdk.NewCoin("testCoin", sdk.NewInt(0))},
}
signBytes := auth.StdSignBytes("test-chain", 0, 0, fee, []sdk.Msg{msg}, "")
sig, err := priv1.Sign(signBytes)

View File

@ -75,7 +75,7 @@ func NewBasecoinApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.Ba
},
)
app.bankKeeper = bank.NewBaseKeeper(app.accountKeeper)
app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace))
app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, ibc.DefaultCodespace)
// register message routes
app.Router().

View File

@ -8,17 +8,28 @@ import (
"github.com/cosmos/cosmos-sdk/client/rpc"
"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/cosmos/cosmos-sdk/docs/examples/basecoin/app"
"github.com/cosmos/cosmos-sdk/docs/examples/basecoin/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/version"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
auth "github.com/cosmos/cosmos-sdk/x/auth/client/rest"
bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
bank "github.com/cosmos/cosmos-sdk/x/bank/client/rest"
ibccmd "github.com/cosmos/cosmos-sdk/x/ibc/client/cli"
slashingcmd "github.com/cosmos/cosmos-sdk/x/slashing/client/cli"
slashing "github.com/cosmos/cosmos-sdk/x/slashing/client/rest"
stakecmd "github.com/cosmos/cosmos-sdk/x/stake/client/cli"
stake "github.com/cosmos/cosmos-sdk/x/stake/client/rest"
"github.com/spf13/cobra"
"github.com/tendermint/tendermint/libs/cli"
)
const (
storeAcc = "acc"
storeSlashing = "slashing"
storeStake = "stake"
)
// rootCmd is the entry point for this binary
var (
rootCmd = &cobra.Command{
@ -34,6 +45,17 @@ func main() {
// get the codec
cdc := app.MakeCodec()
// Setup certain SDK config
config := sdk.GetConfig()
config.SetBech32PrefixForAccount("baseacc", "basepub")
config.SetBech32PrefixForValidator("baseval", "basevalpub")
config.SetBech32PrefixForConsensusNode("basecons", "baseconspub")
config.Seal()
rs := lcd.NewRestServer(cdc)
registerRoutes(rs)
// TODO: Setup keybase, viper object, etc. to be passed into
// the below functions and eliminate global vars, like we do
// with the cdc.
@ -51,20 +73,20 @@ func main() {
// add query/post commands (custom to binary)
rootCmd.AddCommand(
client.GetCommands(
stakecmd.GetCmdQueryValidator("stake", cdc),
stakecmd.GetCmdQueryValidators("stake", cdc),
stakecmd.GetCmdQueryValidatorUnbondingDelegations("stake", cdc),
stakecmd.GetCmdQueryValidatorRedelegations("stake", cdc),
stakecmd.GetCmdQueryDelegation("stake", cdc),
stakecmd.GetCmdQueryDelegations("stake", cdc),
stakecmd.GetCmdQueryPool("stake", cdc),
stakecmd.GetCmdQueryParams("stake", cdc),
stakecmd.GetCmdQueryUnbondingDelegation("stake", cdc),
stakecmd.GetCmdQueryUnbondingDelegations("stake", cdc),
stakecmd.GetCmdQueryRedelegation("stake", cdc),
stakecmd.GetCmdQueryRedelegations("stake", cdc),
slashingcmd.GetCmdQuerySigningInfo("slashing", cdc),
authcmd.GetAccountCmd("acc", cdc, types.GetAccountDecoder(cdc)),
stakecmd.GetCmdQueryValidator(storeStake, cdc),
stakecmd.GetCmdQueryValidators(storeStake, cdc),
stakecmd.GetCmdQueryValidatorUnbondingDelegations(storeStake, cdc),
stakecmd.GetCmdQueryValidatorRedelegations(storeStake, cdc),
stakecmd.GetCmdQueryDelegation(storeStake, cdc),
stakecmd.GetCmdQueryDelegations(storeStake, cdc),
stakecmd.GetCmdQueryPool(storeStake, cdc),
stakecmd.GetCmdQueryParams(storeStake, cdc),
stakecmd.GetCmdQueryUnbondingDelegation(storeStake, cdc),
stakecmd.GetCmdQueryUnbondingDelegations(storeStake, cdc),
stakecmd.GetCmdQueryRedelegation(storeStake, cdc),
stakecmd.GetCmdQueryRedelegations(storeStake, cdc),
slashingcmd.GetCmdQuerySigningInfo(storeSlashing, cdc),
authcmd.GetAccountCmd(storeAcc, cdc),
)...)
rootCmd.AddCommand(
@ -75,15 +97,15 @@ func main() {
stakecmd.GetCmdCreateValidator(cdc),
stakecmd.GetCmdEditValidator(cdc),
stakecmd.GetCmdDelegate(cdc),
stakecmd.GetCmdUnbond("stake", cdc),
stakecmd.GetCmdRedelegate("stake", cdc),
stakecmd.GetCmdUnbond(storeStake, cdc),
stakecmd.GetCmdRedelegate(storeStake, cdc),
slashingcmd.GetCmdUnjail(cdc),
)...)
// add proxy, version and key info
rootCmd.AddCommand(
client.LineBreak,
lcd.ServeCommand(cdc),
rs.ServeCommand(),
keys.Commands(),
client.LineBreak,
version.VersionCmd,
@ -97,3 +119,13 @@ func main() {
panic(err)
}
}
func registerRoutes(rs *lcd.RestServer) {
keys.RegisterRoutes(rs.Mux, rs.CliCtx.Indent)
rpc.RegisterRoutes(rs.CliCtx, rs.Mux)
tx.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc)
auth.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, storeAcc)
bank.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
stake.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
slashing.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
}

View File

@ -83,10 +83,10 @@ func NewDemocoinApp(logger log.Logger, db dbm.DB) *DemocoinApp {
// Add handlers.
app.bankKeeper = bank.NewBaseKeeper(app.accountKeeper)
app.coolKeeper = cool.NewKeeper(app.capKeyMainStore, app.bankKeeper, app.RegisterCodespace(cool.DefaultCodespace))
app.powKeeper = pow.NewKeeper(app.capKeyPowStore, pow.NewConfig("pow", int64(1)), app.bankKeeper, app.RegisterCodespace(pow.DefaultCodespace))
app.ibcMapper = ibc.NewMapper(app.cdc, app.capKeyIBCStore, app.RegisterCodespace(ibc.DefaultCodespace))
app.stakeKeeper = simplestake.NewKeeper(app.capKeyStakingStore, app.bankKeeper, app.RegisterCodespace(simplestake.DefaultCodespace))
app.coolKeeper = cool.NewKeeper(app.capKeyMainStore, app.bankKeeper, cool.DefaultCodespace)
app.powKeeper = pow.NewKeeper(app.capKeyPowStore, pow.NewConfig("pow", int64(1)), app.bankKeeper, pow.DefaultCodespace)
app.ibcMapper = ibc.NewMapper(app.cdc, app.capKeyIBCStore, ibc.DefaultCodespace)
app.stakeKeeper = simplestake.NewKeeper(app.capKeyStakingStore, app.bankKeeper, simplestake.DefaultCodespace)
app.Router().
AddRoute("bank", bank.NewHandler(app.bankKeeper)).
AddRoute("cool", cool.NewHandler(app.coolKeeper)).

View File

@ -13,11 +13,11 @@ import (
"github.com/cosmos/cosmos-sdk/version"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
auth "github.com/cosmos/cosmos-sdk/x/auth/client/rest"
bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
ibccmd "github.com/cosmos/cosmos-sdk/x/ibc/client/cli"
bank "github.com/cosmos/cosmos-sdk/x/bank/client/rest"
"github.com/cosmos/cosmos-sdk/docs/examples/democoin/app"
"github.com/cosmos/cosmos-sdk/docs/examples/democoin/types"
coolcmd "github.com/cosmos/cosmos-sdk/docs/examples/democoin/x/cool/client/cli"
powcmd "github.com/cosmos/cosmos-sdk/docs/examples/democoin/x/pow/client/cli"
simplestakingcmd "github.com/cosmos/cosmos-sdk/docs/examples/democoin/x/simplestake/client/cli"
@ -31,6 +31,7 @@ var (
Use: "democli",
Short: "Democoin light-client",
}
storeAcc = "acc"
)
func main() {
@ -47,6 +48,10 @@ func main() {
config.SetBech32PrefixForConsensusNode("democons", "democonspub")
config.Seal()
rs := lcd.NewRestServer(cdc)
registerRoutes(rs)
// TODO: setup keybase, viper object, etc. to be passed into
// the below functions and eliminate global vars, like we do
// with the cdc
@ -66,7 +71,7 @@ func main() {
// start with commands common to basecoin
rootCmd.AddCommand(
client.GetCommands(
authcmd.GetAccountCmd("acc", cdc, types.GetAccountDecoder(cdc)),
authcmd.GetAccountCmd(storeAcc, cdc),
)...)
rootCmd.AddCommand(
client.PostCommands(
@ -74,11 +79,6 @@ func main() {
)...)
rootCmd.AddCommand(
client.PostCommands(
ibccmd.IBCTransferCmd(cdc),
)...)
rootCmd.AddCommand(
client.PostCommands(
ibccmd.IBCRelayCmd(cdc),
simplestakingcmd.BondTxCmd(cdc),
)...)
rootCmd.AddCommand(
@ -96,7 +96,7 @@ func main() {
// add proxy, version and key info
rootCmd.AddCommand(
client.LineBreak,
lcd.ServeCommand(cdc),
rs.ServeCommand(),
keys.Commands(),
client.LineBreak,
version.VersionCmd,
@ -110,3 +110,11 @@ func main() {
panic(err)
}
}
func registerRoutes(rs *lcd.RestServer) {
keys.RegisterRoutes(rs.Mux, rs.CliCtx.Indent)
rpc.RegisterRoutes(rs.CliCtx, rs.Mux)
tx.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc)
auth.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, storeAcc)
bank.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
}

View File

@ -30,7 +30,6 @@ const (
flagClientHome = "home-client"
)
// coolGenAppParams sets up the app_state and appends the cool app state
func CoolAppGenState(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []json.RawMessage) (
appState json.RawMessage, err error) {

View File

@ -50,7 +50,7 @@ func getMockApp(t *testing.T) *mock.App {
RegisterCodec(mapp.Cdc)
keyCool := sdk.NewKVStoreKey("cool")
bankKeeper := bank.NewBaseKeeper(mapp.AccountKeeper)
keeper := NewKeeper(keyCool, bankKeeper, mapp.RegisterCodespace(DefaultCodespace))
keeper := NewKeeper(keyCool, bankKeeper, DefaultCodespace)
mapp.Router().AddRoute("cool", NewHandler(keeper))
mapp.SetInitChainer(getInitChainer(mapp, keeper, "ice-cold"))
@ -90,15 +90,15 @@ func TestMsgQuiz(t *testing.T) {
// Set the trend, submit a really cool quiz and check for reward
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{setTrendMsg1}, []int64{0}, []int64{0}, true, true, priv1)
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{quizMsg1}, []int64{0}, []int64{1}, true, true, priv1)
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"icecold", sdk.NewInt(69)}})
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("icecold", sdk.NewInt(69))})
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{quizMsg2}, []int64{0}, []int64{2}, false, false, priv1) // result without reward
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"icecold", sdk.NewInt(69)}})
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("icecold", sdk.NewInt(69))})
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{quizMsg1}, []int64{0}, []int64{3}, true, true, priv1)
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"icecold", sdk.NewInt(138)}})
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("icecold", sdk.NewInt(138))})
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{setTrendMsg2}, []int64{0}, []int64{4}, true, true, priv1) // reset the trend
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{quizMsg1}, []int64{0}, []int64{5}, false, false, priv1) // the same answer will nolonger do!
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"icecold", sdk.NewInt(138)}})
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("icecold", sdk.NewInt(138))})
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{quizMsg2}, []int64{0}, []int64{6}, true, true, priv1) // earlier answer now relevant again
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"badvibesonly", sdk.NewInt(69)}, {"icecold", sdk.NewInt(138)}})
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("badvibesonly", sdk.NewInt(69)), sdk.NewCoin("icecold", sdk.NewInt(138))})
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{setTrendMsg3}, []int64{0}, []int64{7}, false, false, priv1) // expect to fail to set the trend to something which is not cool
}

View File

@ -8,7 +8,6 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/docs/examples/democoin/x/cool"
sdk "github.com/cosmos/cosmos-sdk/types"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
)
@ -22,7 +21,7 @@ func QuizTxCmd(cdc *codec.Codec) *cobra.Command {
txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc)
cliCtx := context.NewCLIContext().
WithCodec(cdc).
WithAccountDecoder(authcmd.GetAccountDecoder(cdc))
WithAccountDecoder(cdc)
from, err := cliCtx.GetFromAddress()
if err != nil {
@ -46,7 +45,7 @@ func SetTrendTxCmd(cdc *codec.Codec) *cobra.Command {
txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc)
cliCtx := context.NewCLIContext().
WithCodec(cdc).
WithAccountDecoder(authcmd.GetAccountDecoder(cdc))
WithAccountDecoder(cdc)
from, err := cliCtx.GetFromAddress()
if err != nil {

View File

@ -8,7 +8,7 @@ import (
// Cool errors reserve 400 ~ 499.
const (
DefaultCodespace sdk.CodespaceType = 6
DefaultCodespace sdk.CodespaceType = "cool"
// Cool module reserves error 400-499 lawl
CodeIncorrectCoolAnswer sdk.CodeType = 400

View File

@ -94,7 +94,7 @@ func (keeper Keeper) Handle(h Handler, ctx sdk.Context, o Msg, codespace sdk.Cod
err := h(cctx, payload)
if err != nil {
return sdk.Result{
Code: sdk.ABCICodeOK,
Code: sdk.CodeOK,
Log: err.ABCILog(),
}
}

View File

@ -27,7 +27,7 @@ func getMockApp(t *testing.T) *mock.App {
keyPOW := sdk.NewKVStoreKey("pow")
bankKeeper := bank.NewBaseKeeper(mapp.AccountKeeper)
config := Config{"pow", 1}
keeper := NewKeeper(keyPOW, config, bankKeeper, mapp.RegisterCodespace(DefaultCodespace))
keeper := NewKeeper(keyPOW, config, bankKeeper, DefaultCodespace)
mapp.Router().AddRoute("pow", keeper.Handler)
mapp.SetInitChainer(getInitChainer(mapp, keeper))
@ -75,12 +75,12 @@ func TestMsgMine(t *testing.T) {
// Mine and check for reward
mineMsg1 := GenerateMsgMine(addr1, 1, 2)
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{mineMsg1}, []int64{0}, []int64{0}, true, true, priv1)
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"pow", sdk.NewInt(1)}})
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("pow", sdk.NewInt(1))})
// Mine again and check for reward
mineMsg2 := GenerateMsgMine(addr1, 2, 3)
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{mineMsg2}, []int64{0}, []int64{1}, true, true, priv1)
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"pow", sdk.NewInt(2)}})
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("pow", sdk.NewInt(2))})
// Mine again - should be invalid
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{mineMsg2}, []int64{0}, []int64{1}, false, false, priv1)
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"pow", sdk.NewInt(2)}})
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("pow", sdk.NewInt(2))})
}

View File

@ -8,7 +8,6 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/docs/examples/democoin/x/pow"
sdk "github.com/cosmos/cosmos-sdk/types"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
"github.com/spf13/cobra"
@ -24,7 +23,7 @@ func MineCmd(cdc *codec.Codec) *cobra.Command {
txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc)
cliCtx := context.NewCLIContext().
WithCodec(cdc).
WithAccountDecoder(authcmd.GetAccountDecoder(cdc))
WithAccountDecoder(cdc)
from, err := cliCtx.GetFromAddress()
if err != nil {

View File

@ -9,7 +9,7 @@ type CodeType = sdk.CodeType
// POW errors reserve 200 ~ 299
const (
DefaultCodespace sdk.CodespaceType = 5
DefaultCodespace sdk.CodespaceType = "pow"
CodeInvalidDifficulty CodeType = 201
CodeNonexistentDifficulty CodeType = 202
CodeNonexistentReward CodeType = 203

View File

@ -9,7 +9,6 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/docs/examples/democoin/x/simplestake"
sdk "github.com/cosmos/cosmos-sdk/types"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
"github.com/spf13/cobra"
@ -32,7 +31,7 @@ func BondTxCmd(cdc *codec.Codec) *cobra.Command {
txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc)
cliCtx := context.NewCLIContext().
WithCodec(cdc).
WithAccountDecoder(authcmd.GetAccountDecoder(cdc))
WithAccountDecoder(cdc)
from, err := cliCtx.GetFromAddress()
if err != nil {

View File

@ -6,7 +6,7 @@ import (
// simple stake errors reserve 300 ~ 399.
const (
DefaultCodespace sdk.CodespaceType = 4
DefaultCodespace sdk.CodespaceType = moduleName
// simplestake errors reserve 300 - 399.
CodeEmptyValidator sdk.CodeType = 300

View File

@ -22,12 +22,12 @@ func handleMsgBond() sdk.Result {
// Removed ValidatorSet from result because it does not get used.
// TODO: Implement correct bond/unbond handling
return sdk.Result{
Code: sdk.ABCICodeOK,
Code: sdk.CodeOK,
}
}
func handleMsgUnbond() sdk.Result {
return sdk.Result{
Code: sdk.ABCICodeOK,
Code: sdk.CodeOK,
}
}

View File

@ -63,7 +63,7 @@ principle:
type AppAccount struct {...}
var account := &AppAccount{
Address: pub.Address(),
Coins: sdk.Coins{{"ATM", 100}},
Coins: sdk.Coins{sdk.NewInt64Coin("ATM", 100)},
}
var sumValue := externalModule.ComputeSumValue(account)
```

View File

@ -1,13 +1,63 @@
# baseApp
# BaseApp
`baseApp` requires stores to be mounted via capabilities keys - handlers can only access stores they're given the key to. The `baseApp` ensures all stores are properly loaded, cached, and committed. One mounted store is considered the "main" - it holds the latest block header, from which we can find and load the most recent state.
The BaseApp defines the foundational implementation for a basic ABCI application
so that your Cosmos-SDK application can communicate with an underlying
Tendermint node.
`baseApp` distinguishes between two handler types: `AnteHandler` and `MsgHandler`. Whilst the former is a global validity check that applies to all transactions from all modules, i.e. it checks nonces and whether balances are sufficient to pay fees, validates signatures and ensures that transactions don't carry too many signatures, the latter is the full state transition function.
During CheckTx the state transition function is only applied to the checkTxState and should return
before any expensive state transitions are run (this is up to each developer). It also needs to return the estimated
gas cost.
The BaseApp is composed of many internal components. Some of the most important
include the `CommitMultiStore` and its internal state. The internal state is
essentially two sub-states, both of which are used for transaction execution
during different phases, `CheckTx` and `DeliverTx` respectively. During block
commitment, only the `DeliverTx` is persisted.
During DeliverTx the state transition function is applied to the blockchain state and the transactions
need to be fully executed.
The BaseApp requires stores to be mounted via capabilities keys - handlers can
only access stores they're given the key to. The `baseApp` ensures all stores are
properly loaded, cached, and committed. One mounted store is considered the
"main" - it holds the latest block header, from which we can find and load the
most recent state.
BaseApp is responsible for managing the context passed into handlers - it makes the block header available and provides the right stores for CheckTx and DeliverTx. BaseApp is completely agnostic to serialization formats.
The BaseApp distinguishes between two handler types - the `AnteHandler` and the
`MsgHandler`. The former is a global validity check (checking nonces, sigs and
sufficient balances to pay fees, e.g. things that apply to all transaction from
all modules), the later is the full state transition function.
During `CheckTx` the state transition function is only applied to the `checkTxState`
and should return before any expensive state transitions are run
(this is up to each developer). It also needs to return the estimated gas cost.
During `DeliverTx` the state transition function is applied to the blockchain
state and the transactions need to be fully executed.
The BaseApp is responsible for managing the context passed into handlers -
it makes the block header available and provides the right stores for `CheckTx`
and `DeliverTx`. BaseApp is completely agnostic to serialization formats.
## Transaction Life Cycle
During the execution of a transaction, it may pass through both `CheckTx` and
`DeliverTx` as defined in the ABCI specification. `CheckTx` is executed by the
proposing validator and is used for the Tendermint mempool for all full nodes.
Both `CheckTx` and `DeliverTx` execute the application's AnteHandler (if
defined), where the AnteHandler is responsible for pre-message validation
checks such as account and signature validation, fee deduction and collection,
and incrementing sequence numbers.
### CheckTx
During the execution of `CheckTx`, only the AnteHandler is executed.
State transitions due to the AnteHandler are persisted between subsequent calls
of `CheckTx` in the check-tx state, unless the AnteHandler fails and aborts.
### DeliverTx
During the execution of `DeliverTx`, the AnteHandler and Handler is executed.
The transaction execution during `DeliverTx` operates in a similar fashion to
`CheckTx`. However, state transitions that occur during the AnteHandler are
persisted even when the following Handler processing logic fails.
It is possible that a malicious proposer may include a transaction in a block
that fails the AnteHandler. In this case, all state transitions for the
offending transaction are discarded.

View File

@ -3,4 +3,4 @@
Here contains the files required for automated deployment of either local or remote testnets.
Doing so is best accomplished using the `make` targets. For more information, see the
[networks documentation](/docs/getting-started/networks.md)
[networks documentation](/docs/gaia/networks.md)

View File

@ -15,7 +15,6 @@ import (
tmtypes "github.com/tendermint/tendermint/types"
)
// SimpleGenTx is a simple genesis tx
type SimpleGenTx struct {
Addr sdk.AccAddress `json:"addr"`
@ -23,7 +22,6 @@ type SimpleGenTx struct {
//_____________________________________________________________________
// Generate a genesis transaction
func SimpleAppGenTx(cdc *codec.Codec, pk crypto.PubKey) (
appGenTx, cliPrint json.RawMessage, validator types.GenesisValidator, err error) {

View File

@ -11,6 +11,8 @@ import (
// cacheMultiStore holds many cache-wrapped stores.
// Implements MultiStore.
// NOTE: a cacheMultiStore (and MultiStores in general) should never expose the
// keys for the substores.
type cacheMultiStore struct {
db CacheKVStore
stores map[StoreKey]CacheWrap

View File

@ -73,15 +73,15 @@ func testGasKVStoreWrap(t *testing.T, store KVStore) {
meter := sdk.NewGasMeter(10000)
store = store.Gas(meter, sdk.GasConfig{HasCost: 10})
require.Equal(t, int64(0), meter.GasConsumed())
require.Equal(t, uint64(0), meter.GasConsumed())
store.Has([]byte("key"))
require.Equal(t, int64(10), meter.GasConsumed())
require.Equal(t, uint64(10), meter.GasConsumed())
store = store.Gas(meter, sdk.GasConfig{HasCost: 20})
store.Has([]byte("key"))
require.Equal(t, int64(40), meter.GasConsumed())
require.Equal(t, uint64(40), meter.GasConsumed())
}
func TestGasKVStoreWrap(t *testing.T) {

View File

@ -156,34 +156,37 @@ func TestMultiStoreQuery(t *testing.T) {
// Test bad path.
query := abci.RequestQuery{Path: "/key", Data: k, Height: ver}
qres := multi.Query(query)
require.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnknownRequest), sdk.ABCICodeType(qres.Code))
require.EqualValues(t, sdk.CodeUnknownRequest, qres.Code)
require.EqualValues(t, sdk.CodespaceRoot, qres.Codespace)
query.Path = "h897fy32890rf63296r92"
qres = multi.Query(query)
require.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnknownRequest), sdk.ABCICodeType(qres.Code))
require.EqualValues(t, sdk.CodeUnknownRequest, qres.Code)
require.EqualValues(t, sdk.CodespaceRoot, qres.Codespace)
// Test invalid store name.
query.Path = "/garbage/key"
qres = multi.Query(query)
require.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnknownRequest), sdk.ABCICodeType(qres.Code))
require.EqualValues(t, sdk.CodeUnknownRequest, qres.Code)
require.EqualValues(t, sdk.CodespaceRoot, qres.Codespace)
// Test valid query with data.
query.Path = "/store1/key"
qres = multi.Query(query)
require.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeOK), sdk.ABCICodeType(qres.Code))
require.EqualValues(t, sdk.CodeOK, qres.Code)
require.Equal(t, v, qres.Value)
// Test valid but empty query.
query.Path = "/store2/key"
query.Prove = true
qres = multi.Query(query)
require.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeOK), sdk.ABCICodeType(qres.Code))
require.EqualValues(t, sdk.CodeOK, qres.Code)
require.Nil(t, qres.Value)
// Test store2 data.
query.Data = k2
qres = multi.Query(query)
require.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeOK), sdk.ABCICodeType(qres.Code))
require.EqualValues(t, sdk.CodeOK, qres.Code)
require.Equal(t, v2, qres.Value)
}

View File

@ -1,35 +0,0 @@
package types
// Codespacer is a simple struct to track reserved codespaces
type Codespacer struct {
reserved map[CodespaceType]bool
}
// NewCodespacer generates a new Codespacer with the starting codespace
func NewCodespacer() *Codespacer {
return &Codespacer{
reserved: make(map[CodespaceType]bool),
}
}
// RegisterNext reserves and returns the next available codespace, starting from a default, and panics if the maximum codespace is reached
func (c *Codespacer) RegisterNext(codespace CodespaceType) CodespaceType {
for {
if !c.reserved[codespace] {
c.reserved[codespace] = true
return codespace
}
codespace++
if codespace == MaximumCodespace {
panic("Maximum codespace reached!")
}
}
}
// RegisterOrPanic reserved a codespace or panics if it is unavailable
func (c *Codespacer) RegisterOrPanic(codespace CodespaceType) {
if c.reserved[codespace] {
panic("Cannot register codespace, already reserved")
}
c.reserved[codespace] = true
}

View File

@ -1,47 +0,0 @@
package types
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestRegisterNext(t *testing.T) {
codespacer := NewCodespacer()
// unregistered, allow
code1 := codespacer.RegisterNext(CodespaceType(2))
require.Equal(t, code1, CodespaceType(2))
// registered, pick next
code2 := codespacer.RegisterNext(CodespaceType(2))
require.Equal(t, code2, CodespaceType(3))
// pick next
code3 := codespacer.RegisterNext(CodespaceType(2))
require.Equal(t, code3, CodespaceType(4))
// skip 1
code4 := codespacer.RegisterNext(CodespaceType(6))
require.Equal(t, code4, CodespaceType(6))
code5 := codespacer.RegisterNext(CodespaceType(2))
require.Equal(t, code5, CodespaceType(5))
code6 := codespacer.RegisterNext(CodespaceType(2))
require.Equal(t, code6, CodespaceType(7))
// panic on maximum
defer func() {
r := recover()
require.NotNil(t, r, "Did not panic on maximum codespace")
}()
codespacer.RegisterNext(MaximumCodespace - 1)
codespacer.RegisterNext(MaximumCodespace - 1)
}
func TestRegisterOrPanic(t *testing.T) {
codespacer := NewCodespacer()
// unregistered, allow
code1 := codespacer.RegisterNext(CodespaceType(2))
require.Equal(t, code1, CodespaceType(2))
// panic on duplicate
defer func() {
r := recover()
require.NotNil(t, r, "Did not panic on duplicate codespace")
}()
codespacer.RegisterOrPanic(CodespaceType(2))
}

View File

@ -4,23 +4,41 @@ import (
"fmt"
"regexp"
"sort"
"strconv"
"strings"
)
// Coin hold some amount of one currency
//-----------------------------------------------------------------------------
// Coin
// Coin hold some amount of one currency.
//
// CONTRACT: A coin will never hold a negative amount of any denomination.
//
// TODO: Make field members private for further safety.
type Coin struct {
Denom string `json:"denom"`
Amount Int `json:"amount"`
Denom string `json:"denom"`
// To allow the use of unsigned integers (see: #1273) a larger refactor will
// need to be made. So we use signed integers for now with safety measures in
// place preventing negative values being used.
Amount Int `json:"amount"`
}
// NewCoin returns a new coin with a denomination and amount. It will panic if
// the amount is negative.
func NewCoin(denom string, amount Int) Coin {
if amount.LT(ZeroInt()) {
panic("negative coin amount")
}
return Coin{
Denom: denom,
Amount: amount,
}
}
// NewInt64Coin returns a new coin with a denomination and amount. It will panic
// if the amount is negative.
func NewInt64Coin(denom string, amount int64) Coin {
return NewCoin(denom, NewInt(amount))
}
@ -57,33 +75,46 @@ func (coin Coin) IsEqual(other Coin) bool {
return coin.SameDenomAs(other) && (coin.Amount.Equal(other.Amount))
}
// IsPositive returns true if coin amount is positive
// Adds amounts of two coins with same denom. If the coins differ in denom then
// it panics.
func (coin Coin) Plus(coinB Coin) Coin {
if !coin.SameDenomAs(coinB) {
panic(fmt.Sprintf("invalid coin denominations; %s, %s", coin.Denom, coinB.Denom))
}
return Coin{coin.Denom, coin.Amount.Add(coinB.Amount)}
}
// Subtracts amounts of two coins with same denom. If the coins differ in denom
// then it panics.
func (coin Coin) Minus(coinB Coin) Coin {
if !coin.SameDenomAs(coinB) {
panic(fmt.Sprintf("invalid coin denominations; %s, %s", coin.Denom, coinB.Denom))
}
res := Coin{coin.Denom, coin.Amount.Sub(coinB.Amount)}
if !res.IsNotNegative() {
panic("negative count amount")
}
return res
}
// IsPositive returns true if coin amount is positive.
//
// TODO: Remove once unsigned integers are used.
func (coin Coin) IsPositive() bool {
return (coin.Amount.Sign() == 1)
}
// IsNotNegative returns true if coin amount is not negative
// IsNotNegative returns true if coin amount is not negative and false otherwise.
//
// TODO: Remove once unsigned integers are used.
func (coin Coin) IsNotNegative() bool {
return (coin.Amount.Sign() != -1)
}
// Adds amounts of two coins with same denom
func (coin Coin) Plus(coinB Coin) Coin {
if !coin.SameDenomAs(coinB) {
return coin
}
return Coin{coin.Denom, coin.Amount.Add(coinB.Amount)}
}
// Subtracts amounts of two coins with same denom
func (coin Coin) Minus(coinB Coin) Coin {
if !coin.SameDenomAs(coinB) {
return coin
}
return Coin{coin.Denom, coin.Amount.Sub(coinB.Amount)}
}
//----------------------------------------
//-----------------------------------------------------------------------------
// Coins
// Coins is a set of Coin, one per currency
@ -101,127 +132,157 @@ func (coins Coins) String() string {
return out[:len(out)-1]
}
// IsValid asserts the Coins are sorted, and don't have 0 amounts
// IsValid asserts the Coins are sorted and have positive amounts.
func (coins Coins) IsValid() bool {
switch len(coins) {
case 0:
return true
case 1:
return !coins[0].IsZero()
return coins[0].IsPositive()
default:
lowDenom := coins[0].Denom
for _, coin := range coins[1:] {
if coin.Denom <= lowDenom {
return false
}
if coin.IsZero() {
if !coin.IsPositive() {
return false
}
// we compare each coin against the last denom
lowDenom = coin.Denom
}
return true
}
}
// Plus combines two sets of coins
// CONTRACT: Plus will never return Coins where one Coin has a 0 amount.
// Plus adds two sets of coins.
//
// e.g.
// {2A} + {A, 2B} = {3A, 2B}
// {2A} + {0B} = {2A}
//
// NOTE: Plus operates under the invariant that coins are sorted by
// denominations.
//
// CONTRACT: Plus will never return Coins where one Coin has a non-positive
// amount. In otherwords, IsValid will always return true.
func (coins Coins) Plus(coinsB Coins) Coins {
return coins.safePlus(coinsB)
}
// safePlus will perform addition of two coins sets. If both coin sets are
// empty, then an empty set is returned. If only a single set is empty, the
// other set is returned. Otherwise, the coins are compared in order of their
// denomination and addition only occurs when the denominations match, otherwise
// the coin is simply added to the sum assuming it's not zero.
func (coins Coins) safePlus(coinsB Coins) Coins {
sum := ([]Coin)(nil)
indexA, indexB := 0, 0
lenA, lenB := len(coins), len(coinsB)
for {
if indexA == lenA {
if indexB == lenB {
// return nil coins if both sets are empty
return sum
}
return append(sum, coinsB[indexB:]...)
// return set B (excluding zero coins) if set A is empty
return append(sum, removeZeroCoins(coinsB[indexB:])...)
} else if indexB == lenB {
return append(sum, coins[indexA:]...)
// return set A (excluding zero coins) if set B is empty
return append(sum, removeZeroCoins(coins[indexA:])...)
}
coinA, coinB := coins[indexA], coinsB[indexB]
switch strings.Compare(coinA.Denom, coinB.Denom) {
case -1:
if coinA.IsZero() {
// ignore 0 sum coin type
} else {
case -1: // coin A denom < coin B denom
if !coinA.IsZero() {
sum = append(sum, coinA)
}
indexA++
case 0:
if coinA.Amount.Add(coinB.Amount).IsZero() {
// ignore 0 sum coin type
} else {
sum = append(sum, coinA.Plus(coinB))
case 0: // coin A denom == coin B denom
res := coinA.Plus(coinB)
if !res.IsZero() {
sum = append(sum, res)
}
indexA++
indexB++
case 1:
if coinB.IsZero() {
// ignore 0 sum coin type
} else {
case 1: // coin A denom > coin B denom
if !coinB.IsZero() {
sum = append(sum, coinB)
}
indexB++
}
}
}
// Negative returns a set of coins with all amount negative
func (coins Coins) Negative() Coins {
res := make([]Coin, 0, len(coins))
for _, coin := range coins {
res = append(res, Coin{
Denom: coin.Denom,
Amount: coin.Amount.Neg(),
})
}
return res
}
// Minus subtracts a set of coins from another (adds the inverse)
// Minus subtracts a set of coins from another.
//
// e.g.
// {2A, 3B} - {A} = {A, 3B}
// {2A} - {0B} = {2A}
// {A, B} - {A} = {B}
//
// CONTRACT: Minus will never return Coins where one Coin has a non-positive
// amount. In otherwords, IsValid will always return true.
func (coins Coins) Minus(coinsB Coins) Coins {
return coins.Plus(coinsB.Negative())
diff, hasNeg := coins.SafeMinus(coinsB)
if hasNeg {
panic("negative coin amount")
}
return diff
}
// IsAllGT returns True iff for every denom in coins, the denom is present at a
// SafeMinus performs the same arithmetic as Minus but returns a boolean if any
// negative coin amount was returned.
func (coins Coins) SafeMinus(coinsB Coins) (Coins, bool) {
diff := coins.safePlus(coinsB.negative())
return diff, !diff.IsNotNegative()
}
// IsAllGT returns true iff for every denom in coins, the denom is present at a
// greater amount in coinsB.
func (coins Coins) IsAllGT(coinsB Coins) bool {
diff := coins.Minus(coinsB)
diff, _ := coins.SafeMinus(coinsB)
if len(diff) == 0 {
return false
}
return diff.IsPositive()
}
// IsAllGTE returns True iff for every denom in coins, the denom is present at an
// equal or greater amount in coinsB.
// IsAllGTE returns true iff for every denom in coins, the denom is present at
// an equal or greater amount in coinsB.
func (coins Coins) IsAllGTE(coinsB Coins) bool {
diff := coins.Minus(coinsB)
diff, _ := coins.SafeMinus(coinsB)
if len(diff) == 0 {
return true
}
return diff.IsNotNegative()
}
// IsAllLT returns True iff for every denom in coins, the denom is present at
// a smaller amount in coinsB.
func (coins Coins) IsAllLT(coinsB Coins) bool {
diff := coinsB.Minus(coins)
if len(diff) == 0 {
return false
}
return diff.IsPositive()
return coinsB.IsAllGT(coins)
}
// IsAllLTE returns True iff for every denom in coins, the denom is present at
// IsAllLTE returns true iff for every denom in coins, the denom is present at
// a smaller or equal amount in coinsB.
func (coins Coins) IsAllLTE(coinsB Coins) bool {
diff := coinsB.Minus(coins)
if len(diff) == 0 {
return true
}
return diff.IsNotNegative()
return coinsB.IsAllGTE(coins)
}
// IsZero returns true if there are no coins or all coins are zero.
@ -239,40 +300,22 @@ func (coins Coins) IsEqual(coinsB Coins) bool {
if len(coins) != len(coinsB) {
return false
}
coins = coins.Sort()
coinsB = coinsB.Sort()
for i := 0; i < len(coins); i++ {
if coins[i].Denom != coinsB[i].Denom || !coins[i].Amount.Equal(coinsB[i].Amount) {
return false
}
}
return true
}
// IsPositive returns true if there is at least one coin, and all
// currencies have a positive value
func (coins Coins) IsPositive() bool {
if len(coins) == 0 {
return false
}
for _, coin := range coins {
if !coin.IsPositive() {
return false
}
}
return true
}
// IsNotNegative returns true if there is no currency with a negative value
// (even no coins is true here)
func (coins Coins) IsNotNegative() bool {
if len(coins) == 0 {
return true
}
for _, coin := range coins {
if !coin.IsNotNegative() {
return false
}
}
return true
// Empty returns true if there are no coins and false otherwise.
func (coins Coins) Empty() bool {
return len(coins) == 0
}
// Returns the amount of a denom from coins
@ -280,15 +323,18 @@ func (coins Coins) AmountOf(denom string) Int {
switch len(coins) {
case 0:
return ZeroInt()
case 1:
coin := coins[0]
if coin.Denom == denom {
return coin.Amount
}
return ZeroInt()
default:
midIdx := len(coins) / 2 // 2:1, 3:1, 4:2
coin := coins[midIdx]
if denom < coin.Denom {
return coins[:midIdx].AmountOf(denom)
} else if denom == coin.Denom {
@ -299,7 +345,75 @@ func (coins Coins) AmountOf(denom string) Int {
}
}
//----------------------------------------
// IsPositive returns true if there is at least one coin and all currencies
// have a positive value.
//
// TODO: Remove once unsigned integers are used.
func (coins Coins) IsPositive() bool {
if len(coins) == 0 {
return false
}
for _, coin := range coins {
if !coin.IsPositive() {
return false
}
}
return true
}
// IsNotNegative returns true if there is no coin amount with a negative value
// (even no coins is true here).
//
// TODO: Remove once unsigned integers are used.
func (coins Coins) IsNotNegative() bool {
if len(coins) == 0 {
return true
}
for _, coin := range coins {
if !coin.IsNotNegative() {
return false
}
}
return true
}
// negative returns a set of coins with all amount negative.
//
// TODO: Remove once unsigned integers are used.
func (coins Coins) negative() Coins {
res := make([]Coin, 0, len(coins))
for _, coin := range coins {
res = append(res, Coin{
Denom: coin.Denom,
Amount: coin.Amount.Neg(),
})
}
return res
}
// removeZeroCoins removes all zero coins from the given coin set in-place.
func removeZeroCoins(coins Coins) Coins {
i, l := 0, len(coins)
for i < l {
if coins[i].IsZero() {
// remove coin
coins = append(coins[:i], coins[i+1:]...)
l--
} else {
i++
}
}
return coins[:i]
}
//-----------------------------------------------------------------------------
// Sort interface
//nolint
@ -315,7 +429,7 @@ func (coins Coins) Sort() Coins {
return coins
}
//----------------------------------------
//-----------------------------------------------------------------------------
// Parsing
var (
@ -333,17 +447,17 @@ func ParseCoin(coinStr string) (coin Coin, err error) {
matches := reCoin.FindStringSubmatch(coinStr)
if matches == nil {
err = fmt.Errorf("invalid coin expression: %s", coinStr)
return
return Coin{}, fmt.Errorf("invalid coin expression: %s", coinStr)
}
denomStr, amountStr := matches[2], matches[1]
amount, err := strconv.Atoi(amountStr)
if err != nil {
return
amount, ok := NewIntFromString(amountStr)
if !ok {
return Coin{}, fmt.Errorf("failed to parse coin amount: %s", amountStr)
}
return Coin{denomStr, NewInt(int64(amount))}, nil
return Coin{denomStr, amount}, nil
}
// ParseCoins will parse out a list of coins separated by commas.

View File

@ -0,0 +1,64 @@
package types
import (
"fmt"
"testing"
)
func BenchmarkCoinsAdditionIntersect(b *testing.B) {
benchmarkingFunc := func(numCoinsA int, numCoinsB int) func(b *testing.B) {
return func(b *testing.B) {
coinsA := Coins(make([]Coin, numCoinsA))
coinsB := Coins(make([]Coin, numCoinsB))
for i := 0; i < numCoinsA; i++ {
coinsA[i] = NewCoin("COINZ_"+string(i), NewInt(int64(i)))
}
for i := 0; i < numCoinsB; i++ {
coinsB[i] = NewCoin("COINZ_"+string(i), NewInt(int64(i)))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
coinsA.Plus(coinsB)
}
}
}
benchmarkSizes := [][]int{{1, 1}, {5, 5}, {5, 20}, {1, 1000}, {2, 1000}}
for i := 0; i < len(benchmarkSizes); i++ {
sizeA := benchmarkSizes[i][0]
sizeB := benchmarkSizes[i][1]
b.Run(fmt.Sprintf("sizes: A_%d, B_%d", sizeA, sizeB), benchmarkingFunc(sizeA, sizeB))
}
}
func BenchmarkCoinsAdditionNoIntersect(b *testing.B) {
benchmarkingFunc := func(numCoinsA int, numCoinsB int) func(b *testing.B) {
return func(b *testing.B) {
coinsA := Coins(make([]Coin, numCoinsA))
coinsB := Coins(make([]Coin, numCoinsB))
for i := 0; i < numCoinsA; i++ {
coinsA[i] = NewCoin("COINZ_"+string(numCoinsB+i), NewInt(int64(i)))
}
for i := 0; i < numCoinsB; i++ {
coinsB[i] = NewCoin("COINZ_"+string(i), NewInt(int64(i)))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
coinsA.Plus(coinsB)
}
}
}
benchmarkSizes := [][]int{{1, 1}, {5, 5}, {5, 20}, {1, 1000}, {2, 1000}, {1000, 2}}
for i := 0; i < len(benchmarkSizes); i++ {
sizeA := benchmarkSizes[i][0]
sizeB := benchmarkSizes[i][1]
b.Run(fmt.Sprintf("sizes: A_%d, B_%d", sizeA, sizeB), benchmarkingFunc(sizeA, sizeB))
}
}

View File

@ -1,43 +1,20 @@
package types
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestIsPositiveCoin(t *testing.T) {
cases := []struct {
inputOne Coin
expected bool
}{
{NewInt64Coin("A", 1), true},
{NewInt64Coin("A", 0), false},
{NewInt64Coin("a", -1), false},
}
// ----------------------------------------------------------------------------
// Coin tests
for tcIndex, tc := range cases {
res := tc.inputOne.IsPositive()
require.Equal(t, tc.expected, res, "%s positivity is incorrect, tc #%d", tc.inputOne.String(), tcIndex)
}
}
func TestIsNotNegativeCoin(t *testing.T) {
cases := []struct {
inputOne Coin
expected bool
}{
{NewInt64Coin("A", 1), true},
{NewInt64Coin("A", 0), true},
{NewInt64Coin("a", -1), false},
}
for tcIndex, tc := range cases {
res := tc.inputOne.IsNotNegative()
require.Equal(t, tc.expected, res, "%s not-negativity is incorrect, tc #%d", tc.inputOne.String(), tcIndex)
}
func TestCoin(t *testing.T) {
require.Panics(t, func() { NewInt64Coin("A", -1) })
require.Panics(t, func() { NewCoin("A", NewInt(-1)) })
require.Equal(t, NewInt(5), NewInt64Coin("A", 5).Amount)
require.Equal(t, NewInt(5), NewCoin("A", NewInt(5)).Amount)
}
func TestSameDenomAsCoin(t *testing.T) {
@ -49,8 +26,7 @@ func TestSameDenomAsCoin(t *testing.T) {
{NewInt64Coin("A", 1), NewInt64Coin("A", 1), true},
{NewInt64Coin("A", 1), NewInt64Coin("a", 1), false},
{NewInt64Coin("a", 1), NewInt64Coin("b", 1), false},
{NewInt64Coin("stake", 1), NewInt64Coin("stake", 10), true},
{NewInt64Coin("stake", -11), NewInt64Coin("stake", 10), true},
{NewInt64Coin("steak", 1), NewInt64Coin("steak", 10), true},
}
for tcIndex, tc := range cases {
@ -59,6 +35,78 @@ func TestSameDenomAsCoin(t *testing.T) {
}
}
func TestIsEqualCoin(t *testing.T) {
cases := []struct {
inputOne Coin
inputTwo Coin
expected bool
}{
{NewInt64Coin("A", 1), NewInt64Coin("A", 1), true},
{NewInt64Coin("A", 1), NewInt64Coin("a", 1), false},
{NewInt64Coin("a", 1), NewInt64Coin("b", 1), false},
{NewInt64Coin("steak", 1), NewInt64Coin("steak", 10), false},
}
for tcIndex, tc := range cases {
res := tc.inputOne.IsEqual(tc.inputTwo)
require.Equal(t, tc.expected, res, "coin equality relation is incorrect, tc #%d", tcIndex)
}
}
func TestPlusCoin(t *testing.T) {
cases := []struct {
inputOne Coin
inputTwo Coin
expected Coin
shouldPanic bool
}{
{NewInt64Coin("A", 1), NewInt64Coin("A", 1), NewInt64Coin("A", 2), false},
{NewInt64Coin("A", 1), NewInt64Coin("A", 0), NewInt64Coin("A", 1), false},
{NewInt64Coin("A", 1), NewInt64Coin("B", 1), NewInt64Coin("A", 1), true},
}
for tcIndex, tc := range cases {
if tc.shouldPanic {
require.Panics(t, func() { tc.inputOne.Plus(tc.inputTwo) })
} else {
res := tc.inputOne.Plus(tc.inputTwo)
require.Equal(t, tc.expected, res, "sum of coins is incorrect, tc #%d", tcIndex)
}
}
}
func TestMinusCoin(t *testing.T) {
cases := []struct {
inputOne Coin
inputTwo Coin
expected Coin
shouldPanic bool
}{
{NewInt64Coin("A", 1), NewInt64Coin("B", 1), NewInt64Coin("A", 1), true},
{NewInt64Coin("A", 10), NewInt64Coin("A", 1), NewInt64Coin("A", 9), false},
{NewInt64Coin("A", 5), NewInt64Coin("A", 3), NewInt64Coin("A", 2), false},
{NewInt64Coin("A", 5), NewInt64Coin("A", 0), NewInt64Coin("A", 5), false},
{NewInt64Coin("A", 1), NewInt64Coin("A", 5), Coin{}, true},
}
for tcIndex, tc := range cases {
if tc.shouldPanic {
require.Panics(t, func() { tc.inputOne.Minus(tc.inputTwo) })
} else {
res := tc.inputOne.Minus(tc.inputTwo)
require.Equal(t, tc.expected, res, "difference of coins is incorrect, tc #%d", tcIndex)
}
}
tc := struct {
inputOne Coin
inputTwo Coin
expected int64
}{NewInt64Coin("A", 1), NewInt64Coin("A", 1), 0}
res := tc.inputOne.Minus(tc.inputTwo)
require.Equal(t, tc.expected, res.Amount.Int64())
}
func TestIsGTECoin(t *testing.T) {
cases := []struct {
inputOne Coin
@ -67,8 +115,7 @@ func TestIsGTECoin(t *testing.T) {
}{
{NewInt64Coin("A", 1), NewInt64Coin("A", 1), true},
{NewInt64Coin("A", 2), NewInt64Coin("A", 1), true},
{NewInt64Coin("A", -1), NewInt64Coin("A", 5), false},
{NewInt64Coin("a", 1), NewInt64Coin("b", 1), false},
{NewInt64Coin("A", 1), NewInt64Coin("B", 1), false},
}
for tcIndex, tc := range cases {
@ -85,7 +132,6 @@ func TestIsLTCoin(t *testing.T) {
}{
{NewInt64Coin("A", 1), NewInt64Coin("A", 1), false},
{NewInt64Coin("A", 2), NewInt64Coin("A", 1), false},
{NewInt64Coin("A", -1), NewInt64Coin("A", 5), true},
{NewInt64Coin("a", 0), NewInt64Coin("b", 1), false},
{NewInt64Coin("a", 1), NewInt64Coin("b", 1), false},
{NewInt64Coin("a", 1), NewInt64Coin("a", 1), false},
@ -98,76 +144,18 @@ func TestIsLTCoin(t *testing.T) {
}
}
func TestIsEqualCoin(t *testing.T) {
cases := []struct {
inputOne Coin
inputTwo Coin
expected bool
}{
{NewInt64Coin("A", 1), NewInt64Coin("A", 1), true},
{NewInt64Coin("A", 1), NewInt64Coin("a", 1), false},
{NewInt64Coin("a", 1), NewInt64Coin("b", 1), false},
{NewInt64Coin("stake", 1), NewInt64Coin("stake", 10), false},
{NewInt64Coin("stake", -11), NewInt64Coin("stake", 10), false},
}
func TestCoinIsZero(t *testing.T) {
coin := NewInt64Coin("A", 0)
res := coin.IsZero()
require.True(t, res)
for tcIndex, tc := range cases {
res := tc.inputOne.IsEqual(tc.inputTwo)
require.Equal(t, tc.expected, res, "coin equality relation is incorrect, tc #%d", tcIndex)
}
coin = NewInt64Coin("A", 1)
res = coin.IsZero()
require.False(t, res)
}
func TestPlusCoin(t *testing.T) {
cases := []struct {
inputOne Coin
inputTwo Coin
expected Coin
}{
{NewInt64Coin("A", 1), NewInt64Coin("A", 1), NewInt64Coin("A", 2)},
{NewInt64Coin("A", 1), NewInt64Coin("B", 1), NewInt64Coin("A", 1)},
{NewInt64Coin("asdf", -4), NewInt64Coin("asdf", 5), NewInt64Coin("asdf", 1)},
}
for tcIndex, tc := range cases {
res := tc.inputOne.Plus(tc.inputTwo)
require.Equal(t, tc.expected, res, "sum of coins is incorrect, tc #%d", tcIndex)
}
tc := struct {
inputOne Coin
inputTwo Coin
expected int64
}{NewInt64Coin("asdf", -1), NewInt64Coin("asdf", 1), 0}
res := tc.inputOne.Plus(tc.inputTwo)
require.Equal(t, tc.expected, res.Amount.Int64())
}
func TestMinusCoin(t *testing.T) {
cases := []struct {
inputOne Coin
inputTwo Coin
expected Coin
}{
{NewInt64Coin("A", 1), NewInt64Coin("B", 1), NewInt64Coin("A", 1)},
{NewInt64Coin("asdf", -4), NewInt64Coin("asdf", 5), NewInt64Coin("asdf", -9)},
{NewInt64Coin("asdf", 10), NewInt64Coin("asdf", 1), NewInt64Coin("asdf", 9)},
}
for tcIndex, tc := range cases {
res := tc.inputOne.Minus(tc.inputTwo)
require.Equal(t, tc.expected, res, "difference of coins is incorrect, tc #%d", tcIndex)
}
tc := struct {
inputOne Coin
inputTwo Coin
expected int64
}{NewInt64Coin("A", 1), NewInt64Coin("A", 1), 0}
res := tc.inputOne.Minus(tc.inputTwo)
require.Equal(t, tc.expected, res.Amount.Int64())
}
// ----------------------------------------------------------------------------
// Coins tests
func TestIsZeroCoins(t *testing.T) {
cases := []struct {
@ -199,8 +187,7 @@ func TestEqualCoins(t *testing.T) {
{Coins{NewInt64Coin("A", 0)}, Coins{NewInt64Coin("B", 0)}, false},
{Coins{NewInt64Coin("A", 0)}, Coins{NewInt64Coin("A", 1)}, false},
{Coins{NewInt64Coin("A", 0)}, Coins{NewInt64Coin("A", 0), NewInt64Coin("B", 1)}, false},
// TODO: is it expected behaviour? shouldn't we sort the coins before comparing them?
{Coins{NewInt64Coin("A", 0), NewInt64Coin("B", 1)}, Coins{NewInt64Coin("B", 1), NewInt64Coin("A", 0)}, false},
{Coins{NewInt64Coin("A", 0), NewInt64Coin("B", 1)}, Coins{NewInt64Coin("B", 1), NewInt64Coin("A", 0)}, true},
}
for tcnum, tc := range cases {
@ -209,16 +196,65 @@ func TestEqualCoins(t *testing.T) {
}
}
func TestCoins(t *testing.T) {
func TestPlusCoins(t *testing.T) {
zero := NewInt(0)
one := NewInt(1)
two := NewInt(2)
//Define the coins to be used in tests
cases := []struct {
inputOne Coins
inputTwo Coins
expected Coins
}{
{Coins{{"A", one}, {"B", one}}, Coins{{"A", one}, {"B", one}}, Coins{{"A", two}, {"B", two}}},
{Coins{{"A", zero}, {"B", one}}, Coins{{"A", zero}, {"B", zero}}, Coins{{"B", one}}},
{Coins{{"A", two}}, Coins{{"B", zero}}, Coins{{"A", two}}},
{Coins{{"A", one}}, Coins{{"A", one}, {"B", two}}, Coins{{"A", two}, {"B", two}}},
{Coins{{"A", zero}, {"B", zero}}, Coins{{"A", zero}, {"B", zero}}, Coins(nil)},
}
for tcIndex, tc := range cases {
res := tc.inputOne.Plus(tc.inputTwo)
assert.True(t, res.IsValid())
require.Equal(t, tc.expected, res, "sum of coins is incorrect, tc #%d", tcIndex)
}
}
func TestMinusCoins(t *testing.T) {
zero := NewInt(0)
one := NewInt(1)
two := NewInt(2)
testCases := []struct {
inputOne Coins
inputTwo Coins
expected Coins
shouldPanic bool
}{
{Coins{{"A", two}}, Coins{{"A", one}, {"B", two}}, Coins{{"A", one}, {"B", two}}, true},
{Coins{{"A", two}}, Coins{{"B", zero}}, Coins{{"A", two}}, false},
{Coins{{"A", one}}, Coins{{"B", zero}}, Coins{{"A", one}}, false},
{Coins{{"A", one}, {"B", one}}, Coins{{"A", one}}, Coins{{"B", one}}, false},
{Coins{{"A", one}, {"B", one}}, Coins{{"A", two}}, Coins{}, true},
}
for i, tc := range testCases {
if tc.shouldPanic {
require.Panics(t, func() { tc.inputOne.Minus(tc.inputTwo) })
} else {
res := tc.inputOne.Minus(tc.inputTwo)
assert.True(t, res.IsValid())
require.Equal(t, tc.expected, res, "sum of coins is incorrect, tc #%d", i)
}
}
}
func TestCoins(t *testing.T) {
good := Coins{
{"GAS", NewInt(1)},
{"MINERAL", NewInt(1)},
{"TREE", NewInt(1)},
}
neg := good.Negative()
sum := good.Plus(neg)
empty := Coins{
{"GOLD", NewInt(0)},
}
@ -228,6 +264,7 @@ func TestCoins(t *testing.T) {
{"GAS", NewInt(1)},
{"MINERAL", NewInt(1)},
}
// both are after the first one, but the second and third are in the wrong order
badSort2 := Coins{
{"GAS", NewInt(1)},
@ -251,13 +288,10 @@ func TestCoins(t *testing.T) {
assert.True(t, good.IsAllGTE(empty), "Expected %v to be >= %v", good, empty)
assert.False(t, good.IsAllLT(empty), "Expected %v to be < %v", good, empty)
assert.True(t, empty.IsAllLT(good), "Expected %v to be < %v", empty, good)
assert.False(t, neg.IsPositive(), "Expected neg coins to not be positive: %v", neg)
assert.Zero(t, len(sum), "Expected 0 coins")
assert.False(t, badSort1.IsValid(), "Coins are not sorted")
assert.False(t, badSort2.IsValid(), "Coins are not sorted")
assert.False(t, badAmt.IsValid(), "Coins cannot include 0 amounts")
assert.False(t, dup.IsValid(), "Duplicate coin")
}
func TestCoinsGT(t *testing.T) {
@ -314,32 +348,6 @@ func TestCoinsLTE(t *testing.T) {
assert.True(t, Coins{}.IsAllLTE(Coins{{"A", one}}))
}
func TestPlusCoins(t *testing.T) {
one := NewInt(1)
zero := NewInt(0)
negone := NewInt(-1)
two := NewInt(2)
cases := []struct {
inputOne Coins
inputTwo Coins
expected Coins
}{
{Coins{{"A", one}, {"B", one}}, Coins{{"A", one}, {"B", one}}, Coins{{"A", two}, {"B", two}}},
{Coins{{"A", zero}, {"B", one}}, Coins{{"A", zero}, {"B", zero}}, Coins{{"B", one}}},
{Coins{{"A", zero}, {"B", zero}}, Coins{{"A", zero}, {"B", zero}}, Coins(nil)},
{Coins{{"A", one}, {"B", zero}}, Coins{{"A", negone}, {"B", zero}}, Coins(nil)},
{Coins{{"A", negone}, {"B", zero}}, Coins{{"A", zero}, {"B", zero}}, Coins{{"A", negone}}},
}
for tcIndex, tc := range cases {
res := tc.inputOne.Plus(tc.inputTwo)
assert.True(t, res.IsValid())
require.Equal(t, tc.expected, res, "sum of coins is incorrect, tc #%d", tcIndex)
}
}
//Test the parsing of Coin and Coins
func TestParse(t *testing.T) {
one := NewInt(1)
@ -370,11 +378,9 @@ func TestParse(t *testing.T) {
require.Equal(t, tc.expected, res, "coin parsing was incorrect, tc #%d", tcIndex)
}
}
}
func TestSortCoins(t *testing.T) {
good := Coins{
NewInt64Coin("GAS", 1),
NewInt64Coin("MINERAL", 1),
@ -424,7 +430,6 @@ func TestSortCoins(t *testing.T) {
}
func TestAmountOf(t *testing.T) {
case0 := Coins{}
case1 := Coins{
NewInt64Coin("", 0),
@ -481,55 +486,3 @@ func TestAmountOf(t *testing.T) {
assert.Equal(t, NewInt(tc.amountOfTREE), tc.coins.AmountOf("TREE"))
}
}
func BenchmarkCoinsAdditionIntersect(b *testing.B) {
benchmarkingFunc := func(numCoinsA int, numCoinsB int) func(b *testing.B) {
return func(b *testing.B) {
coinsA := Coins(make([]Coin, numCoinsA))
coinsB := Coins(make([]Coin, numCoinsB))
for i := 0; i < numCoinsA; i++ {
coinsA[i] = NewCoin("COINZ_"+string(i), NewInt(int64(i)))
}
for i := 0; i < numCoinsB; i++ {
coinsB[i] = NewCoin("COINZ_"+string(i), NewInt(int64(i)))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
coinsA.Plus(coinsB)
}
}
}
benchmarkSizes := [][]int{{1, 1}, {5, 5}, {5, 20}, {1, 1000}, {2, 1000}}
for i := 0; i < len(benchmarkSizes); i++ {
sizeA := benchmarkSizes[i][0]
sizeB := benchmarkSizes[i][1]
b.Run(fmt.Sprintf("sizes: A_%d, B_%d", sizeA, sizeB), benchmarkingFunc(sizeA, sizeB))
}
}
func BenchmarkCoinsAdditionNoIntersect(b *testing.B) {
benchmarkingFunc := func(numCoinsA int, numCoinsB int) func(b *testing.B) {
return func(b *testing.B) {
coinsA := Coins(make([]Coin, numCoinsA))
coinsB := Coins(make([]Coin, numCoinsB))
for i := 0; i < numCoinsA; i++ {
coinsA[i] = NewCoin("COINZ_"+string(numCoinsB+i), NewInt(int64(i)))
}
for i := 0; i < numCoinsB; i++ {
coinsB[i] = NewCoin("COINZ_"+string(i), NewInt(int64(i)))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
coinsA.Plus(coinsB)
}
}
}
benchmarkSizes := [][]int{{1, 1}, {5, 5}, {5, 20}, {1, 1000}, {2, 1000}, {1000, 2}}
for i := 0; i < len(benchmarkSizes); i++ {
sizeA := benchmarkSizes[i][0]
sizeB := benchmarkSizes[i][1]
b.Run(fmt.Sprintf("sizes: A_%d, B_%d", sizeA, sizeB), benchmarkingFunc(sizeA, sizeB))
}
}

View File

@ -73,12 +73,12 @@ func (c Context) Value(key interface{}) interface{} {
// KVStore fetches a KVStore from the MultiStore.
func (c Context) KVStore(key StoreKey) KVStore {
return c.multiStore().GetKVStore(key).Gas(c.GasMeter(), cachedKVGasConfig)
return c.MultiStore().GetKVStore(key).Gas(c.GasMeter(), cachedKVGasConfig)
}
// TransientStore fetches a TransientStore from the MultiStore.
func (c Context) TransientStore(key StoreKey) KVStore {
return c.multiStore().GetKVStore(key).Gas(c.GasMeter(), cachedTransientGasConfig)
return c.MultiStore().GetKVStore(key).Gas(c.GasMeter(), cachedTransientGasConfig)
}
//----------------------------------------
@ -143,10 +143,7 @@ const (
contextKeyMinimumFees
)
// NOTE: Do not expose MultiStore.
// MultiStore exposes all the keys.
// Instead, pass the context and the store key.
func (c Context) multiStore() MultiStore {
func (c Context) MultiStore() MultiStore {
return c.Value(contextKeyMultiStore).(MultiStore)
}
@ -174,7 +171,9 @@ func (c Context) IsCheckTx() bool { return c.Value(contextKeyIsCheckTx).(bool) }
func (c Context) MinimumFees() Coins { return c.Value(contextKeyMinimumFees).(Coins) }
func (c Context) WithMultiStore(ms MultiStore) Context { return c.withValue(contextKeyMultiStore, ms) }
func (c Context) WithMultiStore(ms MultiStore) Context {
return c.withValue(contextKeyMultiStore, ms)
}
func (c Context) WithBlockHeader(header abci.Header) Context {
var _ proto.Message = &header // for cloning.
@ -203,8 +202,10 @@ func (c Context) WithConsensusParams(params *abci.ConsensusParams) Context {
if params == nil {
return c
}
// TODO: Do we need to handle invalid MaxGas values?
return c.withValue(contextKeyConsensusParams, params).
WithGasMeter(NewGasMeter(params.BlockSize.MaxGas))
WithGasMeter(NewGasMeter(uint64(params.BlockSize.MaxGas)))
}
func (c Context) WithChainID(chainID string) Context { return c.withValue(contextKeyChainID, chainID) }
@ -230,7 +231,7 @@ func (c Context) WithMinimumFees(minFees Coins) Context {
// Cache the multistore and return a new cached context. The cached context is
// written to the context when writeCache is called.
func (c Context) CacheContext() (cc Context, writeCache func()) {
cms := c.multiStore().CacheMultiStore()
cms := c.MultiStore().CacheMultiStore()
cc = c.WithMultiStore(cms)
return cc, cms.Write
}

View File

@ -10,37 +10,22 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
)
// ABCICodeType - combined codetype / codespace
type ABCICodeType uint32
// CodeType - code identifier within codespace
type CodeType uint16
// CodeType - ABCI code identifier within codespace
type CodeType uint32
// CodespaceType - codespace identifier
type CodespaceType uint16
type CodespaceType string
// IsOK - is everything okay?
func (code ABCICodeType) IsOK() bool {
if code == ABCICodeOK {
func (code CodeType) IsOK() bool {
if code == CodeOK {
return true
}
return false
}
// get the abci code from the local code and codespace
func ToABCICode(space CodespaceType, code CodeType) ABCICodeType {
// TODO: Make Tendermint more aware of codespaces.
if space == CodespaceRoot && code == CodeOK {
return ABCICodeOK
}
return ABCICodeType((uint32(space) << 16) | uint32(code))
}
// SDK error codes
const (
// ABCI error codes
ABCICodeOK ABCICodeType = 0
// Base error codes
CodeOK CodeType = 0
CodeInternal CodeType = 1
@ -62,11 +47,8 @@ const (
// CodespaceRoot is a codespace for error codes in this file only.
// Notice that 0 is an "unset" codespace, which can be overridden with
// Error.WithDefaultCodespace().
CodespaceUndefined CodespaceType = 0
CodespaceRoot CodespaceType = 1
// Maximum reservable codespace (2^16 - 1)
MaximumCodespace CodespaceType = 65535
CodespaceUndefined CodespaceType = ""
CodespaceRoot CodespaceType = "sdk"
)
func unknownCodeMsg(code CodeType) string {
@ -185,7 +167,6 @@ type Error interface {
Code() CodeType
Codespace() CodespaceType
ABCILog() string
ABCICode() ABCICodeType
Result() Result
QueryResult() abci.ResponseQuery
}
@ -239,17 +220,12 @@ func (err *sdkError) TraceSDK(format string, args ...interface{}) Error {
// Implements ABCIError.
func (err *sdkError) Error() string {
return fmt.Sprintf(`ERROR:
Codespace: %d
Codespace: %s
Code: %d
Message: %#v
`, err.codespace, err.code, err.cmnError.Error())
}
// Implements ABCIError.
func (err *sdkError) ABCICode() ABCICodeType {
return ToABCICode(err.codespace, err.code)
}
// Implements Error.
func (err *sdkError) Codespace() CodespaceType {
return err.codespace
@ -267,7 +243,6 @@ func (err *sdkError) ABCILog() string {
jsonErr := humanReadableError{
Codespace: err.codespace,
Code: err.code,
ABCICode: err.ABCICode(),
Message: errMsg,
}
bz, er := cdc.MarshalJSON(jsonErr)
@ -280,16 +255,18 @@ func (err *sdkError) ABCILog() string {
func (err *sdkError) Result() Result {
return Result{
Code: err.ABCICode(),
Log: err.ABCILog(),
Code: err.Code(),
Codespace: err.Codespace(),
Log: err.ABCILog(),
}
}
// QueryResult allows us to return sdk.Error.QueryResult() in query responses
func (err *sdkError) QueryResult() abci.ResponseQuery {
return abci.ResponseQuery{
Code: uint32(err.ABCICode()),
Log: err.ABCILog(),
Code: uint32(err.Code()),
Codespace: string(err.Codespace()),
Log: err.ABCILog(),
}
}
@ -324,6 +301,5 @@ func mustGetMsgIndex(abciLog string) int {
type humanReadableError struct {
Codespace CodespaceType `json:"codespace"`
Code CodeType `json:"code"`
ABCICode ABCICodeType `json:"abci_code"`
Message string `json:"message"`
}

View File

@ -42,7 +42,7 @@ var errFns = []errFn{
}
func TestCodeType(t *testing.T) {
require.True(t, ABCICodeOK.IsOK())
require.True(t, CodeOK.IsOK())
for tcnum, c := range codeTypes {
msg := CodeToDefaultMsg(c)
@ -59,12 +59,9 @@ func TestErrFn(t *testing.T) {
codeType := codeTypes[i]
require.Equal(t, err.Code(), codeType, "Err function expected to return proper code. tc #%d", i)
require.Equal(t, err.Codespace(), CodespaceRoot, "Err function expected to return proper codespace. tc #%d", i)
require.Equal(t, err.Result().Code, ToABCICode(CodespaceRoot, codeType), "Err function expected to return proper ABCICode. tc #%d")
require.Equal(t, err.QueryResult().Code, uint32(err.ABCICode()), "Err function expected to return proper ABCICode from QueryResult. tc #%d")
require.Equal(t, err.QueryResult().Code, uint32(err.Code()), "Err function expected to return proper Code from QueryResult. tc #%d")
require.Equal(t, err.QueryResult().Log, err.ABCILog(), "Err function expected to return proper ABCILog from QueryResult. tc #%d")
}
require.Equal(t, ABCICodeOK, ToABCICode(CodespaceRoot, CodeOK))
}
func TestAppendMsgToErr(t *testing.T) {

View File

@ -18,13 +18,19 @@ var (
)
// Gas measured by the SDK
type Gas = int64
type Gas = uint64
// ErrorOutOfGas defines an error thrown when an action results in out of gas.
type ErrorOutOfGas struct {
Descriptor string
}
// ErrorGasOverflow defines an error thrown when an action results gas consumption
// unsigned integer overflow.
type ErrorGasOverflow struct {
Descriptor string
}
// GasMeter interface to track gas consumption
type GasMeter interface {
GasConsumed() Gas
@ -49,7 +55,14 @@ func (g *basicGasMeter) GasConsumed() Gas {
}
func (g *basicGasMeter) ConsumeGas(amount Gas, descriptor string) {
g.consumed += amount
var overflow bool
// TODO: Should we set the consumed field after overflow checking?
g.consumed, overflow = AddUint64Overflow(g.consumed, amount)
if overflow {
panic(ErrorGasOverflow{descriptor})
}
if g.consumed > g.limit {
panic(ErrorOutOfGas{descriptor})
}
@ -71,7 +84,13 @@ func (g *infiniteGasMeter) GasConsumed() Gas {
}
func (g *infiniteGasMeter) ConsumeGas(amount Gas, descriptor string) {
g.consumed += amount
var overflow bool
// TODO: Should we set the consumed field after overflow checking?
g.consumed, overflow = AddUint64Overflow(g.consumed, amount)
if overflow {
panic(ErrorGasOverflow{descriptor})
}
}
// GasConfig defines gas cost for each operation on KVStores

View File

@ -21,7 +21,7 @@ func TestGasMeter(t *testing.T) {
for tcnum, tc := range cases {
meter := NewGasMeter(tc.limit)
used := int64(0)
used := uint64(0)
for unum, usage := range tc.usage {
used += usage

View File

@ -2,6 +2,7 @@ package types
import (
"encoding/json"
"math"
"testing"
"math/big"
@ -321,11 +322,11 @@ func NewUint(n uint64) Uint {
// NewUintFromBigUint constructs Uint from big.Uint
func NewUintFromBigInt(i *big.Int) Uint {
// Check overflow
if i.Sign() == -1 || i.Sign() == 1 && i.BitLen() > 256 {
res := Uint{i}
if UintOverflow(res) {
panic("Uint overflow")
}
return Uint{i}
return res
}
// NewUintFromString constructs Uint from string
@ -352,11 +353,12 @@ func NewUintWithDecimal(n uint64, dec int) Uint {
i := new(big.Int)
i.Mul(new(big.Int).SetUint64(n), exp)
// Check overflow
if i.Sign() == -1 || i.Sign() == 1 && i.BitLen() > 256 {
res := Uint{i}
if UintOverflow(res) {
panic("NewUintWithDecimal() out of bound")
}
return Uint{i}
return res
}
// ZeroUint returns Uint value with zero
@ -407,8 +409,7 @@ func (i Uint) LT(i2 Uint) bool {
// Add adds Uint from another
func (i Uint) Add(i2 Uint) (res Uint) {
res = Uint{add(i.i, i2.i)}
// Check overflow
if res.Sign() == -1 || res.Sign() == 1 && res.i.BitLen() > 256 {
if UintOverflow(res) {
panic("Uint overflow")
}
return
@ -422,13 +423,23 @@ func (i Uint) AddRaw(i2 uint64) Uint {
// Sub subtracts Uint from another
func (i Uint) Sub(i2 Uint) (res Uint) {
res = Uint{sub(i.i, i2.i)}
// Check overflow
if res.Sign() == -1 || res.Sign() == 1 && res.i.BitLen() > 256 {
if UintOverflow(res) {
panic("Uint overflow")
}
return
}
// SafeSub attempts to subtract one Uint from another. A boolean is also returned
// indicating if the result contains integer overflow.
func (i Uint) SafeSub(i2 Uint) (Uint, bool) {
res := Uint{sub(i.i, i2.i)}
if UintOverflow(res) {
return res, true
}
return res, false
}
// SubRaw subtracts uint64 from Uint
func (i Uint) SubRaw(i2 uint64) Uint {
return i.Sub(NewUint(i2))
@ -436,15 +447,15 @@ func (i Uint) SubRaw(i2 uint64) Uint {
// Mul multiples two Uints
func (i Uint) Mul(i2 Uint) (res Uint) {
// Check overflow
if i.i.BitLen()+i2.i.BitLen()-1 > 256 {
panic("Uint overflow")
}
res = Uint{mul(i.i, i2.i)}
// Check overflow
if res.Sign() == -1 || res.Sign() == 1 && res.i.BitLen() > 256 {
if UintOverflow(res) {
panic("Uint overflow")
}
return
}
@ -529,6 +540,22 @@ func (i *Uint) UnmarshalJSON(bz []byte) error {
//__________________________________________________________________________
// UintOverflow returns true if a given unsigned integer overflows and false
// otherwise.
func UintOverflow(x Uint) bool {
return x.i.Sign() == -1 || x.i.Sign() == 1 && x.i.BitLen() > 256
}
// AddUint64Overflow performs the addition operation on two uint64 integers and
// returns a boolean on whether or not the result overflows.
func AddUint64Overflow(a, b uint64) (uint64, bool) {
if math.MaxUint64-a < b {
return 0, true
}
return a + b, false
}
// intended to be used with require/assert: require.True(IntEq(...))
func IntEq(t *testing.T, exp, got Int) (*testing.T, bool, string, string, string) {
return t, exp.Equal(got), "expected:\t%v\ngot:\t\t%v", exp.String(), got.String()

View File

@ -590,3 +590,53 @@ func TestEncodingTableUint(t *testing.T) {
require.Equal(t, tc.i, i, "Unmarshaled value is different from expected. tc #%d", tcnum)
}
}
func TestSafeSub(t *testing.T) {
testCases := []struct {
x, y Uint
expected uint64
overflow bool
}{
{NewUint(0), NewUint(0), 0, false},
{NewUint(10), NewUint(5), 5, false},
{NewUint(5), NewUint(10), 5, true},
{NewUint(math.MaxUint64), NewUint(0), math.MaxUint64, false},
}
for i, tc := range testCases {
res, overflow := tc.x.SafeSub(tc.y)
require.Equal(
t, tc.overflow, overflow,
"invalid overflow result; x: %s, y: %s, tc: #%d", tc.x, tc.y, i,
)
require.Equal(
t, tc.expected, res.BigInt().Uint64(),
"invalid subtraction result; x: %s, y: %s, tc: #%d", tc.x, tc.y, i,
)
}
}
func TestAddUint64Overflow(t *testing.T) {
testCases := []struct {
a, b uint64
result uint64
overflow bool
}{
{0, 0, 0, false},
{100, 100, 200, false},
{math.MaxUint64 / 2, math.MaxUint64/2 + 1, math.MaxUint64, false},
{math.MaxUint64 / 2, math.MaxUint64/2 + 2, 0, true},
}
for i, tc := range testCases {
res, overflow := AddUint64Overflow(tc.a, tc.b)
require.Equal(
t, tc.overflow, overflow,
"invalid overflow result; tc: #%d, a: %d, b: %d", i, tc.a, tc.b,
)
require.Equal(
t, tc.result, res,
"invalid uint64 result; tc: #%d, a: %d, b: %d", i, tc.a, tc.b,
)
}
}

11
types/module_clients.go Normal file
View File

@ -0,0 +1,11 @@
package types
import (
"github.com/spf13/cobra"
)
// ModuleClients helps modules provide a standard interface for exporting client functionality
type ModuleClients interface {
GetQueryCmd() *cobra.Command
GetTxCmd() *cobra.Command
}

View File

@ -4,7 +4,10 @@ package types
type Result struct {
// Code is the response code, is stored back on the chain.
Code ABCICodeType
Code CodeType
// Codespace is the string referring to the domain of an error
Codespace CodespaceType
// Data is any data returned from the app.
Data []byte
@ -13,10 +16,10 @@ type Result struct {
Log string
// GasWanted is the maximum units of work we allow this tx to perform.
GasWanted int64
GasWanted uint64
// GasUsed is the amount of gas actually consumed. NOTE: unimplemented
GasUsed int64
GasUsed uint64
// Tx fee amount and denom.
FeeAmount int64

View File

@ -13,6 +13,6 @@ func TestResult(t *testing.T) {
res.Data = []byte("data")
require.True(t, res.IsOK())
res.Code = ABCICodeType(1)
res.Code = CodeType(1)
require.False(t, res.IsOK())
}

View File

@ -71,6 +71,7 @@ func NewAnteHandler(am AccountKeeper, fck FeeCollectionKeeper) sdk.AnteHandler {
if err != nil {
return newCtx, err.Result(), true
}
// charge gas for the memo
newCtx.GasMeter().ConsumeGas(memoCostPerByte*sdk.Gas(len(stdTx.GetMemo())), "memo")
@ -260,13 +261,16 @@ func consumeSignatureVerificationGas(meter sdk.GasMeter, pubkey crypto.PubKey) {
}
}
func adjustFeesByGas(fees sdk.Coins, gas int64) sdk.Coins {
func adjustFeesByGas(fees sdk.Coins, gas uint64) sdk.Coins {
gasCost := gas / gasPerUnitCost
gasFees := make(sdk.Coins, len(fees))
// TODO: Make this not price all coins in the same way
// TODO: Undo int64 casting once unsigned integers are supported for coins
for i := 0; i < len(fees); i++ {
gasFees[i] = sdk.NewInt64Coin(fees[i].Denom, gasCost)
gasFees[i] = sdk.NewInt64Coin(fees[i].Denom, int64(gasCost))
}
return fees.Plus(gasFees)
}
@ -277,24 +281,36 @@ func deductFees(acc Account, fee StdFee) (Account, sdk.Result) {
coins := acc.GetCoins()
feeAmount := fee.Amount
newCoins := coins.Minus(feeAmount)
if !newCoins.IsNotNegative() {
if !feeAmount.IsValid() {
return nil, sdk.ErrInsufficientFee(fmt.Sprintf("invalid fee amount: %s", feeAmount)).Result()
}
newCoins, ok := coins.SafeMinus(feeAmount)
if ok {
errMsg := fmt.Sprintf("%s < %s", coins, feeAmount)
return nil, sdk.ErrInsufficientFunds(errMsg).Result()
}
err := acc.SetCoins(newCoins)
if err != nil {
// Handle w/ #870
panic(err)
}
return acc, sdk.Result{}
}
func ensureSufficientMempoolFees(ctx sdk.Context, stdTx StdTx) sdk.Result {
// currently we use a very primitive gas pricing model with a constant gasPrice.
// adjustFeesByGas handles calculating the amount of fees required based on the provided gas.
// TODO: Make the gasPrice not a constant, and account for tx size.
requiredFees := adjustFeesByGas(ctx.MinimumFees(), stdTx.Fee.Gas)
//
// TODO:
// - Make the gasPrice not a constant, and account for tx size.
// - Make Gas an unsigned integer and use tx basic validation
if stdTx.Fee.Gas <= 0 {
return sdk.ErrInternal(fmt.Sprintf("invalid gas supplied: %d", stdTx.Fee.Gas)).Result()
}
requiredFees := adjustFeesByGas(ctx.MinimumFees(), uint64(stdTx.Fee.Gas))
// NOTE: !A.IsAllGTE(B) is not the same as A.IsAllLT(B).
if !ctx.MinimumFees().IsZero() && !stdTx.Fee.Amount.IsAllGTE(requiredFees) {
@ -306,10 +322,12 @@ func ensureSufficientMempoolFees(ctx sdk.Context, stdTx StdTx) sdk.Result {
}
func setGasMeter(simulate bool, ctx sdk.Context, stdTx StdTx) sdk.Context {
// set the gas meter
// In various cases such as simulation and during the genesis block, we do not
// meter any gas utilization.
if simulate || ctx.BlockHeight() == 0 {
return ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
}
return ctx.WithGasMeter(sdk.NewGasMeter(stdTx.Fee.Gas))
}

View File

@ -43,7 +43,7 @@ func privAndAddr() (crypto.PrivKey, sdk.AccAddress) {
func checkValidTx(t *testing.T, anteHandler sdk.AnteHandler, ctx sdk.Context, tx sdk.Tx, simulate bool) {
_, result, abort := anteHandler(ctx, tx, simulate)
require.False(t, abort)
require.Equal(t, sdk.ABCICodeOK, result.Code)
require.Equal(t, sdk.CodeOK, result.Code)
require.True(t, result.IsOK())
}
@ -51,8 +51,9 @@ func checkValidTx(t *testing.T, anteHandler sdk.AnteHandler, ctx sdk.Context, tx
func checkInvalidTx(t *testing.T, anteHandler sdk.AnteHandler, ctx sdk.Context, tx sdk.Tx, simulate bool, code sdk.CodeType) {
newCtx, result, abort := anteHandler(ctx, tx, simulate)
require.True(t, abort)
require.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, code), result.Code,
fmt.Sprintf("Expected %v, got %v", sdk.ToABCICode(sdk.CodespaceRoot, code), result))
require.Equal(t, code, result.Code, fmt.Sprintf("Expected %v, got %v", code, result))
require.Equal(t, sdk.CodespaceRoot, result.Codespace)
if code == sdk.CodeOutOfGas {
stdTx, ok := tx.(StdTx)
@ -676,7 +677,7 @@ func TestConsumeSignatureVerificationGas(t *testing.T) {
tests := []struct {
name string
args args
gasConsumed int64
gasConsumed uint64
wantPanic bool
}{
{"PubKeyEd25519", args{sdk.NewInfiniteGasMeter(), ed25519.GenPrivKey().PubKey()}, ed25519VerifyCost, false},
@ -698,7 +699,7 @@ func TestConsumeSignatureVerificationGas(t *testing.T) {
func TestAdjustFeesByGas(t *testing.T) {
type args struct {
fee sdk.Coins
gas int64
gas uint64
}
tests := []struct {
name string
@ -707,7 +708,6 @@ func TestAdjustFeesByGas(t *testing.T) {
}{
{"nil coins", args{sdk.Coins{}, 10000}, sdk.Coins{}},
{"nil coins", args{sdk.Coins{sdk.NewInt64Coin("A", 10), sdk.NewInt64Coin("B", 0)}, 10000}, sdk.Coins{sdk.NewInt64Coin("A", 20), sdk.NewInt64Coin("B", 10)}},
{"negative coins", args{sdk.Coins{sdk.NewInt64Coin("A", -10), sdk.NewInt64Coin("B", 10)}, 10000}, sdk.Coins{sdk.NewInt64Coin("B", 20)}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

View File

@ -5,34 +5,17 @@ import (
"github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
)
// GetAccountCmdDefault invokes the GetAccountCmd for the auth.BaseAccount type.
func GetAccountCmdDefault(storeName string, cdc *codec.Codec) *cobra.Command {
return GetAccountCmd(storeName, cdc, GetAccountDecoder(cdc))
}
// GetAccountDecoder gets the account decoder for auth.DefaultAccount.
func GetAccountDecoder(cdc *codec.Codec) auth.AccountDecoder {
return func(accBytes []byte) (acct auth.Account, err error) {
err = cdc.UnmarshalBinaryBare(accBytes, &acct)
if err != nil {
panic(err)
}
return acct, err
}
}
// GetAccountCmd returns a query account that will display the state of the
// account at a given address.
// nolint: unparam
func GetAccountCmd(storeName string, cdc *codec.Codec, decoder auth.AccountDecoder) *cobra.Command {
return &cobra.Command{
func GetAccountCmd(storeName string, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "account [address]",
Short: "Query account balance",
Args: cobra.ExactArgs(1),
@ -47,9 +30,9 @@ func GetAccountCmd(storeName string, cdc *codec.Codec, decoder auth.AccountDecod
cliCtx := context.NewCLIContext().
WithCodec(cdc).
WithAccountDecoder(decoder)
WithAccountDecoder(cdc)
if err := cliCtx.EnsureAccountExistsFromAddr(key); err != nil {
if err = cliCtx.EnsureAccountExistsFromAddr(key); err != nil {
return err
}
@ -72,4 +55,7 @@ func GetAccountCmd(storeName string, cdc *codec.Codec, decoder auth.AccountDecod
return nil
},
}
// Add the flags here and return the command
return client.GetCommands(cmd)[0]
}

View File

@ -2,9 +2,10 @@ package cli
import (
"fmt"
"io/ioutil"
"github.com/pkg/errors"
"github.com/spf13/viper"
"io/ioutil"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context"
@ -24,7 +25,7 @@ const (
)
// GetSignCommand returns the sign command
func GetSignCommand(codec *amino.Codec, decoder auth.AccountDecoder) *cobra.Command {
func GetSignCommand(codec *amino.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "sign <file>",
Short: "Sign transactions generated offline",
@ -41,7 +42,7 @@ order.
The --offline flag makes sure that the client will not reach out to the local cache.
Thus account number or sequence number lookups will not be performed and it is
recommended to set such parameters manually.`,
RunE: makeSignCmd(codec, decoder),
RunE: makeSignCmd(codec),
Args: cobra.ExactArgs(1),
}
cmd.Flags().String(client.FlagName, "", "Name of private key with which to sign")
@ -51,10 +52,12 @@ recommended to set such parameters manually.`,
cmd.Flags().Bool(flagValidateSigs, false, "Print the addresses that must sign the transaction, "+
"those who have already signed it, and make sure that signatures are in the correct order.")
cmd.Flags().Bool(flagOffline, false, "Offline mode. Do not query local cache.")
return cmd
// Add the flags here and return the command
return client.PostCommands(cmd)[0]
}
func makeSignCmd(cdc *amino.Codec, decoder auth.AccountDecoder) func(cmd *cobra.Command, args []string) error {
func makeSignCmd(cdc *amino.Codec) func(cmd *cobra.Command, args []string) error {
return func(cmd *cobra.Command, args []string) (err error) {
stdTx, err := readAndUnmarshalStdTx(cdc, args[0])
if err != nil {
@ -72,7 +75,7 @@ func makeSignCmd(cdc *amino.Codec, decoder auth.AccountDecoder) func(cmd *cobra.
if name == "" {
return errors.New("required flag \"name\" has not been set")
}
cliCtx := context.NewCLIContext().WithCodec(cdc).WithAccountDecoder(decoder)
cliCtx := context.NewCLIContext().WithCodec(cdc).WithAccountDecoder(cdc)
txBldr := authtxb.NewTxBuilderFromCLI()
// if --signature-only is on, then override --append

View File

@ -8,7 +8,6 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
"github.com/gorilla/mux"
)
@ -17,11 +16,11 @@ import (
func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Codec, storeName string) {
r.HandleFunc(
"/auth/accounts/{address}",
QueryAccountRequestHandlerFn(storeName, cdc, authcmd.GetAccountDecoder(cdc), cliCtx),
QueryAccountRequestHandlerFn(storeName, cdc, context.GetAccountDecoder(cdc), cliCtx),
).Methods("GET")
r.HandleFunc(
"/bank/balances/{address}",
QueryBalancesRequestHandlerFn(storeName, cdc, authcmd.GetAccountDecoder(cdc), cliCtx),
QueryBalancesRequestHandlerFn(storeName, cdc, context.GetAccountDecoder(cdc), cliCtx),
).Methods("GET")
r.HandleFunc(
"/tx/sign",

View File

@ -16,7 +16,7 @@ type TxBuilder struct {
Codec *codec.Codec
AccountNumber int64
Sequence int64
Gas int64 // TODO: should this turn into uint64? requires further discussion - see #2173
Gas uint64
GasAdjustment float64
SimulateGas bool
ChainID string
@ -61,7 +61,7 @@ func (bldr TxBuilder) WithChainID(chainID string) TxBuilder {
}
// WithGas returns a copy of the context with an updated gas.
func (bldr TxBuilder) WithGas(gas int64) TxBuilder {
func (bldr TxBuilder) WithGas(gas uint64) TxBuilder {
bldr.Gas = gas
return bldr
}

View File

@ -9,8 +9,8 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/tendermint/tendermint/crypto/ed25519"
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
"github.com/tendermint/tendermint/crypto/ed25519"
)
var (
@ -23,7 +23,7 @@ func TestTxBuilderBuild(t *testing.T) {
Codec *codec.Codec
AccountNumber int64
Sequence int64
Gas int64
Gas uint64
GasAdjustment float64
SimulateGas bool
ChainID string

View File

@ -70,10 +70,10 @@ func (tx StdTx) GetSignatures() []StdSignature { return tx.Signatures }
// which must be above some miminum to be accepted into the mempool.
type StdFee struct {
Amount sdk.Coins `json:"amount"`
Gas int64 `json:"gas"`
Gas uint64 `json:"gas"`
}
func NewStdFee(gas int64, amount ...sdk.Coin) StdFee {
func NewStdFee(gas uint64, amount ...sdk.Coin) StdFee {
return StdFee{
Amount: amount,
Gas: gas,

View File

@ -144,7 +144,8 @@ func TestMsgSendWithAccounts(t *testing.T) {
tx.Signatures[0].Sequence = 1
res := mapp.Deliver(tx)
require.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnauthorized), res.Code, res.Log)
require.EqualValues(t, sdk.CodeUnauthorized, res.Code, res.Log)
require.EqualValues(t, sdk.CodespaceRoot, res.Codespace)
// resigning the tx with the bumped sequence should work
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{sendMsg1, sendMsg2}, []int64{0}, []int64{1}, true, true, priv1)

View File

@ -4,6 +4,7 @@ import (
"io/ioutil"
"os"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/spf13/cobra"
@ -36,7 +37,7 @@ in place of an input filename, the command reads from standard input.`,
},
}
return cmd
return client.PostCommands(cmd)[0]
}
func readAndUnmarshalStdTx(cdc *amino.Codec, filename string) (stdTx auth.StdTx, err error) {

View File

@ -1,13 +1,13 @@
package cli
import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/client/utils"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
"github.com/cosmos/cosmos-sdk/x/bank/client"
bankClient "github.com/cosmos/cosmos-sdk/x/bank/client"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@ -28,7 +28,7 @@ func SendTxCmd(cdc *codec.Codec) *cobra.Command {
txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc)
cliCtx := context.NewCLIContext().
WithCodec(cdc).
WithAccountDecoder(authcmd.GetAccountDecoder(cdc))
WithAccountDecoder(cdc)
if err := cliCtx.EnsureAccountExists(); err != nil {
return err
@ -64,7 +64,7 @@ func SendTxCmd(cdc *codec.Codec) *cobra.Command {
}
// build and sign the transaction, then broadcast to Tendermint
msg := client.CreateMsg(from, to, coins)
msg := bankClient.CreateMsg(from, to, coins)
if cliCtx.GenerateOnly {
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, false)
}
@ -78,5 +78,5 @@ func SendTxCmd(cdc *codec.Codec) *cobra.Command {
cmd.MarkFlagRequired(flagTo)
cmd.MarkFlagRequired(flagAmount)
return cmd
return client.PostCommands(cmd)[0]
}

View File

@ -7,7 +7,6 @@ import (
// Register concrete types on codec codec
func RegisterCodec(cdc *codec.Codec) {
cdc.RegisterConcrete(MsgSend{}, "cosmos-sdk/Send", nil)
cdc.RegisterConcrete(MsgIssue{}, "cosmos-sdk/Issue", nil)
}
var msgCdc = codec.New()

View File

@ -7,7 +7,7 @@ import (
// Bank errors reserve 100 ~ 199.
const (
DefaultCodespace sdk.CodespaceType = 2
DefaultCodespace sdk.CodespaceType = "bank"
CodeInvalidInput sdk.CodeType = 101
CodeInvalidOutput sdk.CodeType = 102

View File

@ -10,8 +10,6 @@ func NewHandler(k Keeper) sdk.Handler {
switch msg := msg.(type) {
case MsgSend:
return handleMsgSend(ctx, k, msg)
case MsgIssue:
return handleMsgIssue(ctx, k, msg)
default:
errMsg := "Unrecognized bank Msg type: %s" + msg.Type()
return sdk.ErrUnknownRequest(errMsg).Result()
@ -32,8 +30,3 @@ func handleMsgSend(ctx sdk.Context, k Keeper, msg MsgSend) sdk.Result {
Tags: tags,
}
}
// Handle MsgIssue.
func handleMsgIssue(ctx sdk.Context, k Keeper, msg MsgIssue) sdk.Result {
panic("not implemented yet")
}

View File

@ -182,11 +182,13 @@ func hasCoins(ctx sdk.Context, am auth.AccountKeeper, addr sdk.AccAddress, amt s
// SubtractCoins subtracts amt from the coins at the addr.
func subtractCoins(ctx sdk.Context, am auth.AccountKeeper, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Tags, sdk.Error) {
ctx.GasMeter().ConsumeGas(costSubtractCoins, "subtractCoins")
oldCoins := getCoins(ctx, am, addr)
newCoins := oldCoins.Minus(amt)
if !newCoins.IsNotNegative() {
newCoins, hasNeg := oldCoins.SafeMinus(amt)
if hasNeg {
return amt, nil, sdk.ErrInsufficientCoins(fmt.Sprintf("%s < %s", oldCoins, amt))
}
err := setCoins(ctx, am, addr, newCoins)
tags := sdk.NewTags("sender", []byte(addr.String()))
return newCoins, tags, err

View File

@ -86,65 +86,6 @@ func (msg MsgSend) GetSigners() []sdk.AccAddress {
return addrs
}
//----------------------------------------
// MsgIssue
// MsgIssue - high level transaction of the coin module
type MsgIssue struct {
Banker sdk.AccAddress `json:"banker"`
Outputs []Output `json:"outputs"`
}
var _ sdk.Msg = MsgIssue{}
// NewMsgIssue - construct arbitrary multi-in, multi-out send msg.
func NewMsgIssue(banker sdk.AccAddress, out []Output) MsgIssue {
return MsgIssue{Banker: banker, Outputs: out}
}
// Implements Msg.
// nolint
func (msg MsgIssue) Route() string { return "bank" } // TODO: "bank/issue"
func (msg MsgIssue) Type() string { return "issue" }
// Implements Msg.
func (msg MsgIssue) ValidateBasic() sdk.Error {
// XXX
if len(msg.Outputs) == 0 {
return ErrNoOutputs(DefaultCodespace).TraceSDK("")
}
for _, out := range msg.Outputs {
if err := out.ValidateBasic(); err != nil {
return err.TraceSDK("")
}
}
return nil
}
// Implements Msg.
func (msg MsgIssue) GetSignBytes() []byte {
var outputs []json.RawMessage
for _, output := range msg.Outputs {
outputs = append(outputs, output.GetSignBytes())
}
b, err := msgCdc.MarshalJSON(struct {
Banker sdk.AccAddress `json:"banker"`
Outputs []json.RawMessage `json:"outputs"`
}{
Banker: msg.Banker,
Outputs: outputs,
})
if err != nil {
panic(err)
}
return sdk.MustSortJSON(b)
}
// Implements Msg.
func (msg MsgIssue) GetSigners() []sdk.AccAddress {
return []sdk.AccAddress{msg.Banker}
}
//----------------------------------------
// Input

View File

@ -35,8 +35,6 @@ func TestInputValidation(t *testing.T) {
emptyCoins := sdk.Coins{}
emptyCoins2 := sdk.Coins{sdk.NewInt64Coin("eth", 0)}
someEmptyCoins := sdk.Coins{sdk.NewInt64Coin("eth", 10), sdk.NewInt64Coin("atom", 0)}
minusCoins := sdk.Coins{sdk.NewInt64Coin("eth", -34)}
someMinusCoins := sdk.Coins{sdk.NewInt64Coin("atom", 20), sdk.NewInt64Coin("eth", -34)}
unsortedCoins := sdk.Coins{sdk.NewInt64Coin("eth", 1), sdk.NewInt64Coin("atom", 1)}
cases := []struct {
@ -52,8 +50,6 @@ func TestInputValidation(t *testing.T) {
{false, NewInput(addr1, emptyCoins)}, // invalid coins
{false, NewInput(addr1, emptyCoins2)}, // invalid coins
{false, NewInput(addr1, someEmptyCoins)}, // invalid coins
{false, NewInput(addr1, minusCoins)}, // negative coins
{false, NewInput(addr1, someMinusCoins)}, // negative coins
{false, NewInput(addr1, unsortedCoins)}, // unsorted coins
}
@ -77,8 +73,6 @@ func TestOutputValidation(t *testing.T) {
emptyCoins := sdk.Coins{}
emptyCoins2 := sdk.Coins{sdk.NewInt64Coin("eth", 0)}
someEmptyCoins := sdk.Coins{sdk.NewInt64Coin("eth", 10), sdk.NewInt64Coin("atom", 0)}
minusCoins := sdk.Coins{sdk.NewInt64Coin("eth", -34)}
someMinusCoins := sdk.Coins{sdk.NewInt64Coin("atom", 20), sdk.NewInt64Coin("eth", -34)}
unsortedCoins := sdk.Coins{sdk.NewInt64Coin("eth", 1), sdk.NewInt64Coin("atom", 1)}
cases := []struct {
@ -94,8 +88,6 @@ func TestOutputValidation(t *testing.T) {
{false, NewOutput(addr1, emptyCoins)}, // invalid coins
{false, NewOutput(addr1, emptyCoins2)}, // invalid coins
{false, NewOutput(addr1, someEmptyCoins)}, // invalid coins
{false, NewOutput(addr1, minusCoins)}, // negative coins
{false, NewOutput(addr1, someMinusCoins)}, // negative coins
{false, NewOutput(addr1, unsortedCoins)}, // unsorted coins
}
@ -223,48 +215,3 @@ func TestMsgSendSigners(t *testing.T) {
require.Equal(t, signers, tx.Signers())
}
*/
// ----------------------------------------
// MsgIssue Tests
func TestNewMsgIssue(t *testing.T) {
// TODO
}
func TestMsgIssueRoute(t *testing.T) {
// Construct an MsgIssue
addr := sdk.AccAddress([]byte("loan-from-bank"))
coins := sdk.Coins{sdk.NewInt64Coin("atom", 10)}
var msg = MsgIssue{
Banker: sdk.AccAddress([]byte("input")),
Outputs: []Output{NewOutput(addr, coins)},
}
// TODO some failures for bad result
require.Equal(t, msg.Route(), "bank")
}
func TestMsgIssueValidation(t *testing.T) {
// TODO
}
func TestMsgIssueGetSignBytes(t *testing.T) {
addr := sdk.AccAddress([]byte("loan-from-bank"))
coins := sdk.Coins{sdk.NewInt64Coin("atom", 10)}
var msg = MsgIssue{
Banker: sdk.AccAddress([]byte("input")),
Outputs: []Output{NewOutput(addr, coins)},
}
res := msg.GetSignBytes()
expected := `{"banker":"cosmos1d9h8qat57ljhcm","outputs":[{"address":"cosmos1d3hkzm3dveex7mfdvfsku6cjngpcj","coins":[{"amount":"10","denom":"atom"}]}]}`
require.Equal(t, expected, string(res))
}
func TestMsgIssueGetSigners(t *testing.T) {
var msg = MsgIssue{
Banker: sdk.AccAddress([]byte("onlyone")),
}
res := msg.GetSigners()
require.Equal(t, fmt.Sprintf("%v", res), "[6F6E6C796F6E65]")
}

View File

@ -82,7 +82,7 @@ func createSingleInputSendMsg(r *rand.Rand, ctx sdk.Context, accs []simulation.A
toAddr.String(),
)
coins := sdk.Coins{{initFromCoins[denomIndex].Denom, amt}}
coins := sdk.Coins{sdk.NewCoin(initFromCoins[denomIndex].Denom, amt)}
msg = bank.MsgSend{
Inputs: []bank.Input{bank.NewInput(fromAcc.Address, coins)},
Outputs: []bank.Output{bank.NewOutput(toAddr, coins)},

View File

@ -6,12 +6,13 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
amino "github.com/tendermint/go-amino"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/client/utils"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
@ -22,6 +23,21 @@ var (
flagIsValidator = "is-validator"
)
// GetTxCmd returns the transaction commands for this module
func GetTxCmd(storeKey string, cdc *amino.Codec) *cobra.Command {
distTxCmd := &cobra.Command{
Use: "dist",
Short: "Distribution transactions subcommands",
}
distTxCmd.AddCommand(client.PostCommands(
GetCmdWithdrawRewards(cdc),
GetCmdSetWithdrawAddr(cdc),
)...)
return distTxCmd
}
// command to withdraw rewards
func GetCmdWithdrawRewards(cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
@ -41,7 +57,7 @@ func GetCmdWithdrawRewards(cdc *codec.Codec) *cobra.Command {
txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc)
cliCtx := context.NewCLIContext().
WithCodec(cdc).
WithAccountDecoder(authcmd.GetAccountDecoder(cdc))
WithAccountDecoder(cdc)
var msg sdk.Msg
switch {
@ -92,7 +108,7 @@ func GetCmdSetWithdrawAddr(cdc *codec.Codec) *cobra.Command {
txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc)
cliCtx := context.NewCLIContext().
WithCodec(cdc).
WithAccountDecoder(authcmd.GetAccountDecoder(cdc))
WithAccountDecoder(cdc)
delAddr, err := cliCtx.GetFromAddress()
if err != nil {

View File

@ -0,0 +1,38 @@
package client
import (
"github.com/cosmos/cosmos-sdk/client"
distCmds "github.com/cosmos/cosmos-sdk/x/distribution/client/cli"
"github.com/spf13/cobra"
amino "github.com/tendermint/go-amino"
)
// ModuleClient exports all client functionality from this module
type ModuleClient struct {
storeKey string
cdc *amino.Codec
}
func NewModuleClient(storeKey string, cdc *amino.Codec) ModuleClient {
return ModuleClient{storeKey, cdc}
}
// GetQueryCmd returns the cli query commands for this module
func (mc ModuleClient) GetQueryCmd() *cobra.Command {
return &cobra.Command{Hidden: true}
}
// GetTxCmd returns the transaction commands for this module
func (mc ModuleClient) GetTxCmd() *cobra.Command {
distTxCmd := &cobra.Command{
Use: "dist",
Short: "Distribution transactions subcommands",
}
distTxCmd.AddCommand(client.PostCommands(
distCmds.GetCmdWithdrawRewards(mc.cdc),
distCmds.GetCmdSetWithdrawAddr(mc.cdc),
)...)
return distTxCmd
}

View File

@ -8,7 +8,7 @@ import (
type CodeType = sdk.CodeType
const (
DefaultCodespace sdk.CodespaceType = 6
DefaultCodespace sdk.CodespaceType = "DISTR"
CodeInvalidInput CodeType = 103
CodeNoDistributionInfo CodeType = 104
)

324
x/gov/client/cli/query.go Normal file
View File

@ -0,0 +1,324 @@
package cli
import (
"fmt"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/gov"
govClientUtils "github.com/cosmos/cosmos-sdk/x/gov/client/utils"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
// GetCmdQueryProposal implements the query proposal command.
func GetCmdQueryProposal(queryRoute string, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "proposal",
Short: "Query details of a single proposal",
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
proposalID := uint64(viper.GetInt64(flagProposalID))
params := gov.QueryProposalParams{
ProposalID: proposalID,
}
bz, err := cdc.MarshalJSON(params)
if err != nil {
return err
}
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/proposal", queryRoute), bz)
if err != nil {
return err
}
fmt.Println(string(res))
return nil
},
}
cmd.Flags().String(flagProposalID, "", "proposalID of proposal being queried")
return cmd
}
// GetCmdQueryProposals implements a query proposals command.
func GetCmdQueryProposals(queryRoute string, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "proposals",
Short: "Query proposals with optional filters",
RunE: func(cmd *cobra.Command, args []string) error {
bechDepositerAddr := viper.GetString(flagDepositer)
bechVoterAddr := viper.GetString(flagVoter)
strProposalStatus := viper.GetString(flagStatus)
numLimit := uint64(viper.GetInt64(flagNumLimit))
params := gov.QueryProposalsParams{
Limit: numLimit,
}
if len(bechDepositerAddr) != 0 {
depositerAddr, err := sdk.AccAddressFromBech32(bechDepositerAddr)
if err != nil {
return err
}
params.Depositer = depositerAddr
}
if len(bechVoterAddr) != 0 {
voterAddr, err := sdk.AccAddressFromBech32(bechVoterAddr)
if err != nil {
return err
}
params.Voter = voterAddr
}
if len(strProposalStatus) != 0 {
proposalStatus, err := gov.ProposalStatusFromString(govClientUtils.NormalizeProposalStatus(strProposalStatus))
if err != nil {
return err
}
params.ProposalStatus = proposalStatus
}
bz, err := cdc.MarshalJSON(params)
if err != nil {
return err
}
cliCtx := context.NewCLIContext().WithCodec(cdc)
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/proposals", queryRoute), bz)
if err != nil {
return err
}
var matchingProposals []gov.Proposal
err = cdc.UnmarshalJSON(res, &matchingProposals)
if err != nil {
return err
}
if len(matchingProposals) == 0 {
fmt.Println("No matching proposals found")
return nil
}
for _, proposal := range matchingProposals {
fmt.Printf(" %d - %s\n", proposal.GetProposalID(), proposal.GetTitle())
}
return nil
},
}
cmd.Flags().String(flagNumLimit, "", "(optional) limit to latest [number] proposals. Defaults to all proposals")
cmd.Flags().String(flagDepositer, "", "(optional) filter by proposals deposited on by depositer")
cmd.Flags().String(flagVoter, "", "(optional) filter by proposals voted on by voted")
cmd.Flags().String(flagStatus, "", "(optional) filter proposals by proposal status, status: deposit_period/voting_period/passed/rejected")
return cmd
}
// Command to Get a Proposal Information
// GetCmdQueryVote implements the query proposal vote command.
func GetCmdQueryVote(queryRoute string, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "vote",
Short: "Query details of a single vote",
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
proposalID := uint64(viper.GetInt64(flagProposalID))
voterAddr, err := sdk.AccAddressFromBech32(viper.GetString(flagVoter))
if err != nil {
return err
}
params := gov.QueryVoteParams{
Voter: voterAddr,
ProposalID: proposalID,
}
bz, err := cdc.MarshalJSON(params)
if err != nil {
return err
}
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/vote", queryRoute), bz)
if err != nil {
return err
}
fmt.Println(string(res))
return nil
},
}
cmd.Flags().String(flagProposalID, "", "proposalID of proposal voting on")
cmd.Flags().String(flagVoter, "", "bech32 voter address")
return cmd
}
// GetCmdQueryVotes implements the command to query for proposal votes.
func GetCmdQueryVotes(queryRoute string, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "votes",
Short: "Query votes on a proposal",
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
proposalID := uint64(viper.GetInt64(flagProposalID))
params := gov.QueryVotesParams{
ProposalID: proposalID,
}
bz, err := cdc.MarshalJSON(params)
if err != nil {
return err
}
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/votes", queryRoute), bz)
if err != nil {
return err
}
fmt.Println(string(res))
return nil
},
}
cmd.Flags().String(flagProposalID, "", "proposalID of which proposal's votes are being queried")
return cmd
}
// Command to Get a specific Deposit Information
// GetCmdQueryDeposit implements the query proposal deposit command.
func GetCmdQueryDeposit(queryRoute string, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "deposit",
Short: "Query details of a deposit",
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
proposalID := uint64(viper.GetInt64(flagProposalID))
depositerAddr, err := sdk.AccAddressFromBech32(viper.GetString(flagDepositer))
if err != nil {
return err
}
params := gov.QueryDepositParams{
Depositer: depositerAddr,
ProposalID: proposalID,
}
bz, err := cdc.MarshalJSON(params)
if err != nil {
return err
}
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/deposit", queryRoute), bz)
if err != nil {
return err
}
fmt.Println(string(res))
return nil
},
}
cmd.Flags().String(flagProposalID, "", "proposalID of proposal deposited on")
cmd.Flags().String(flagDepositer, "", "bech32 depositer address")
return cmd
}
// GetCmdQueryDeposits implements the command to query for proposal deposits.
func GetCmdQueryDeposits(queryRoute string, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "deposits",
Short: "Query deposits on a proposal",
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
proposalID := uint64(viper.GetInt64(flagProposalID))
params := gov.QueryDepositsParams{
ProposalID: proposalID,
}
bz, err := cdc.MarshalJSON(params)
if err != nil {
return err
}
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/deposits", queryRoute), bz)
if err != nil {
return err
}
fmt.Println(string(res))
return nil
},
}
cmd.Flags().String(flagProposalID, "", "proposalID of which proposal's deposits are being queried")
return cmd
}
// GetCmdQueryTally implements the command to query for proposal tally result.
func GetCmdQueryTally(queryRoute string, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "tally",
Short: "Get the tally of a proposal vote",
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
proposalID := uint64(viper.GetInt64(flagProposalID))
params := gov.QueryTallyParams{
ProposalID: proposalID,
}
bz, err := cdc.MarshalJSON(params)
if err != nil {
return err
}
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/tally", queryRoute), bz)
if err != nil {
return err
}
fmt.Println(string(res))
return nil
},
}
cmd.Flags().String(flagProposalID, "", "proposalID of which proposal is being tallied")
return cmd
}
// GetCmdQueryProposal implements the query proposal command.
func GetCmdQueryParams(queryRoute string, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "param [param-type]",
Short: "Query the parameters (voting|tallying|deposit) of the governance process",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
paramType := args[0]
cliCtx := context.NewCLIContext().WithCodec(cdc)
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/params/%s", queryRoute, paramType), nil)
if err != nil {
return err
}
fmt.Println(string(res))
return nil
},
}
return cmd
}

View File

@ -7,7 +7,6 @@ import (
"github.com/cosmos/cosmos-sdk/client/utils"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
"github.com/cosmos/cosmos-sdk/x/gov"
@ -15,7 +14,7 @@ import (
"io/ioutil"
"strings"
"github.com/cosmos/cosmos-sdk/x/gov/client"
govClientUtils "github.com/cosmos/cosmos-sdk/x/gov/client/utils"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
@ -80,7 +79,7 @@ $ gaiacli gov submit-proposal --title="Test Proposal" --description="My awesome
txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc)
cliCtx := context.NewCLIContext().
WithCodec(cdc).
WithAccountDecoder(authcmd.GetAccountDecoder(cdc))
WithAccountDecoder(cdc)
fromAddr, err := cliCtx.GetFromAddress()
if err != nil {
@ -130,7 +129,7 @@ func parseSubmitProposalFlags() (*proposal, error) {
if proposalFile == "" {
proposal.Title = viper.GetString(flagTitle)
proposal.Description = viper.GetString(flagDescription)
proposal.Type = client.NormalizeProposalType(viper.GetString(flagProposalType))
proposal.Type = govClientUtils.NormalizeProposalType(viper.GetString(flagProposalType))
proposal.Deposit = viper.GetString(flagDeposit)
return proposal, nil
}
@ -163,7 +162,7 @@ func GetCmdDeposit(cdc *codec.Codec) *cobra.Command {
txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc)
cliCtx := context.NewCLIContext().
WithCodec(cdc).
WithAccountDecoder(authcmd.GetAccountDecoder(cdc))
WithAccountDecoder(cdc)
depositerAddr, err := cliCtx.GetFromAddress()
if err != nil {
@ -208,7 +207,7 @@ func GetCmdVote(cdc *codec.Codec) *cobra.Command {
txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc)
cliCtx := context.NewCLIContext().
WithCodec(cdc).
WithAccountDecoder(authcmd.GetAccountDecoder(cdc))
WithAccountDecoder(cdc)
voterAddr, err := cliCtx.GetFromAddress()
if err != nil {
@ -218,7 +217,7 @@ func GetCmdVote(cdc *codec.Codec) *cobra.Command {
proposalID := uint64(viper.GetInt64(flagProposalID))
option := viper.GetString(flagOption)
byteVoteOption, err := gov.VoteOptionFromString(client.NormalizeVoteOption(option))
byteVoteOption, err := gov.VoteOptionFromString(govClientUtils.NormalizeVoteOption(option))
if err != nil {
return err
}
@ -248,314 +247,3 @@ func GetCmdVote(cdc *codec.Codec) *cobra.Command {
return cmd
}
// GetCmdQueryProposal implements the query proposal command.
func GetCmdQueryParams(queryRoute string, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "param [param-type]",
Short: "Query the parameters (voting|tallying|deposit) of the governance process",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
paramType := args[0]
cliCtx := context.NewCLIContext().WithCodec(cdc)
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/params/%s", queryRoute, paramType), nil)
if err != nil {
return err
}
fmt.Println(string(res))
return nil
},
}
return cmd
}
// GetCmdQueryProposal implements the query proposal command.
func GetCmdQueryProposal(queryRoute string, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "proposal",
Short: "Query details of a single proposal",
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
proposalID := uint64(viper.GetInt64(flagProposalID))
params := gov.QueryProposalParams{
ProposalID: proposalID,
}
bz, err := cdc.MarshalJSON(params)
if err != nil {
return err
}
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/proposal", queryRoute), bz)
if err != nil {
return err
}
fmt.Println(string(res))
return nil
},
}
cmd.Flags().String(flagProposalID, "", "proposalID of proposal being queried")
return cmd
}
// GetCmdQueryProposals implements a query proposals command.
func GetCmdQueryProposals(queryRoute string, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "proposals",
Short: "Query proposals with optional filters",
RunE: func(cmd *cobra.Command, args []string) error {
bechDepositerAddr := viper.GetString(flagDepositer)
bechVoterAddr := viper.GetString(flagVoter)
strProposalStatus := viper.GetString(flagStatus)
numLimit := uint64(viper.GetInt64(flagNumLimit))
params := gov.QueryProposalsParams{
Limit: numLimit,
}
if len(bechDepositerAddr) != 0 {
depositerAddr, err := sdk.AccAddressFromBech32(bechDepositerAddr)
if err != nil {
return err
}
params.Depositer = depositerAddr
}
if len(bechVoterAddr) != 0 {
voterAddr, err := sdk.AccAddressFromBech32(bechVoterAddr)
if err != nil {
return err
}
params.Voter = voterAddr
}
if len(strProposalStatus) != 0 {
proposalStatus, err := gov.ProposalStatusFromString(client.NormalizeProposalStatus(strProposalStatus))
if err != nil {
return err
}
params.ProposalStatus = proposalStatus
}
bz, err := cdc.MarshalJSON(params)
if err != nil {
return err
}
cliCtx := context.NewCLIContext().WithCodec(cdc)
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/proposals", queryRoute), bz)
if err != nil {
return err
}
var matchingProposals []gov.Proposal
err = cdc.UnmarshalJSON(res, &matchingProposals)
if err != nil {
return err
}
if len(matchingProposals) == 0 {
fmt.Println("No matching proposals found")
return nil
}
for _, proposal := range matchingProposals {
fmt.Printf(" %d - %s\n", proposal.GetProposalID(), proposal.GetTitle())
}
return nil
},
}
cmd.Flags().String(flagNumLimit, "", "(optional) limit to latest [number] proposals. Defaults to all proposals")
cmd.Flags().String(flagDepositer, "", "(optional) filter by proposals deposited on by depositer")
cmd.Flags().String(flagVoter, "", "(optional) filter by proposals voted on by voted")
cmd.Flags().String(flagStatus, "", "(optional) filter proposals by proposal status, status: deposit_period/voting_period/passed/rejected")
return cmd
}
// Command to Get a Proposal Information
// GetCmdQueryVote implements the query proposal vote command.
func GetCmdQueryVote(queryRoute string, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "vote",
Short: "Query details of a single vote",
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
proposalID := uint64(viper.GetInt64(flagProposalID))
voterAddr, err := sdk.AccAddressFromBech32(viper.GetString(flagVoter))
if err != nil {
return err
}
params := gov.QueryVoteParams{
Voter: voterAddr,
ProposalID: proposalID,
}
bz, err := cdc.MarshalJSON(params)
if err != nil {
return err
}
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/vote", queryRoute), bz)
if err != nil {
return err
}
fmt.Println(string(res))
return nil
},
}
cmd.Flags().String(flagProposalID, "", "proposalID of proposal voting on")
cmd.Flags().String(flagVoter, "", "bech32 voter address")
return cmd
}
// GetCmdQueryVotes implements the command to query for proposal votes.
func GetCmdQueryVotes(queryRoute string, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "votes",
Short: "Query votes on a proposal",
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
proposalID := uint64(viper.GetInt64(flagProposalID))
params := gov.QueryVotesParams{
ProposalID: proposalID,
}
bz, err := cdc.MarshalJSON(params)
if err != nil {
return err
}
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/votes", queryRoute), bz)
if err != nil {
return err
}
fmt.Println(string(res))
return nil
},
}
cmd.Flags().String(flagProposalID, "", "proposalID of which proposal's votes are being queried")
return cmd
}
// Command to Get a specific Deposit Information
// GetCmdQueryDeposit implements the query proposal deposit command.
func GetCmdQueryDeposit(queryRoute string, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "deposit",
Short: "Query details of a deposit",
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
proposalID := uint64(viper.GetInt64(flagProposalID))
depositerAddr, err := sdk.AccAddressFromBech32(viper.GetString(flagDepositer))
if err != nil {
return err
}
params := gov.QueryDepositParams{
Depositer: depositerAddr,
ProposalID: proposalID,
}
bz, err := cdc.MarshalJSON(params)
if err != nil {
return err
}
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/deposit", queryRoute), bz)
if err != nil {
return err
}
fmt.Println(string(res))
return nil
},
}
cmd.Flags().String(flagProposalID, "", "proposalID of proposal deposited on")
cmd.Flags().String(flagDepositer, "", "bech32 depositer address")
return cmd
}
// GetCmdQueryDeposits implements the command to query for proposal deposits.
func GetCmdQueryDeposits(queryRoute string, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "deposits",
Short: "Query deposits on a proposal",
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
proposalID := uint64(viper.GetInt64(flagProposalID))
params := gov.QueryDepositsParams{
ProposalID: proposalID,
}
bz, err := cdc.MarshalJSON(params)
if err != nil {
return err
}
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/deposits", queryRoute), bz)
if err != nil {
return err
}
fmt.Println(string(res))
return nil
},
}
cmd.Flags().String(flagProposalID, "", "proposalID of which proposal's deposits are being queried")
return cmd
}
// GetCmdQueryTally implements the command to query for proposal tally result.
func GetCmdQueryTally(queryRoute string, cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "tally",
Short: "Get the tally of a proposal vote",
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
proposalID := uint64(viper.GetInt64(flagProposalID))
params := gov.QueryTallyParams{
ProposalID: proposalID,
}
bz, err := cdc.MarshalJSON(params)
if err != nil {
return err
}
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/tally", queryRoute), bz)
if err != nil {
return err
}
fmt.Println(string(res))
return nil
},
}
cmd.Flags().String(flagProposalID, "", "proposalID of which proposal is being tallied")
return cmd
}

View File

@ -0,0 +1,55 @@
package client
import (
"github.com/cosmos/cosmos-sdk/client"
govCli "github.com/cosmos/cosmos-sdk/x/gov/client/cli"
"github.com/spf13/cobra"
amino "github.com/tendermint/go-amino"
)
// ModuleClient exports all client functionality from this module
type ModuleClient struct {
storeKey string
cdc *amino.Codec
}
func NewModuleClient(storeKey string, cdc *amino.Codec) ModuleClient {
return ModuleClient{storeKey, cdc}
}
// GetQueryCmd returns the cli query commands for this module
func (mc ModuleClient) GetQueryCmd() *cobra.Command {
// Group gov queries under a subcommand
govQueryCmd := &cobra.Command{
Use: "gov",
Short: "Querying commands for the governance module",
}
govQueryCmd.AddCommand(client.GetCommands(
govCli.GetCmdQueryProposal(mc.storeKey, mc.cdc),
govCli.GetCmdQueryProposals(mc.storeKey, mc.cdc),
govCli.GetCmdQueryVote(mc.storeKey, mc.cdc),
govCli.GetCmdQueryVotes(mc.storeKey, mc.cdc),
govCli.GetCmdQueryParams(mc.storeKey, mc.cdc),
govCli.GetCmdQueryDeposit(mc.storeKey, mc.cdc),
govCli.GetCmdQueryDeposits(mc.storeKey, mc.cdc),
govCli.GetCmdQueryTally(mc.storeKey, mc.cdc))...)
return govQueryCmd
}
// GetTxCmd returns the transaction commands for this module
func (mc ModuleClient) GetTxCmd() *cobra.Command {
govTxCmd := &cobra.Command{
Use: "gov",
Short: "Governance transactions subcommands",
}
govTxCmd.AddCommand(client.PostCommands(
govCli.GetCmdDeposit(mc.cdc),
govCli.GetCmdVote(mc.cdc),
govCli.GetCmdSubmitProposal(mc.cdc),
)...)
return govTxCmd
}

View File

@ -10,7 +10,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/gov"
"github.com/cosmos/cosmos-sdk/x/gov/client"
govClientUtils "github.com/cosmos/cosmos-sdk/x/gov/client/utils"
"github.com/gorilla/mux"
"github.com/pkg/errors"
)
@ -81,7 +81,7 @@ func postProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Han
return
}
proposalType, err := gov.ProposalTypeFromString(client.NormalizeProposalType(req.ProposalType))
proposalType, err := gov.ProposalTypeFromString(govClientUtils.NormalizeProposalType(req.ProposalType))
if err != nil {
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
@ -165,7 +165,7 @@ func voteHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc
return
}
voteOption, err := gov.VoteOptionFromString(client.NormalizeVoteOption(req.Option))
voteOption, err := gov.VoteOptionFromString(govClientUtils.NormalizeVoteOption(req.Option))
if err != nil {
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
@ -460,7 +460,7 @@ func queryProposalsWithParameterFn(cdc *codec.Codec, cliCtx context.CLIContext)
}
if len(strProposalStatus) != 0 {
proposalStatus, err := gov.ProposalStatusFromString(client.NormalizeProposalStatus(strProposalStatus))
proposalStatus, err := gov.ProposalStatusFromString(govClientUtils.NormalizeProposalStatus(strProposalStatus))
if err != nil {
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return

View File

@ -1,4 +1,4 @@
package client
package utils
// NormalizeVoteOption - normalize user specified vote option
func NormalizeVoteOption(option string) string {

View File

@ -8,7 +8,7 @@ import (
)
const (
DefaultCodespace sdk.CodespaceType = 5
DefaultCodespace sdk.CodespaceType = "GOV"
CodeUnknownProposal sdk.CodeType = 1
CodeInactiveProposal sdk.CodeType = 2

View File

@ -13,7 +13,6 @@ import (
var (
coinsPos = sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 1000)}
coinsZero = sdk.Coins{}
coinsNeg = sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, -10000)}
coinsPosNotAtoms = sdk.Coins{sdk.NewInt64Coin("foo", 10000)}
coinsMulti = sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 1000), sdk.NewInt64Coin("foo", 10000)}
)
@ -40,7 +39,6 @@ func TestMsgSubmitProposal(t *testing.T) {
{"Test Proposal", "the purpose of this proposal is to test", 0x05, addrs[0], coinsPos, false},
{"Test Proposal", "the purpose of this proposal is to test", ProposalTypeText, sdk.AccAddress{}, coinsPos, false},
{"Test Proposal", "the purpose of this proposal is to test", ProposalTypeText, addrs[0], coinsZero, true},
{"Test Proposal", "the purpose of this proposal is to test", ProposalTypeText, addrs[0], coinsNeg, false},
{"Test Proposal", "the purpose of this proposal is to test", ProposalTypeText, addrs[0], coinsMulti, true},
}
@ -66,7 +64,6 @@ func TestMsgDeposit(t *testing.T) {
{0, addrs[0], coinsPos, true},
{1, sdk.AccAddress{}, coinsPos, false},
{1, addrs[0], coinsZero, true},
{1, addrs[0], coinsNeg, false},
{1, addrs[0], coinsMulti, true},
}

View File

@ -35,7 +35,7 @@ func getMockApp(t *testing.T, numGenAccs int) (*mock.App, Keeper, stake.Keeper,
pk := params.NewKeeper(mapp.Cdc, keyGlobalParams, tkeyGlobalParams)
ck := bank.NewBaseKeeper(mapp.AccountKeeper)
sk := stake.NewKeeper(mapp.Cdc, keyStake, tkeyStake, ck, pk.Subspace(stake.DefaultParamspace), mapp.RegisterCodespace(stake.DefaultCodespace))
sk := stake.NewKeeper(mapp.Cdc, keyStake, tkeyStake, ck, pk.Subspace(stake.DefaultParamspace), stake.DefaultCodespace)
keeper := NewKeeper(mapp.Cdc, keyGov, pk, pk.Subspace("testgov"), ck, sk, DefaultCodespace)
mapp.Router().AddRoute("gov", NewHandler(keeper))

View File

@ -20,7 +20,7 @@ func getMockApp(t *testing.T) *mock.App {
RegisterCodec(mapp.Cdc)
keyIBC := sdk.NewKVStoreKey("ibc")
ibcMapper := NewMapper(mapp.Cdc, keyIBC, mapp.RegisterCodespace(DefaultCodespace))
ibcMapper := NewMapper(mapp.Cdc, keyIBC, DefaultCodespace)
bankKeeper := bank.NewBaseKeeper(mapp.AccountKeeper)
mapp.Router().AddRoute("ibc", NewHandler(ibcMapper, bankKeeper))

View File

@ -8,7 +8,6 @@ import (
"github.com/cosmos/cosmos-sdk/client/utils"
codec "github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
"github.com/cosmos/cosmos-sdk/x/ibc"
@ -30,7 +29,7 @@ func IBCTransferCmd(cdc *codec.Codec) *cobra.Command {
txBldr := authtxb.NewTxBuilderFromCLI().WithCodec(cdc)
cliCtx := context.NewCLIContext().
WithCodec(cdc).
WithAccountDecoder(authcmd.GetAccountDecoder(cdc))
WithAccountDecoder(cdc)
from, err := cliCtx.GetFromAddress()
if err != nil {

View File

@ -9,7 +9,6 @@ import (
codec "github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
"github.com/cosmos/cosmos-sdk/x/ibc"
@ -42,7 +41,7 @@ type relayCommander struct {
func IBCRelayCmd(cdc *codec.Codec) *cobra.Command {
cmdr := relayCommander{
cdc: cdc,
decoder: authcmd.GetAccountDecoder(cdc),
decoder: context.GetAccountDecoder(cdc),
ibcStore: "ibc",
mainStore: "main",
accStore: "acc",

View File

@ -6,7 +6,7 @@ import (
// IBC errors reserve 200 ~ 299.
const (
DefaultCodespace sdk.CodespaceType = 3
DefaultCodespace sdk.CodespaceType = "ibc"
// IBC errors reserve 200 - 299.
CodeInvalidSequence sdk.CodeType = 200

View File

@ -44,7 +44,6 @@ func makeCodec() *codec.Codec {
// Register Msgs
cdc.RegisterInterface((*sdk.Msg)(nil), nil)
cdc.RegisterConcrete(bank.MsgSend{}, "test/ibc/Send", nil)
cdc.RegisterConcrete(bank.MsgIssue{}, "test/ibc/Issue", nil)
cdc.RegisterConcrete(IBCTransferMsg{}, "test/ibc/IBCTransferMsg", nil)
cdc.RegisterConcrete(IBCReceiveMsg{}, "test/ibc/IBCReceiveMsg", nil)

View File

@ -71,7 +71,9 @@ func TestCheckAndDeliverGenTx(t *testing.T) {
[]int64{accs[1].GetAccountNumber()}, []int64{accs[1].GetSequence() + 1},
true, false, privKeys[1],
)
require.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnauthorized), res.Code, res.Log)
require.Equal(t, sdk.CodeUnauthorized, res.Code, res.Log)
require.Equal(t, sdk.CodespaceRoot, res.Codespace)
// Resigning the tx with the correct privKey should result in an OK result
SignCheckDeliver(

View File

@ -57,9 +57,9 @@ func CheckGenTx(
res := app.Check(tx)
if expPass {
require.Equal(t, sdk.ABCICodeOK, res.Code, res.Log)
require.Equal(t, sdk.CodeOK, res.Code, res.Log)
} else {
require.NotEqual(t, sdk.ABCICodeOK, res.Code, res.Log)
require.NotEqual(t, sdk.CodeOK, res.Code, res.Log)
}
return res
@ -78,9 +78,9 @@ func SignCheckDeliver(
res := app.Simulate(tx)
if expSimPass {
require.Equal(t, sdk.ABCICodeOK, res.Code, res.Log)
require.Equal(t, sdk.CodeOK, res.Code, res.Log)
} else {
require.NotEqual(t, sdk.ABCICodeOK, res.Code, res.Log)
require.NotEqual(t, sdk.CodeOK, res.Code, res.Log)
}
// Simulate a sending a transaction and committing a block
@ -88,9 +88,9 @@ func SignCheckDeliver(
res = app.Deliver(tx)
if expPass {
require.Equal(t, sdk.ABCICodeOK, res.Code, res.Log)
require.Equal(t, sdk.CodeOK, res.Code, res.Log)
} else {
require.NotEqual(t, sdk.ABCICodeOK, res.Code, res.Log)
require.NotEqual(t, sdk.CodeOK, res.Code, res.Log)
}
app.EndBlock(abci.RequestEndBlock{})

Some files were not shown because too many files have changed in this diff Show More