Merge PR #5421: Refactor Error Handling

This commit is contained in:
Alexander Bezobchuk 2019-12-27 12:57:54 -05:00 committed by GitHub
parent 3c82b66347
commit 9a183ffbcc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
170 changed files with 2317 additions and 2934 deletions

View File

@ -50,7 +50,20 @@ logic has been implemented for v0.38 target version. Applications can migrate vi
### API Breaking Changes
* (client) [\#5442](https://github.com/cosmos/cosmos-sdk/pull/5442) Remove client/alias.go as it's not necessary and
* (baseapp/types) [\#5421](https://github.com/cosmos/cosmos-sdk/pull/5421) The `Error` interface (`types/errors.go`)
has been removed in favor of the concrete type defined in `types/errors/` which implements the standard `error`
interface. As a result, the `Handler` and `Querier` implementations now return a standard `error`.
Within `BaseApp`, `runTx` now returns a `(GasInfo, *Result, error)` tuple and `runMsgs` returns a
`(*Result, error)` tuple. A reference to a `Result` is now used to indicate success whereas an error
signals an invalid message or failed message execution. As a result, the fields `Code`, `Codespace`,
`GasWanted`, and `GasUsed` have been removed the `Result` type. The latter two fields are now found
in the `GasInfo` type which is always returned regardless of execution outcome.
Note to developers: Since all handlers and queriers must now return a standard `error`, the `types/errors/`
package contains all the relevant and pre-registered errors that you typically work with. A typical
error returned will look like `sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "...")`. You can retrieve
relevant ABCI information from the error via `ABCIInfo`.
* (client) [\#5442](https://github.com/cosmos/cosmos-sdk/pull/5442) Remove client/alias.go as it's not necessary and
components can be imported directly from the packages.
* (store) [\#4748](https://github.com/cosmos/cosmos-sdk/pull/4748) The `CommitMultiStore` interface
now requires a `SetInterBlockCache` method. Applications that do not wish to support this can simply

View File

@ -11,6 +11,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
// InitChain implements the ABCI interface. It runs the initialization logic
@ -153,54 +154,66 @@ func (app *BaseApp) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBloc
return
}
// CheckTx implements the ABCI interface. It runs the "basic checks" to see
// whether or not a transaction can possibly be executed, first decoding and then
// the ante handler (which checks signatures/fees/ValidateBasic).
//
// NOTE:CheckTx does not run the actual Msg handler function(s).
func (app *BaseApp) CheckTx(req abci.RequestCheckTx) (res abci.ResponseCheckTx) {
var result sdk.Result
// CheckTx implements the ABCI interface and executes a tx in CheckTx mode. In
// CheckTx mode, messages are not executed. This means messages are only validated
// and only the AnteHandler is executed. State is persisted to the BaseApp's
// internal CheckTx state if the AnteHandler passes. Otherwise, the ResponseCheckTx
// will contain releveant error information. Regardless of tx execution outcome,
// the ResponseCheckTx will contain relevant gas execution context.
func (app *BaseApp) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx {
tx, err := app.txDecoder(req.Tx)
if err != nil {
return sdkerrors.ResponseCheckTx(err, 0, 0)
}
var mode runTxMode
switch {
case err != nil:
result = err.Result()
case req.Type == abci.CheckTxType_New:
result = app.runTx(runTxModeCheck, req.Tx, tx)
mode = runTxModeCheck
case req.Type == abci.CheckTxType_Recheck:
result = app.runTx(runTxModeReCheck, req.Tx, tx)
mode = runTxModeReCheck
default:
panic(fmt.Sprintf("Unknown RequestCheckTx Type: %v", req.Type))
panic(fmt.Sprintf("unknown RequestCheckTx type: %s", req.Type))
}
gInfo, result, err := app.runTx(mode, req.Tx, tx)
if err != nil {
return sdkerrors.ResponseCheckTx(err, gInfo.GasWanted, gInfo.GasUsed)
}
return abci.ResponseCheckTx{
Code: uint32(result.Code),
Data: result.Data,
GasWanted: int64(gInfo.GasWanted), // TODO: Should type accept unsigned ints?
GasUsed: int64(gInfo.GasUsed), // TODO: Should type accept unsigned ints?
Log: result.Log,
GasWanted: int64(result.GasWanted), // TODO: Should type accept unsigned ints?
GasUsed: int64(result.GasUsed), // TODO: Should type accept unsigned ints?
Data: result.Data,
Events: result.Events.ToABCIEvents(),
}
}
// DeliverTx implements the ABCI interface.
func (app *BaseApp) DeliverTx(req abci.RequestDeliverTx) (res abci.ResponseDeliverTx) {
var result sdk.Result
// DeliverTx implements the ABCI interface and executes a tx in DeliverTx mode.
// State only gets persisted if all messages are valid and get executed successfully.
// Otherwise, the ResponseDeliverTx will contain releveant error information.
// Regardless of tx execution outcome, the ResponseDeliverTx will contain relevant
// gas execution context.
func (app *BaseApp) DeliverTx(req abci.RequestDeliverTx) abci.ResponseDeliverTx {
tx, err := app.txDecoder(req.Tx)
if err != nil {
result = err.Result()
} else {
result = app.runTx(runTxModeDeliver, req.Tx, tx)
return sdkerrors.ResponseDeliverTx(err, 0, 0)
}
gInfo, result, err := app.runTx(runTxModeDeliver, req.Tx, tx)
if err != nil {
return sdkerrors.ResponseDeliverTx(err, gInfo.GasWanted, gInfo.GasUsed)
}
return abci.ResponseDeliverTx{
Code: uint32(result.Code),
Codespace: string(result.Codespace),
Data: result.Data,
GasWanted: int64(gInfo.GasWanted), // TODO: Should type accept unsigned ints?
GasUsed: int64(gInfo.GasUsed), // TODO: Should type accept unsigned ints?
Log: result.Log,
GasWanted: int64(result.GasWanted), // TODO: Should type accept unsigned ints?
GasUsed: int64(result.GasUsed), // TODO: Should type accept unsigned ints?
Data: result.Data,
Events: result.Events.ToABCIEvents(),
}
}
@ -278,11 +291,10 @@ func (app *BaseApp) halt() {
// Query implements the ABCI interface. It delegates to CommitMultiStore if it
// implements Queryable.
func (app *BaseApp) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
func (app *BaseApp) Query(req abci.RequestQuery) abci.ResponseQuery {
path := splitPath(req.Path)
if len(path) == 0 {
msg := "no query path provided"
return sdk.ErrUnknownRequest(msg).QueryResult()
sdkerrors.QueryResult(sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "no query path provided"))
}
switch path[0] {
@ -294,61 +306,59 @@ func (app *BaseApp) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
return handleQueryStore(app, path, req)
case "p2p":
return handleQueryP2P(app, path, req)
return handleQueryP2P(app, path)
case "custom":
return handleQueryCustom(app, path, req)
}
msg := "unknown query path"
return sdk.ErrUnknownRequest(msg).QueryResult()
return sdkerrors.QueryResult(sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "unknown query path"))
}
func handleQueryApp(app *BaseApp, path []string, req abci.RequestQuery) (res abci.ResponseQuery) {
func handleQueryApp(app *BaseApp, path []string, req abci.RequestQuery) abci.ResponseQuery {
if len(path) >= 2 {
var result sdk.Result
switch path[1] {
case "simulate":
txBytes := req.Data
tx, err := app.txDecoder(txBytes)
if err != nil {
result = err.Result()
} else {
result = app.Simulate(txBytes, tx)
return sdkerrors.QueryResult(sdkerrors.Wrap(err, "failed to decode tx"))
}
gInfo, _, _ := app.Simulate(txBytes, tx)
return abci.ResponseQuery{
Codespace: sdkerrors.RootCodespace,
Height: req.Height,
Value: codec.Cdc.MustMarshalBinaryLengthPrefixed(gInfo.GasUsed),
}
case "version":
return abci.ResponseQuery{
Code: uint32(sdk.CodeOK),
Codespace: string(sdk.CodespaceRoot),
Codespace: sdkerrors.RootCodespace,
Height: req.Height,
Value: []byte(app.appVersion),
}
default:
result = sdk.ErrUnknownRequest(fmt.Sprintf("unknown query: %s", path)).Result()
}
value := codec.Cdc.MustMarshalBinaryLengthPrefixed(result)
return abci.ResponseQuery{
Code: uint32(sdk.CodeOK),
Codespace: string(sdk.CodespaceRoot),
Height: req.Height,
Value: value,
return sdkerrors.QueryResult(sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown query: %s", path))
}
}
msg := "expected second parameter to be either 'simulate' or 'version', neither was present"
return sdk.ErrUnknownRequest(msg).QueryResult()
return sdkerrors.QueryResult(
sdkerrors.Wrap(
sdkerrors.ErrUnknownRequest,
"expected second parameter to be either 'simulate' or 'version', neither was present",
),
)
}
func handleQueryStore(app *BaseApp, path []string, req abci.RequestQuery) abci.ResponseQuery {
// "/store" prefix for store queries
queryable, ok := app.cms.(sdk.Queryable)
if !ok {
msg := "multistore doesn't support queries"
return sdk.ErrUnknownRequest(msg).QueryResult()
return sdkerrors.QueryResult(sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "multistore doesn't support queries"))
}
req.Path = "/" + strings.Join(path[1:], "/")
@ -359,7 +369,12 @@ func handleQueryStore(app *BaseApp, path []string, req abci.RequestQuery) abci.R
}
if req.Height <= 1 && req.Prove {
return sdk.ErrInternal("cannot query with proof when height <= 1; please provide a valid height").QueryResult()
return sdkerrors.QueryResult(
sdkerrors.Wrap(
sdkerrors.ErrInvalidRequest,
"cannot query with proof when height <= 1; please provide a valid height",
),
)
}
resp := queryable.Query(req)
@ -368,7 +383,7 @@ func handleQueryStore(app *BaseApp, path []string, req abci.RequestQuery) abci.R
return resp
}
func handleQueryP2P(app *BaseApp, path []string, _ abci.RequestQuery) (res abci.ResponseQuery) {
func handleQueryP2P(app *BaseApp, path []string) abci.ResponseQuery {
// "/p2p" prefix for p2p queries
if len(path) >= 4 {
cmd, typ, arg := path[1], path[2], path[3]
@ -383,28 +398,30 @@ func handleQueryP2P(app *BaseApp, path []string, _ abci.RequestQuery) (res abci.
}
default:
msg := "expected second parameter to be 'filter'"
return sdk.ErrUnknownRequest(msg).QueryResult()
return sdkerrors.QueryResult(sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "expected second parameter to be 'filter'"))
}
}
msg := "Expected path is p2p filter <addr|id> <parameter>"
return sdk.ErrUnknownRequest(msg).QueryResult()
return sdkerrors.QueryResult(
sdkerrors.Wrap(
sdkerrors.ErrUnknownRequest, "expected path is p2p filter <addr|id> <parameter>",
),
)
}
func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res abci.ResponseQuery) {
func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) abci.ResponseQuery {
// path[0] should be "custom" because "/custom" prefix is required for keeper
// queries.
//
// The QueryRouter routes using path[1]. For example, in the path
// "custom/gov/proposal", QueryRouter routes using "gov".
if len(path) < 2 || path[1] == "" {
return sdk.ErrUnknownRequest("No route for custom query specified").QueryResult()
return sdkerrors.QueryResult(sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "no route for custom query specified"))
}
querier := app.queryRouter.Route(path[1])
if querier == nil {
return sdk.ErrUnknownRequest(fmt.Sprintf("no custom querier found for route %s", path[1])).QueryResult()
return sdkerrors.QueryResult(sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "no custom querier found for route %s", path[1]))
}
// when a client did not provide a query height, manually inject the latest
@ -413,17 +430,22 @@ func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res
}
if req.Height <= 1 && req.Prove {
return sdk.ErrInternal("cannot query with proof when height <= 1; please provide a valid height").QueryResult()
return sdkerrors.QueryResult(
sdkerrors.Wrap(
sdkerrors.ErrInvalidRequest,
"cannot query with proof when height <= 1; please provide a valid height",
),
)
}
cacheMS, err := app.cms.CacheMultiStoreWithVersion(req.Height)
if err != nil {
return sdk.ErrInternal(
fmt.Sprintf(
"failed to load state at height %d; %s (latest height: %d)",
req.Height, err, app.LastBlockHeight(),
return sdkerrors.QueryResult(
sdkerrors.Wrapf(
sdkerrors.ErrInvalidRequest,
"failed to load state at height %d; %s (latest height: %d)", req.Height, err, app.LastBlockHeight(),
),
).QueryResult()
)
}
// cache wrap the commit-multistore for safety
@ -435,18 +457,18 @@ func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res
//
// For example, in the path "custom/gov/proposal/test", the gov querier gets
// []string{"proposal", "test"} as the path.
resBytes, queryErr := querier(ctx, path[2:], req)
if queryErr != nil {
resBytes, err := querier(ctx, path[2:], req)
if err != nil {
space, code, log := sdkerrors.ABCIInfo(err, false)
return abci.ResponseQuery{
Code: uint32(queryErr.Code()),
Codespace: string(queryErr.Codespace()),
Code: code,
Codespace: space,
Log: log,
Height: req.Height,
Log: queryErr.ABCILog(),
}
}
return abci.ResponseQuery{
Code: uint32(sdk.CodeOK),
Height: req.Height,
Value: resBytes,
}

View File

@ -19,6 +19,7 @@ import (
"github.com/cosmos/cosmos-sdk/store"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
const (
@ -446,13 +447,12 @@ func (app *BaseApp) validateHeight(req abci.RequestBeginBlock) error {
}
// validateBasicTxMsgs executes basic validator calls for messages.
func validateBasicTxMsgs(msgs []sdk.Msg) sdk.Error {
func validateBasicTxMsgs(msgs []sdk.Msg) error {
if len(msgs) == 0 {
return sdk.ErrUnknownRequest("Tx.GetMsgs() must return at least one message in list")
return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "must contain at least one message")
}
for _, msg := range msgs {
// Validate the Msg.
err := msg.ValidateBasic()
if err != nil {
return err
@ -508,11 +508,14 @@ func (app *BaseApp) cacheTxContext(ctx sdk.Context, txBytes []byte) (sdk.Context
return ctx.WithMultiStore(msCache), msCache
}
// runTx processes a transaction. The transactions is processed via an
// 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) {
// runTx processes a transaction within a given execution mode, encoded transaction
// bytes, and the decoded transaction itself. All state transitions occur through
// a cached Context depending on the mode provided. State only gets persisted
// if all messages get executed successfully and the execution mode is DeliverTx.
// Note, gas execution info is always returned. A reference to a Result is
// returned if the tx does not run out of gas and if all the messages are valid
// and execute successfully. An error is returned otherwise.
func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (gInfo sdk.GasInfo, result *sdk.Result, err error) {
// 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.
@ -523,7 +526,8 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk
// only run the tx if there is block gas remaining
if mode == runTxModeDeliver && ctx.BlockGasMeter().IsOutOfGas() {
return sdk.ErrOutOfGas("no block gas left to run tx").Result()
gInfo = sdk.GasInfo{GasUsed: ctx.BlockGasMeter().GasConsumed()}
return gInfo, nil, sdkerrors.Wrap(sdkerrors.ErrOutOfGas, "no block gas left to run tx")
}
var startingGas uint64
@ -534,20 +538,28 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk
defer func() {
if r := recover(); r != nil {
switch rType := r.(type) {
// TODO: Use ErrOutOfGas instead of ErrorOutOfGas which would allow us
// to keep the stracktrace.
case sdk.ErrorOutOfGas:
log := fmt.Sprintf(
"out of gas in location: %v; gasWanted: %d, gasUsed: %d",
rType.Descriptor, gasWanted, ctx.GasMeter().GasConsumed(),
err = sdkerrors.Wrap(
sdkerrors.ErrOutOfGas, fmt.Sprintf(
"out of gas in location: %v; gasWanted: %d, gasUsed: %d",
rType.Descriptor, gasWanted, ctx.GasMeter().GasConsumed(),
),
)
result = sdk.ErrOutOfGas(log).Result()
default:
log := fmt.Sprintf("recovered: %v\nstack:\n%v", r, string(debug.Stack()))
result = sdk.ErrInternal(log).Result()
err = sdkerrors.Wrap(
sdkerrors.ErrPanic, fmt.Sprintf(
"recovered: %v\nstack:\n%v", r, string(debug.Stack()),
),
)
}
result = nil
}
result.GasWanted = gasWanted
result.GasUsed = ctx.GasMeter().GasConsumed()
gInfo = sdk.GasInfo{GasWanted: gasWanted, GasUsed: ctx.GasMeter().GasConsumed()}
}()
// If BlockGasMeter() panics it will be caught by the above recover and will
@ -558,8 +570,7 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk
defer func() {
if mode == runTxModeDeliver {
ctx.BlockGasMeter().ConsumeGas(
ctx.GasMeter().GasConsumedToLimit(),
"block gas meter",
ctx.GasMeter().GasConsumedToLimit(), "block gas meter",
)
if ctx.BlockGasMeter().GasConsumed() < startingGas {
@ -568,20 +579,21 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk
}
}()
var msgs = tx.GetMsgs()
msgs := tx.GetMsgs()
if err := validateBasicTxMsgs(msgs); err != nil {
return err.Result()
gInfo = sdk.GasInfo{GasUsed: ctx.BlockGasMeter().GasConsumed()}
return gInfo, nil, err
}
if app.anteHandler != nil {
var anteCtx sdk.Context
var msCache sdk.CacheMultiStore
// Cache wrap context before anteHandler call in case it aborts.
// Cache wrap context before AnteHandler call in case it aborts.
// This is required for both CheckTx and DeliverTx.
// Ref: https://github.com/cosmos/cosmos-sdk/issues/2772
//
// NOTE: Alternatively, we could require that anteHandler ensures that
// 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)
@ -589,11 +601,11 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk
newCtx, err := app.anteHandler(anteCtx, tx, mode == runTxModeSimulate)
if !newCtx.IsZero() {
// At this point, newCtx.MultiStore() is cache-wrapped, or something else
// replaced by the ante handler. We want the original multistore, not one
// which was cache-wrapped for the ante handler.
// replaced by the AnteHandler. We want the original multistore, not one
// which was cache-wrapped for the AnteHandler.
//
// Also, in the case of the tx aborting, we need to track gas consumed via
// the instantiated gas meter in the ante handler, so we update the context
// the instantiated gas meter in the AnteHandler, so we update the context
// prior to returning.
ctx = newCtx.WithMultiStore(ms)
}
@ -602,10 +614,7 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk
gasWanted = ctx.GasMeter().Limit()
if err != nil {
res := sdk.ResultFromError(err)
res.GasWanted = gasWanted
res.GasUsed = ctx.GasMeter().GasConsumed()
return res
return gInfo, nil, err
}
msCache.Write()
@ -615,83 +624,63 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk
// MultiStore in case message processing fails. At this point, the MultiStore
// is doubly cached-wrapped.
runMsgCtx, msCache := app.cacheTxContext(ctx, txBytes)
result = app.runMsgs(runMsgCtx, msgs, mode)
result.GasWanted = gasWanted
// Safety check: don't write the cache state unless we're in DeliverTx.
if mode != runTxModeDeliver {
return result
}
// only update state if all messages pass
if result.IsOK() {
// Attempt to execute all messages and only update state if all messages pass
// and we're in DeliverTx. Note, runMsgs will never return a reference to a
// Result if any single message fails or does not have a registered Handler.
result, err = app.runMsgs(runMsgCtx, msgs, mode)
if err == nil && mode == runTxModeDeliver {
msCache.Write()
}
return result
return gInfo, result, err
}
// runMsgs iterates through all the messages and executes them.
func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (result sdk.Result) {
// runMsgs iterates through a list of messages and executes them with the provided
// Context and execution mode. Messages will only be executed during simulation
// and DeliverTx. An error is returned if any single message fails or if a
// Handler does not exist for a given message route. Otherwise, a reference to a
// Result is returned. The caller must not commit state if an error is returned.
func (app *BaseApp) runMsgs(ctx sdk.Context, msgs []sdk.Msg, mode runTxMode) (*sdk.Result, error) {
msgLogs := make(sdk.ABCIMessageLogs, 0, len(msgs))
data := make([]byte, 0, len(msgs))
var (
code sdk.CodeType
codespace sdk.CodespaceType
)
events := sdk.EmptyEvents()
// NOTE: GasWanted is determined by ante handler and GasUsed by the GasMeter.
// NOTE: GasWanted is determined by the AnteHandler and GasUsed by the GasMeter.
for i, msg := range msgs {
// match message route
msgRoute := msg.Route()
handler := app.router.Route(msgRoute)
if handler == nil {
return sdk.ErrUnknownRequest("unrecognized message type: " + msgRoute).Result()
}
var msgResult sdk.Result
// skip actual execution for CheckTx and ReCheckTx mode
if mode != runTxModeCheck && mode != runTxModeReCheck {
msgResult = handler(ctx, msg)
}
// Each message result's Data must be length prefixed in order to separate
// each result.
data = append(data, msgResult.Data...)
msgEvents := msgResult.Events
// append events from the message's execution and a message action event
msgEvents = msgEvents.AppendEvent(
sdk.NewEvent(sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyAction, msg.Type())),
)
events = events.AppendEvents(msgEvents)
// stop execution and return on first failed message
if !msgResult.IsOK() {
msgLogs = append(msgLogs, sdk.NewABCIMessageLog(uint16(i), false, msgResult.Log, msgEvents))
code = msgResult.Code
codespace = msgResult.Codespace
// skip actual execution for (Re)CheckTx mode
if mode == runTxModeCheck || mode == runTxModeReCheck {
break
}
msgLogs = append(msgLogs, sdk.NewABCIMessageLog(uint16(i), true, msgResult.Log, msgEvents))
msgRoute := msg.Route()
handler := app.router.Route(msgRoute)
if handler == nil {
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized message route: %s; message index: %d", msgRoute, i)
}
msgResult, err := handler(ctx, msg)
if err != nil {
return nil, sdkerrors.Wrapf(err, "failed to execute message; message index: %d", i)
}
msgEvents := sdk.Events{
sdk.NewEvent(sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyAction, msg.Type())),
}
msgEvents = msgEvents.AppendEvents(msgResult.Events)
// append message events, data and logs
//
// Note: Each message result's data must be length-prefixed in order to
// separate each result.
events = events.AppendEvents(msgEvents)
data = append(data, msgResult.Data...)
msgLogs = append(msgLogs, sdk.NewABCIMessageLog(uint16(i), msgResult.Log, msgEvents))
}
result = sdk.Result{
Code: code,
Codespace: codespace,
Data: data,
Log: strings.TrimSpace(msgLogs.String()),
GasUsed: ctx.GasMeter().GasConsumed(),
Events: events,
}
return result
return &sdk.Result{
Data: data,
Log: strings.TrimSpace(msgLogs.String()),
Events: events,
}, nil
}

View File

@ -514,8 +514,8 @@ func (tx *txTest) setFailOnHandler(fail bool) {
}
// Implements Tx
func (tx txTest) GetMsgs() []sdk.Msg { return tx.Msgs }
func (tx txTest) ValidateBasic() sdk.Error { return nil }
func (tx txTest) GetMsgs() []sdk.Msg { return tx.Msgs }
func (tx txTest) ValidateBasic() error { return nil }
const (
routeMsgCounter = "msgCounter"
@ -534,19 +534,20 @@ func (msg msgCounter) Route() string { return routeMsgCounter }
func (msg msgCounter) Type() string { return "counter1" }
func (msg msgCounter) GetSignBytes() []byte { return nil }
func (msg msgCounter) GetSigners() []sdk.AccAddress { return nil }
func (msg msgCounter) ValidateBasic() sdk.Error {
func (msg msgCounter) ValidateBasic() error {
if msg.Counter >= 0 {
return nil
}
return sdk.ErrInvalidSequence("counter should be a non-negative integer.")
return sdkerrors.Wrap(sdkerrors.ErrInvalidSequence, "counter should be a non-negative integer")
}
func newTxCounter(txInt int64, msgInts ...int64) *txTest {
msgs := make([]sdk.Msg, 0, len(msgInts))
for _, msgInt := range msgInts {
msgs = append(msgs, msgCounter{msgInt, false})
func newTxCounter(counter int64, msgCounters ...int64) *txTest {
msgs := make([]sdk.Msg, 0, len(msgCounters))
for _, c := range msgCounters {
msgs = append(msgs, msgCounter{c, false})
}
return &txTest{msgs, txInt, false}
return &txTest{msgs, counter, false}
}
// a msg we dont know how to route
@ -573,24 +574,26 @@ func (msg msgCounter2) Route() string { return routeMsgCounter2 }
func (msg msgCounter2) Type() string { return "counter2" }
func (msg msgCounter2) GetSignBytes() []byte { return nil }
func (msg msgCounter2) GetSigners() []sdk.AccAddress { return nil }
func (msg msgCounter2) ValidateBasic() sdk.Error {
func (msg msgCounter2) ValidateBasic() error {
if msg.Counter >= 0 {
return nil
}
return sdk.ErrInvalidSequence("counter should be a non-negative integer.")
return sdkerrors.Wrap(sdkerrors.ErrInvalidSequence, "counter should be a non-negative integer")
}
// amino decode
func testTxDecoder(cdc *codec.Codec) sdk.TxDecoder {
return func(txBytes []byte) (sdk.Tx, sdk.Error) {
return func(txBytes []byte) (sdk.Tx, error) {
var tx txTest
if len(txBytes) == 0 {
return nil, sdk.ErrTxDecode("txBytes are empty")
return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "tx bytes are empty")
}
err := cdc.UnmarshalBinaryLengthPrefixed(txBytes, &tx)
if err != nil {
return nil, sdk.ErrTxDecode("").TraceSDK(err.Error())
return nil, sdkerrors.ErrTxDecode
}
return tx, nil
}
}
@ -604,25 +607,28 @@ func anteHandlerTxTest(t *testing.T, capKey sdk.StoreKey, storeKey []byte) sdk.A
return newCtx, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "ante handler failure")
}
res := incrementingCounter(t, store, storeKey, txTest.Counter)
if !res.IsOK() {
err = sdkerrors.ABCIError(string(res.Codespace), uint32(res.Code), res.Log)
_, err = incrementingCounter(t, store, storeKey, txTest.Counter)
if err != nil {
return newCtx, err
}
return
return newCtx, nil
}
}
func handlerMsgCounter(t *testing.T, capKey sdk.StoreKey, deliverKey []byte) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
store := ctx.KVStore(capKey)
var msgCount int64
switch m := msg.(type) {
case *msgCounter:
if m.FailOnHandler {
return sdk.ErrInternal("message handler failure").Result()
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "message handler failure")
}
msgCount = m.Counter
case *msgCounter2:
msgCount = m.Counter
}
@ -651,11 +657,11 @@ func setIntOnStore(store sdk.KVStore, key []byte, i int64) {
// check counter matches what's in store.
// increment and store
func incrementingCounter(t *testing.T, store sdk.KVStore, counterKey []byte, counter int64) (res sdk.Result) {
func incrementingCounter(t *testing.T, store sdk.KVStore, counterKey []byte, counter int64) (*sdk.Result, error) {
storedCounter := getIntFromStore(store, counterKey)
require.Equal(t, storedCounter, counter)
setIntOnStore(store, counterKey, counter+1)
return
return &sdk.Result{}, nil
}
//---------------------------------------------------------------------
@ -675,7 +681,9 @@ func TestCheckTx(t *testing.T) {
anteOpt := func(bapp *BaseApp) { bapp.SetAnteHandler(anteHandlerTxTest(t, capKey1, counterKey)) }
routerOpt := func(bapp *BaseApp) {
// TODO: can remove this once CheckTx doesnt process msgs.
bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) sdk.Result { return sdk.Result{} })
bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
return &sdk.Result{}, nil
})
}
app := setupBaseApp(t, anteOpt, routerOpt)
@ -847,9 +855,9 @@ func TestSimulateTx(t *testing.T) {
}
routerOpt := func(bapp *BaseApp) {
bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
ctx.GasMeter().ConsumeGas(gasConsumed, "test")
return sdk.Result{GasUsed: ctx.GasMeter().GasConsumed()}
return &sdk.Result{}, nil
})
}
@ -872,14 +880,16 @@ func TestSimulateTx(t *testing.T) {
require.Nil(t, err)
// simulate a message, check gas reported
result := app.Simulate(txBytes, tx)
require.True(t, result.IsOK(), result.Log)
require.Equal(t, gasConsumed, result.GasUsed)
gInfo, result, err := app.Simulate(txBytes, tx)
require.NoError(t, err)
require.NotNil(t, result)
require.Equal(t, gasConsumed, gInfo.GasUsed)
// simulate again, same result
result = app.Simulate(txBytes, tx)
require.True(t, result.IsOK(), result.Log)
require.Equal(t, gasConsumed, result.GasUsed)
gInfo, result, err = app.Simulate(txBytes, tx)
require.NoError(t, err)
require.NotNil(t, result)
require.Equal(t, gasConsumed, gInfo.GasUsed)
// simulate by calling Query with encoded tx
query := abci.RequestQuery{
@ -889,11 +899,10 @@ func TestSimulateTx(t *testing.T) {
queryResult := app.Query(query)
require.True(t, queryResult.IsOK(), queryResult.Log)
var res sdk.Result
codec.Cdc.MustUnmarshalBinaryLengthPrefixed(queryResult.Value, &res)
require.Nil(t, err, "Result unmarshalling failed")
require.True(t, res.IsOK(), res.Log)
require.Equal(t, gasConsumed, res.GasUsed, res.Log)
var res uint64
err = codec.Cdc.UnmarshalBinaryLengthPrefixed(queryResult.Value, &res)
require.NoError(t, err)
require.Equal(t, gasConsumed, res)
app.EndBlock(abci.RequestEndBlock{})
app.Commit()
}
@ -906,7 +915,9 @@ func TestRunInvalidTransaction(t *testing.T) {
})
}
routerOpt := func(bapp *BaseApp) {
bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (res sdk.Result) { return })
bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
return &sdk.Result{}, nil
})
}
app := setupBaseApp(t, anteOpt, routerOpt)
@ -914,15 +925,19 @@ func TestRunInvalidTransaction(t *testing.T) {
header := abci.Header{Height: 1}
app.BeginBlock(abci.RequestBeginBlock{Header: header})
// Transaction with no messages
// transaction with no messages
{
emptyTx := &txTest{}
err := app.Deliver(emptyTx)
require.EqualValues(t, sdk.CodeUnknownRequest, err.Code)
require.EqualValues(t, sdk.CodespaceRoot, err.Codespace)
_, result, err := app.Deliver(emptyTx)
require.Error(t, err)
require.Nil(t, result)
space, code, _ := sdkerrors.ABCIInfo(err, false)
require.EqualValues(t, sdkerrors.ErrInvalidRequest.Codespace(), space, err)
require.EqualValues(t, sdkerrors.ErrInvalidRequest.ABCICode(), code, err)
}
// Transaction where ValidateBasic fails
// transaction where ValidateBasic fails
{
testCases := []struct {
tx *txTest
@ -940,27 +955,39 @@ func TestRunInvalidTransaction(t *testing.T) {
for _, testCase := range testCases {
tx := testCase.tx
res := app.Deliver(tx)
_, result, err := app.Deliver(tx)
if testCase.fail {
require.EqualValues(t, sdk.CodeInvalidSequence, res.Code)
require.EqualValues(t, sdk.CodespaceRoot, res.Codespace)
require.Error(t, err)
space, code, _ := sdkerrors.ABCIInfo(err, false)
require.EqualValues(t, sdkerrors.ErrInvalidSequence.Codespace(), space, err)
require.EqualValues(t, sdkerrors.ErrInvalidSequence.ABCICode(), code, err)
} else {
require.True(t, res.IsOK(), fmt.Sprintf("%v", res))
require.NotNil(t, result)
}
}
}
// Transaction with no known route
// transaction with no known route
{
unknownRouteTx := txTest{[]sdk.Msg{msgNoRoute{}}, 0, false}
err := app.Deliver(unknownRouteTx)
require.EqualValues(t, sdk.CodeUnknownRequest, err.Code)
require.EqualValues(t, sdk.CodespaceRoot, err.Codespace)
_, result, err := app.Deliver(unknownRouteTx)
require.Error(t, err)
require.Nil(t, result)
space, code, _ := sdkerrors.ABCIInfo(err, false)
require.EqualValues(t, sdkerrors.ErrUnknownRequest.Codespace(), space, err)
require.EqualValues(t, sdkerrors.ErrUnknownRequest.ABCICode(), code, err)
unknownRouteTx = txTest{[]sdk.Msg{msgCounter{}, msgNoRoute{}}, 0, false}
err = app.Deliver(unknownRouteTx)
require.EqualValues(t, sdk.CodeUnknownRequest, err.Code)
require.EqualValues(t, sdk.CodespaceRoot, err.Codespace)
_, result, err = app.Deliver(unknownRouteTx)
require.Error(t, err)
require.Nil(t, result)
space, code, _ = sdkerrors.ABCIInfo(err, false)
require.EqualValues(t, sdkerrors.ErrUnknownRequest.Codespace(), space, err)
require.EqualValues(t, sdkerrors.ErrUnknownRequest.ABCICode(), code, err)
}
// Transaction with an unregistered message
@ -975,9 +1002,10 @@ func TestRunInvalidTransaction(t *testing.T) {
txBytes, err := newCdc.MarshalBinaryLengthPrefixed(tx)
require.NoError(t, err)
res := app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes})
require.EqualValues(t, sdk.CodeTxDecode, res.Code)
require.EqualValues(t, sdk.CodespaceRoot, res.Codespace)
require.EqualValues(t, sdkerrors.ErrTxDecode.ABCICode(), res.Code)
require.EqualValues(t, sdkerrors.ErrTxDecode.Codespace(), res.Codespace)
}
}
@ -996,8 +1024,7 @@ func TestTxGasLimits(t *testing.T) {
if r := recover(); r != nil {
switch rType := r.(type) {
case sdk.ErrorOutOfGas:
log := fmt.Sprintf("out of gas in location: %v", rType.Descriptor)
err = sdkerrors.Wrap(sdkerrors.ErrOutOfGas, log)
err = sdkerrors.Wrapf(sdkerrors.ErrOutOfGas, "out of gas in location: %v", rType.Descriptor)
default:
panic(r)
}
@ -1007,16 +1034,16 @@ func TestTxGasLimits(t *testing.T) {
count := tx.(*txTest).Counter
newCtx.GasMeter().ConsumeGas(uint64(count), "counter-ante")
return
return newCtx, nil
})
}
routerOpt := func(bapp *BaseApp) {
bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
count := msg.(msgCounter).Counter
ctx.GasMeter().ConsumeGas(uint64(count), "counter-handler")
return sdk.Result{}
return &sdk.Result{}, nil
})
}
@ -1051,17 +1078,21 @@ func TestTxGasLimits(t *testing.T) {
for i, tc := range testCases {
tx := tc.tx
res := app.Deliver(tx)
gInfo, result, err := app.Deliver(tx)
// check gas used and wanted
require.Equal(t, tc.gasUsed, res.GasUsed, fmt.Sprintf("%d: %v, %v", i, tc, res))
require.Equal(t, tc.gasUsed, gInfo.GasUsed, fmt.Sprintf("tc #%d; gas: %v, result: %v, err: %s", i, gInfo, result, err))
// check for out of gas
if !tc.fail {
require.True(t, res.IsOK(), fmt.Sprintf("%d: %v, %v", i, tc, res))
require.NotNil(t, result, fmt.Sprintf("%d: %v, %v", i, tc, err))
} else {
require.Equal(t, sdk.CodeOutOfGas, res.Code, fmt.Sprintf("%d: %v, %v", i, tc, res))
require.Equal(t, sdk.CodespaceRoot, res.Codespace)
require.Error(t, err)
require.Nil(t, result)
space, code, _ := sdkerrors.ABCIInfo(err, false)
require.EqualValues(t, sdkerrors.ErrOutOfGas.Codespace(), space, err)
require.EqualValues(t, sdkerrors.ErrOutOfGas.ABCICode(), code, err)
}
}
}
@ -1093,10 +1124,10 @@ func TestMaxBlockGasLimits(t *testing.T) {
}
routerOpt := func(bapp *BaseApp) {
bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
count := msg.(msgCounter).Counter
ctx.GasMeter().ConsumeGas(uint64(count), "counter-handler")
return sdk.Result{}
return &sdk.Result{}, nil
})
}
@ -1137,23 +1168,29 @@ func TestMaxBlockGasLimits(t *testing.T) {
// execute the transaction multiple times
for j := 0; j < tc.numDelivers; j++ {
res := app.Deliver(tx)
_, result, err := app.Deliver(tx)
ctx := app.getState(runTxModeDeliver).ctx
blockGasUsed := ctx.BlockGasMeter().GasConsumed()
// check for failed transactions
if tc.fail && (j+1) > tc.failAfterDeliver {
require.Equal(t, res.Code, sdk.CodeOutOfGas, fmt.Sprintf("%d: %v, %v", i, tc, res))
require.Equal(t, res.Codespace, sdk.CodespaceRoot, fmt.Sprintf("%d: %v, %v", i, tc, res))
require.Error(t, err, fmt.Sprintf("tc #%d; result: %v, err: %s", i, result, err))
require.Nil(t, result, fmt.Sprintf("tc #%d; result: %v, err: %s", i, result, err))
space, code, _ := sdkerrors.ABCIInfo(err, false)
require.EqualValues(t, sdkerrors.ErrOutOfGas.Codespace(), space, err)
require.EqualValues(t, sdkerrors.ErrOutOfGas.ABCICode(), code, err)
require.True(t, ctx.BlockGasMeter().IsOutOfGas())
} else {
// check gas used and wanted
blockGasUsed := ctx.BlockGasMeter().GasConsumed()
expBlockGasUsed := tc.gasUsedPerDeliver * uint64(j+1)
require.Equal(t, expBlockGasUsed, blockGasUsed,
fmt.Sprintf("%d,%d: %v, %v, %v, %v", i, j, tc, expBlockGasUsed, blockGasUsed, res))
require.Equal(
t, expBlockGasUsed, blockGasUsed,
fmt.Sprintf("%d,%d: %v, %v, %v, %v", i, j, tc, expBlockGasUsed, blockGasUsed, result),
)
require.True(t, res.IsOK(), fmt.Sprintf("%d,%d: %v, %v", i, j, tc, res))
require.NotNil(t, result, fmt.Sprintf("tc #%d; currDeliver: %d, result: %v, err: %s", i, j, result, err))
require.False(t, ctx.BlockGasMeter().IsPastLimit())
}
}
@ -1260,10 +1297,10 @@ func TestGasConsumptionBadTx(t *testing.T) {
}
routerOpt := func(bapp *BaseApp) {
bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
count := msg.(msgCounter).Counter
ctx.GasMeter().ConsumeGas(uint64(count), "counter-handler")
return sdk.Result{}
return &sdk.Result{}, nil
})
}
@ -1313,10 +1350,10 @@ func TestQuery(t *testing.T) {
}
routerOpt := func(bapp *BaseApp) {
bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
bapp.Router().AddRoute(routeMsgCounter, func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
store := ctx.KVStore(capKey1)
store.Set(key, value)
return sdk.Result{}
return &sdk.Result{}, nil
})
}
@ -1338,8 +1375,9 @@ func TestQuery(t *testing.T) {
require.Equal(t, 0, len(res.Value))
// query is still empty after a CheckTx
resTx := app.Check(tx)
require.True(t, resTx.IsOK(), fmt.Sprintf("%v", resTx))
_, resTx, err := app.Check(tx)
require.NoError(t, err)
require.NotNil(t, resTx)
res = app.Query(query)
require.Equal(t, 0, len(res.Value))
@ -1347,8 +1385,9 @@ func TestQuery(t *testing.T) {
header := abci.Header{Height: app.LastBlockHeight() + 1}
app.BeginBlock(abci.RequestBeginBlock{Header: header})
resTx = app.Deliver(tx)
require.True(t, resTx.IsOK(), fmt.Sprintf("%v", resTx))
_, resTx, err = app.Deliver(tx)
require.NoError(t, err)
require.NotNil(t, resTx)
res = app.Query(query)
require.Equal(t, 0, len(res.Value))

View File

@ -10,15 +10,15 @@ import (
var isAlphaNumeric = regexp.MustCompile(`^[a-zA-Z0-9]+$`).MatchString
func (app *BaseApp) Check(tx sdk.Tx) (result sdk.Result) {
func (app *BaseApp) Check(tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) {
return app.runTx(runTxModeCheck, nil, tx)
}
func (app *BaseApp) Simulate(txBytes []byte, tx sdk.Tx) (result sdk.Result) {
func (app *BaseApp) Simulate(txBytes []byte, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) {
return app.runTx(runTxModeSimulate, txBytes, tx)
}
func (app *BaseApp) Deliver(tx sdk.Tx) (result sdk.Result) {
func (app *BaseApp) Deliver(tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) {
return app.runTx(runTxModeDeliver, nil, tx)
}

View File

@ -10,7 +10,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
var testQuerier = func(_ sdk.Context, _ []string, _ abci.RequestQuery) (res []byte, err sdk.Error) {
var testQuerier = func(_ sdk.Context, _ []string, _ abci.RequestQuery) ([]byte, error) {
return nil, nil
}

View File

@ -8,8 +8,8 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
var testHandler = func(_ sdk.Context, _ sdk.Msg) sdk.Result {
return sdk.Result{}
var testHandler = func(_ sdk.Context, _ sdk.Msg) (*sdk.Result, error) {
return &sdk.Result{}, nil
}
func TestRouter(t *testing.T) {

View File

@ -9,6 +9,7 @@ import (
"github.com/cosmos/cosmos-sdk/client/flags"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
// BroadcastTx broadcasts a transactions either synchronously or asynchronously
@ -52,19 +53,19 @@ func CheckTendermintError(err error, txBytes []byte) *sdk.TxResponse {
switch {
case strings.Contains(errStr, strings.ToLower(mempool.ErrTxInCache.Error())):
return &sdk.TxResponse{
Code: uint32(sdk.CodeTxInMempoolCache),
Code: sdkerrors.ErrTxInMempoolCache.ABCICode(),
TxHash: txHash,
}
case strings.Contains(errStr, "mempool is full"):
return &sdk.TxResponse{
Code: uint32(sdk.CodeMempoolIsFull),
Code: sdkerrors.ErrMempoolIsFull.ABCICode(),
TxHash: txHash,
}
case strings.Contains(errStr, "tx too large"):
return &sdk.TxResponse{
Code: uint32(sdk.CodeTxTooLarge),
Code: sdkerrors.ErrTxTooLarge.ABCICode(),
TxHash: txHash,
}

View File

@ -4,16 +4,15 @@ import (
"fmt"
"testing"
"github.com/tendermint/tendermint/crypto/tmhash"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto/tmhash"
"github.com/tendermint/tendermint/mempool"
"github.com/tendermint/tendermint/rpc/client/mock"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
tmtypes "github.com/tendermint/tendermint/types"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
type MockClient struct {
@ -43,9 +42,9 @@ func CreateContextWithErrorAndMode(err error, mode string) CLIContext {
// Test the correct code is returned when
func TestBroadcastError(t *testing.T) {
errors := map[error]uint32{
mempool.ErrTxInCache: uint32(types.CodeTxInMempoolCache),
mempool.ErrTxTooLarge{}: uint32(types.CodeTxTooLarge),
mempool.ErrMempoolIsFull{}: uint32(types.CodeMempoolIsFull),
mempool.ErrTxInCache: sdkerrors.ErrTxInMempoolCache.ABCICode(),
mempool.ErrTxTooLarge{}: sdkerrors.ErrTxTooLarge.ABCICode(),
mempool.ErrMempoolIsFull{}: sdkerrors.ErrMempoolIsFull.ABCICode(),
}
modes := []string{

View File

@ -204,7 +204,7 @@ type PacketDataI interface {
GetCommitment() []byte // Commitment form that will be stored in the state.
GetTimeoutHeight() uint64
ValidateBasic() sdk.Error
ValidateBasic() error
Type() string
}
```

View File

@ -25,19 +25,24 @@ Let us break it down:
## Implementation of a module `handler`s
Module `handler`s are typically implemented in a `./handler.go` file inside the module's folder. The [module manager](./module-manager.md) is used to add the module's `handler`s to the [application's `router`](../core/baseapp.md#message-routing) via the `NewHandler()` method. Typically, the manager's `NewHandler()` method simply calls a `NewHandler()` method defined in `handler.go`, which looks like the following:
Module `handler`s are typically implemented in a `./handler.go` file inside the module's folder. The
[module manager](./module-manager.md) is used to add the module's `handler`s to the
[application's `router`](../core/baseapp.md#message-routing) via the `NewHandler()` method. Typically,
the manager's `NewHandler()` method simply calls a `NewHandler()` method defined in `handler.go`,
which looks like the following:
```go
func NewHandler(keeper Keeper) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
switch msg := msg.(type) {
case MsgType1:
return handleMsgType1(ctx, keeper, msg)
case MsgType2:
return handleMsgType2(ctx, keeper, msg)
default:
errMsg := fmt.Sprintf("Unrecognized nameservice Msg type: %v", msg.Type())
return sdk.ErrUnknownRequest(errMsg).Result()
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", ModuleName, msg)
}
}
}

View File

@ -29,14 +29,16 @@ Module `querier`s are typically implemented in a `./internal/keeper/querier.go`
```go
func NewQuerier(keeper Keeper) sdk.Querier {
return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) {
return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) {
switch path[0] {
case QueryType1:
return queryType1(ctx, path[1:], req, keeper)
case QueryType2:
return queryType2(ctx, path[1:], req, keeper)
default:
return nil, sdk.ErrUnknownRequest("unknown nameservice query endpoint")
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown %s query endpoint: %s", types.ModuleName, path[0])
}
}
}

View File

@ -2,6 +2,7 @@ package mock
import (
"encoding/json"
"errors"
"fmt"
"path/filepath"
@ -49,10 +50,10 @@ func NewApp(rootDir string, logger log.Logger) (abci.Application, error) {
// KVStoreHandler is a simple handler that takes kvstoreTx and writes
// them to the db
func KVStoreHandler(storeKey sdk.StoreKey) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
dTx, ok := msg.(kvstoreTx)
if !ok {
panic("KVStoreHandler should only receive kvstoreTx")
return nil, errors.New("KVStoreHandler should only receive kvstoreTx")
}
// tx is already unmarshalled
@ -62,10 +63,9 @@ func KVStoreHandler(storeKey sdk.StoreKey) sdk.Handler {
store := ctx.KVStore(storeKey)
store.Set(key, value)
return sdk.Result{
Code: 0,
Log: fmt.Sprintf("set %s=%s", key, value),
}
return &sdk.Result{
Log: fmt.Sprintf("set %s=%s", key, value),
}, nil
}
}

View File

@ -6,6 +6,7 @@ import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
// An sdk.Tx which is its own sdk.Msg.
@ -47,7 +48,7 @@ func (tx kvstoreTx) GetSignBytes() []byte {
}
// Should the app be calling this? Or only handlers?
func (tx kvstoreTx) ValidateBasic() sdk.Error {
func (tx kvstoreTx) ValidateBasic() error {
return nil
}
@ -57,7 +58,7 @@ func (tx kvstoreTx) GetSigners() []sdk.AccAddress {
// takes raw transaction bytes and decodes them into an sdk.Tx. An sdk.Tx has
// all the signatures and can be used to authenticate.
func decodeTx(txBytes []byte) (sdk.Tx, sdk.Error) {
func decodeTx(txBytes []byte) (sdk.Tx, error) {
var tx sdk.Tx
split := bytes.Split(txBytes, []byte("="))
@ -68,7 +69,7 @@ func decodeTx(txBytes []byte) (sdk.Tx, sdk.Error) {
k, v := split[0], split[1]
tx = kvstoreTx{k, v, txBytes}
} else {
return nil, sdk.ErrTxDecode("too many =")
return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "too many '='")
}
return tx, nil

View File

@ -158,7 +158,7 @@ func NewSimApp(
}
// init params keeper and subspaces
app.ParamsKeeper = params.NewKeeper(app.cdc, keys[params.StoreKey], tkeys[params.TStoreKey], params.DefaultCodespace)
app.ParamsKeeper = params.NewKeeper(app.cdc, keys[params.StoreKey], tkeys[params.TStoreKey])
app.subspaces[auth.ModuleName] = app.ParamsKeeper.Subspace(auth.DefaultParamspace)
app.subspaces[bank.ModuleName] = app.ParamsKeeper.Subspace(bank.DefaultParamspace)
app.subspaces[staking.ModuleName] = app.ParamsKeeper.Subspace(staking.DefaultParamspace)
@ -174,25 +174,24 @@ func NewSimApp(
app.cdc, keys[auth.StoreKey], app.subspaces[auth.ModuleName], auth.ProtoBaseAccount,
)
app.BankKeeper = bank.NewBaseKeeper(
app.AccountKeeper, app.subspaces[bank.ModuleName], bank.DefaultCodespace,
app.BlacklistedAccAddrs(),
app.AccountKeeper, app.subspaces[bank.ModuleName], app.BlacklistedAccAddrs(),
)
app.SupplyKeeper = supply.NewKeeper(
app.cdc, keys[supply.StoreKey], app.AccountKeeper, app.BankKeeper, maccPerms,
)
stakingKeeper := staking.NewKeeper(
app.cdc, keys[staking.StoreKey], app.SupplyKeeper, app.subspaces[staking.ModuleName],
staking.DefaultCodespace)
)
app.MintKeeper = mint.NewKeeper(
app.cdc, keys[mint.StoreKey], app.subspaces[mint.ModuleName], &stakingKeeper,
app.SupplyKeeper, auth.FeeCollectorName,
)
app.DistrKeeper = distr.NewKeeper(
app.cdc, keys[distr.StoreKey], app.subspaces[distr.ModuleName], &stakingKeeper,
app.SupplyKeeper, distr.DefaultCodespace, auth.FeeCollectorName, app.ModuleAccountAddrs(),
app.SupplyKeeper, auth.FeeCollectorName, app.ModuleAccountAddrs(),
)
app.SlashingKeeper = slashing.NewKeeper(
app.cdc, keys[slashing.StoreKey], &stakingKeeper, app.subspaces[slashing.ModuleName], slashing.DefaultCodespace,
app.cdc, keys[slashing.StoreKey], &stakingKeeper, app.subspaces[slashing.ModuleName],
)
app.CrisisKeeper = crisis.NewKeeper(
app.subspaces[crisis.ModuleName], invCheckPeriod, app.SupplyKeeper, auth.FeeCollectorName,
@ -201,8 +200,7 @@ func NewSimApp(
// create evidence keeper with router
evidenceKeeper := evidence.NewKeeper(
app.cdc, keys[evidence.StoreKey], app.subspaces[evidence.ModuleName], evidence.DefaultCodespace,
&app.StakingKeeper, app.SlashingKeeper,
app.cdc, keys[evidence.StoreKey], app.subspaces[evidence.ModuleName], &app.StakingKeeper, app.SlashingKeeper,
)
evidenceRouter := evidence.NewRouter()
// TODO: Register evidence routes.
@ -217,7 +215,7 @@ func NewSimApp(
AddRoute(upgrade.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper))
app.GovKeeper = gov.NewKeeper(
app.cdc, keys[gov.StoreKey], app.subspaces[gov.ModuleName], app.SupplyKeeper,
&stakingKeeper, gov.DefaultCodespace, govRouter,
&stakingKeeper, govRouter,
)
// register the staking hooks

View File

@ -115,7 +115,7 @@ func CheckBalance(t *testing.T, app *SimApp, addr sdk.AccAddress, exp sdk.Coins)
func SignCheckDeliver(
t *testing.T, cdc *codec.Codec, app *bam.BaseApp, header abci.Header, msgs []sdk.Msg,
accNums, seq []uint64, expSimPass, expPass bool, priv ...crypto.PrivKey,
) sdk.Result {
) (sdk.GasInfo, *sdk.Result, error) {
tx := helpers.GenTx(
msgs,
@ -131,28 +131,32 @@ func SignCheckDeliver(
require.Nil(t, err)
// Must simulate now as CheckTx doesn't run Msgs anymore
res := app.Simulate(txBytes, tx)
_, res, err := app.Simulate(txBytes, tx)
if expSimPass {
require.Equal(t, sdk.CodeOK, res.Code, res.Log)
require.NoError(t, err)
require.NotNil(t, res)
} else {
require.NotEqual(t, sdk.CodeOK, res.Code, res.Log)
require.Error(t, err)
require.Nil(t, res)
}
// Simulate a sending a transaction and committing a block
app.BeginBlock(abci.RequestBeginBlock{Header: header})
res = app.Deliver(tx)
gInfo, res, err := app.Deliver(tx)
if expPass {
require.Equal(t, sdk.CodeOK, res.Code, res.Log)
require.NoError(t, err)
require.NotNil(t, res)
} else {
require.NotEqual(t, sdk.CodeOK, res.Code, res.Log)
require.Error(t, err)
require.Nil(t, res)
}
app.EndBlock(abci.RequestEndBlock{})
app.Commit()
return res
return gInfo, res, err
}
// GenSequenceOfTxs generates a set of signed transactions of messages, such

View File

@ -1,26 +0,0 @@
package errors
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
const (
CodeOK = sdk.CodeOK
CodeInternal = sdk.CodeInternal
CodeTxDecode = sdk.CodeTxDecode
CodeUnknownRequest = sdk.CodeUnknownRequest
CodespaceRoot = sdk.CodespaceRoot
)
type Error = sdk.Error
func ErrInternal(msg string) Error {
return sdk.ErrInternal(msg)
}
func ErrTxDecode(msg string) Error {
return sdk.ErrTxDecode(msg)
}
func ErrUnknownRequest(msg string) Error {
return sdk.ErrUnknownRequest(msg)
}

View File

@ -1,14 +1,13 @@
package iavl
import (
"fmt"
"io"
"sync"
"github.com/cosmos/cosmos-sdk/store/cachekv"
serrors "github.com/cosmos/cosmos-sdk/store/errors"
"github.com/cosmos/cosmos-sdk/store/tracekv"
"github.com/cosmos/cosmos-sdk/store/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/pkg/errors"
"github.com/tendermint/iavl"
@ -236,8 +235,7 @@ func getHeight(tree Tree, req abci.RequestQuery) int64 {
// explicitly set the height you want to see
func (st *Store) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
if len(req.Data) == 0 {
msg := "Query cannot be zero length"
return serrors.ErrTxDecode(msg).QueryResult()
return sdkerrors.QueryResult(sdkerrors.Wrap(sdkerrors.ErrTxDecode, "query cannot be zero length"))
}
tree := st.tree
@ -296,8 +294,7 @@ func (st *Store) Query(req abci.RequestQuery) (res abci.ResponseQuery) {
res.Value = cdc.MustMarshalBinaryLengthPrefixed(KVs)
default:
msg := fmt.Sprintf("Unexpected Query path: %v", req.Path)
return serrors.ErrUnknownRequest(msg).QueryResult()
return sdkerrors.QueryResult(sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unexpected query path: %v", req.Path))
}
return res

View File

@ -11,7 +11,6 @@ import (
cmn "github.com/tendermint/tendermint/libs/common"
dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/store/errors"
"github.com/cosmos/cosmos-sdk/store/types"
)
@ -497,7 +496,7 @@ func TestIAVLStoreQuery(t *testing.T) {
// query subspace before anything set
qres := iavlStore.Query(querySub)
require.Equal(t, uint32(errors.CodeOK), qres.Code)
require.Equal(t, uint32(0), qres.Code)
require.Equal(t, valExpSubEmpty, qres.Value)
// set data
@ -506,24 +505,24 @@ func TestIAVLStoreQuery(t *testing.T) {
// set data without commit, doesn't show up
qres = iavlStore.Query(query)
require.Equal(t, uint32(errors.CodeOK), qres.Code)
require.Equal(t, uint32(0), qres.Code)
require.Nil(t, qres.Value)
// commit it, but still don't see on old version
cid = iavlStore.Commit()
qres = iavlStore.Query(query)
require.Equal(t, uint32(errors.CodeOK), qres.Code)
require.Equal(t, uint32(0), qres.Code)
require.Nil(t, qres.Value)
// but yes on the new version
query.Height = cid.Version
qres = iavlStore.Query(query)
require.Equal(t, uint32(errors.CodeOK), qres.Code)
require.Equal(t, uint32(0), qres.Code)
require.Equal(t, v1, qres.Value)
// and for the subspace
qres = iavlStore.Query(querySub)
require.Equal(t, uint32(errors.CodeOK), qres.Code)
require.Equal(t, uint32(0), qres.Code)
require.Equal(t, valExpSub1, qres.Value)
// modify
@ -532,28 +531,28 @@ func TestIAVLStoreQuery(t *testing.T) {
// query will return old values, as height is fixed
qres = iavlStore.Query(query)
require.Equal(t, uint32(errors.CodeOK), qres.Code)
require.Equal(t, uint32(0), qres.Code)
require.Equal(t, v1, qres.Value)
// update to latest in the query and we are happy
query.Height = cid.Version
qres = iavlStore.Query(query)
require.Equal(t, uint32(errors.CodeOK), qres.Code)
require.Equal(t, uint32(0), qres.Code)
require.Equal(t, v3, qres.Value)
query2 := abci.RequestQuery{Path: "/key", Data: k2, Height: cid.Version}
qres = iavlStore.Query(query2)
require.Equal(t, uint32(errors.CodeOK), qres.Code)
require.Equal(t, uint32(0), qres.Code)
require.Equal(t, v2, qres.Value)
// and for the subspace
qres = iavlStore.Query(querySub)
require.Equal(t, uint32(errors.CodeOK), qres.Code)
require.Equal(t, uint32(0), qres.Code)
require.Equal(t, valExpSub2, qres.Value)
// default (height 0) will show latest -1
query0 := abci.RequestQuery{Path: "/key", Data: k1}
qres = iavlStore.Query(query0)
require.Equal(t, uint32(errors.CodeOK), qres.Code)
require.Equal(t, uint32(0), qres.Code)
require.Equal(t, v1, qres.Value)
}

View File

@ -12,11 +12,11 @@ import (
"github.com/cosmos/cosmos-sdk/store/cachemulti"
"github.com/cosmos/cosmos-sdk/store/dbadapter"
"github.com/cosmos/cosmos-sdk/store/errors"
"github.com/cosmos/cosmos-sdk/store/iavl"
"github.com/cosmos/cosmos-sdk/store/tracekv"
"github.com/cosmos/cosmos-sdk/store/transient"
"github.com/cosmos/cosmos-sdk/store/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
const (
@ -408,19 +408,17 @@ func (rs *Store) Query(req abci.RequestQuery) abci.ResponseQuery {
path := req.Path
storeName, subpath, err := parsePath(path)
if err != nil {
return err.QueryResult()
return sdkerrors.QueryResult(err)
}
store := rs.getStoreByName(storeName)
if store == nil {
msg := fmt.Sprintf("no such store: %s", storeName)
return errors.ErrUnknownRequest(msg).QueryResult()
return sdkerrors.QueryResult(sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "no such store: %s", storeName))
}
queryable, ok := store.(types.Queryable)
if !ok {
msg := fmt.Sprintf("store %s (type %T) doesn't support queries", storeName, store)
return errors.ErrUnknownRequest(msg).QueryResult()
return sdkerrors.QueryResult(sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "store %s (type %T) doesn't support queries", storeName, store))
}
// trim the path and make the query
@ -432,12 +430,12 @@ func (rs *Store) Query(req abci.RequestQuery) abci.ResponseQuery {
}
if res.Proof == nil || len(res.Proof.Ops) == 0 {
return errors.ErrInternal("proof is unexpectedly empty; ensure height has not been pruned").QueryResult()
return sdkerrors.QueryResult(sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "proof is unexpectedly empty; ensure height has not been pruned"))
}
commitInfo, errMsg := getCommitInfo(rs.db, res.Height)
if errMsg != nil {
return errors.ErrInternal(errMsg.Error()).QueryResult()
return sdkerrors.QueryResult(err)
}
// Restore origin path and append proof op.
@ -454,10 +452,9 @@ func (rs *Store) Query(req abci.RequestQuery) abci.ResponseQuery {
// parsePath expects a format like /<storeName>[/<subpath>]
// Must start with /, subpath may be empty
// Returns error if it doesn't start with /
func parsePath(path string) (storeName string, subpath string, err errors.Error) {
func parsePath(path string) (storeName string, subpath string, err error) {
if !strings.HasPrefix(path, "/") {
err = errors.ErrUnknownRequest(fmt.Sprintf("invalid path: %s", path))
return
return storeName, subpath, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid path: %s", path)
}
paths := strings.SplitN(path[1:], "/", 2)
@ -467,7 +464,7 @@ func parsePath(path string) (storeName string, subpath string, err errors.Error)
subpath = "/" + paths[1]
}
return
return storeName, subpath, nil
}
//----------------------------------------

View File

@ -8,9 +8,9 @@ import (
"github.com/tendermint/tendermint/crypto/merkle"
dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/store/errors"
"github.com/cosmos/cosmos-sdk/store/iavl"
"github.com/cosmos/cosmos-sdk/store/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
func TestStoreType(t *testing.T) {
@ -324,37 +324,37 @@ func TestMultiStoreQuery(t *testing.T) {
// Test bad path.
query := abci.RequestQuery{Path: "/key", Data: k, Height: ver}
qres := multi.Query(query)
require.EqualValues(t, errors.CodeUnknownRequest, qres.Code)
require.EqualValues(t, errors.CodespaceRoot, qres.Codespace)
require.EqualValues(t, sdkerrors.ErrUnknownRequest.ABCICode(), qres.Code)
require.EqualValues(t, sdkerrors.ErrUnknownRequest.Codespace(), qres.Codespace)
query.Path = "h897fy32890rf63296r92"
qres = multi.Query(query)
require.EqualValues(t, errors.CodeUnknownRequest, qres.Code)
require.EqualValues(t, errors.CodespaceRoot, qres.Codespace)
require.EqualValues(t, sdkerrors.ErrUnknownRequest.ABCICode(), qres.Code)
require.EqualValues(t, sdkerrors.ErrUnknownRequest.Codespace(), qres.Codespace)
// Test invalid store name.
query.Path = "/garbage/key"
qres = multi.Query(query)
require.EqualValues(t, errors.CodeUnknownRequest, qres.Code)
require.EqualValues(t, errors.CodespaceRoot, qres.Codespace)
require.EqualValues(t, sdkerrors.ErrUnknownRequest.ABCICode(), qres.Code)
require.EqualValues(t, sdkerrors.ErrUnknownRequest.Codespace(), qres.Codespace)
// Test valid query with data.
query.Path = "/store1/key"
qres = multi.Query(query)
require.EqualValues(t, errors.CodeOK, qres.Code)
require.EqualValues(t, 0, 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.EqualValues(t, errors.CodeOK, qres.Code)
require.EqualValues(t, 0, qres.Code)
require.Nil(t, qres.Value)
// Test store2 data.
query.Data = k2
qres = multi.Query(query)
require.EqualValues(t, errors.CodeOK, qres.Code)
require.EqualValues(t, 0, qres.Code)
require.Equal(t, v2, qres.Value)
}

View File

@ -2,6 +2,7 @@ package types
import (
"encoding/json"
"errors"
"fmt"
"math/big"
"strconv"
@ -33,6 +34,13 @@ var (
tenInt = big.NewInt(10)
)
// Decimal errors
var (
ErrEmptyDecimalStr = errors.New("decimal string cannot be empty")
ErrInvalidDecimalLength = errors.New("invalid decimal length")
ErrInvalidDecimalStr = errors.New("invalid decimal string")
)
// Set precision multipliers
func init() {
precisionMultipliers = make([]*big.Int, Precision+1)
@ -123,9 +131,9 @@ func NewDecFromIntWithPrec(i Int, prec int64) Dec {
// are provided in the string than the constant Precision.
//
// CONTRACT - This function does not mutate the input str.
func NewDecFromStr(str string) (d Dec, err Error) {
func NewDecFromStr(str string) (Dec, error) {
if len(str) == 0 {
return d, ErrUnknownRequest("decimal string is empty")
return Dec{}, ErrEmptyDecimalStr
}
// first extract any negative symbol
@ -136,7 +144,7 @@ func NewDecFromStr(str string) (d Dec, err Error) {
}
if len(str) == 0 {
return d, ErrUnknownRequest("decimal string is empty")
return Dec{}, ErrEmptyDecimalStr
}
strs := strings.Split(str, ".")
@ -146,17 +154,16 @@ func NewDecFromStr(str string) (d Dec, err Error) {
if len(strs) == 2 { // has a decimal place
lenDecs = len(strs[1])
if lenDecs == 0 || len(combinedStr) == 0 {
return d, ErrUnknownRequest("bad decimal length")
return Dec{}, ErrInvalidDecimalLength
}
combinedStr += strs[1]
} else if len(strs) > 2 {
return d, ErrUnknownRequest("too many periods to be a decimal string")
return Dec{}, ErrInvalidDecimalStr
}
if lenDecs > Precision {
return d, ErrUnknownRequest(
fmt.Sprintf("too much precision, maximum %v, len decimal %v", Precision, lenDecs))
return Dec{}, fmt.Errorf("invalid precision; max: %d, got: %d", Precision, lenDecs)
}
// add some extra zero's to correct to the Precision factor
@ -166,11 +173,12 @@ func NewDecFromStr(str string) (d Dec, err Error) {
combined, ok := new(big.Int).SetString(combinedStr, 10) // base 10
if !ok {
return d, ErrUnknownRequest(fmt.Sprintf("bad string to integer conversion, combinedStr: %v", combinedStr))
return Dec{}, fmt.Errorf("failed to set decimal string: %s", combinedStr)
}
if neg {
combined = new(big.Int).Neg(combined)
}
return Dec{combined}, nil
}

View File

@ -1,361 +0,0 @@
package types
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"github.com/pkg/errors"
abci "github.com/tendermint/tendermint/abci/types"
cmn "github.com/tendermint/tendermint/libs/common"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
// CodeType - ABCI code identifier within codespace
type CodeType uint32
// CodespaceType - codespace identifier
type CodespaceType string
// IsOK - is everything okay?
func (code CodeType) IsOK() bool {
return code == CodeOK
}
// SDK error codes
const (
// Base error codes
CodeOK CodeType = 0
CodeInternal CodeType = 1
CodeTxDecode CodeType = 2
CodeInvalidSequence CodeType = 3
CodeUnauthorized CodeType = 4
CodeInsufficientFunds CodeType = 5
CodeUnknownRequest CodeType = 6
CodeInvalidAddress CodeType = 7
CodeInvalidPubKey CodeType = 8
CodeUnknownAddress CodeType = 9
CodeInsufficientCoins CodeType = 10
CodeInvalidCoins CodeType = 11
CodeOutOfGas CodeType = 12
CodeMemoTooLarge CodeType = 13
CodeInsufficientFee CodeType = 14
CodeTooManySignatures CodeType = 15
CodeGasOverflow CodeType = 16
CodeNoSignatures CodeType = 17
CodeTxInMempoolCache CodeType = 18
CodeMempoolIsFull CodeType = 19
CodeTxTooLarge CodeType = 20
// 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 = ""
CodespaceRoot CodespaceType = "sdk"
)
func unknownCodeMsg(code CodeType) string {
return fmt.Sprintf("unknown code %d", code)
}
// NOTE: Don't stringer this, we'll put better messages in later.
func CodeToDefaultMsg(code CodeType) string {
switch code {
case CodeInternal:
return "internal error"
case CodeTxDecode:
return "tx parse error"
case CodeInvalidSequence:
return "invalid sequence"
case CodeUnauthorized:
return "unauthorized"
case CodeInsufficientFunds:
return "insufficient funds"
case CodeUnknownRequest:
return "unknown request"
case CodeInvalidAddress:
return "invalid address"
case CodeInvalidPubKey:
return "invalid pubkey"
case CodeUnknownAddress:
return "unknown address"
case CodeInsufficientCoins:
return "insufficient coins"
case CodeInvalidCoins:
return "invalid coins"
case CodeOutOfGas:
return "out of gas"
case CodeMemoTooLarge:
return "memo too large"
case CodeInsufficientFee:
return "insufficient fee"
case CodeTooManySignatures:
return "maximum numer of signatures exceeded"
case CodeNoSignatures:
return "no signatures supplied"
default:
return unknownCodeMsg(code)
}
}
//--------------------------------------------------------------------------------
// All errors are created via constructors so as to enable us to hijack them
// and inject stack traces if we really want to.
// nolint
func ErrInternal(msg string) Error {
return newErrorWithRootCodespace(CodeInternal, msg)
}
func ErrTxDecode(msg string) Error {
return newErrorWithRootCodespace(CodeTxDecode, msg)
}
func ErrInvalidSequence(msg string) Error {
return newErrorWithRootCodespace(CodeInvalidSequence, msg)
}
func ErrUnauthorized(msg string) Error {
return newErrorWithRootCodespace(CodeUnauthorized, msg)
}
func ErrInsufficientFunds(msg string) Error {
return newErrorWithRootCodespace(CodeInsufficientFunds, msg)
}
func ErrUnknownRequest(msg string) Error {
return newErrorWithRootCodespace(CodeUnknownRequest, msg)
}
func ErrInvalidAddress(msg string) Error {
return newErrorWithRootCodespace(CodeInvalidAddress, msg)
}
func ErrUnknownAddress(msg string) Error {
return newErrorWithRootCodespace(CodeUnknownAddress, msg)
}
func ErrInvalidPubKey(msg string) Error {
return newErrorWithRootCodespace(CodeInvalidPubKey, msg)
}
func ErrInsufficientCoins(msg string) Error {
return newErrorWithRootCodespace(CodeInsufficientCoins, msg)
}
func ErrInvalidCoins(msg string) Error {
return newErrorWithRootCodespace(CodeInvalidCoins, msg)
}
func ErrOutOfGas(msg string) Error {
return newErrorWithRootCodespace(CodeOutOfGas, msg)
}
func ErrMemoTooLarge(msg string) Error {
return newErrorWithRootCodespace(CodeMemoTooLarge, msg)
}
func ErrInsufficientFee(msg string) Error {
return newErrorWithRootCodespace(CodeInsufficientFee, msg)
}
func ErrTooManySignatures(msg string) Error {
return newErrorWithRootCodespace(CodeTooManySignatures, msg)
}
func ErrNoSignatures(msg string) Error {
return newErrorWithRootCodespace(CodeNoSignatures, msg)
}
func ErrGasOverflow(msg string) Error {
return newErrorWithRootCodespace(CodeGasOverflow, msg)
}
//----------------------------------------
// Error & sdkError
type cmnError = cmn.Error
// sdk Error type
type Error interface {
// Implements cmn.Error
// Error() string
// Stacktrace() cmn.Error
// Trace(offset int, format string, args ...interface{}) cmn.Error
// Data() interface{}
cmnError
// convenience
TraceSDK(format string, args ...interface{}) Error
// set codespace
WithDefaultCodespace(CodespaceType) Error
Code() CodeType
Codespace() CodespaceType
ABCILog() string
Result() Result
QueryResult() abci.ResponseQuery
}
// NewError - create an error.
func NewError(codespace CodespaceType, code CodeType, format string, args ...interface{}) Error {
return newError(codespace, code, format, args...)
}
func newErrorWithRootCodespace(code CodeType, format string, args ...interface{}) *sdkError {
return newError(CodespaceRoot, code, format, args...)
}
func newError(codespace CodespaceType, code CodeType, format string, args ...interface{}) *sdkError {
if format == "" {
format = CodeToDefaultMsg(code)
}
return &sdkError{
codespace: codespace,
code: code,
cmnError: cmn.NewError(format, args...),
}
}
type sdkError struct {
codespace CodespaceType
code CodeType
cmnError
}
// Implements Error.
func (err *sdkError) WithDefaultCodespace(cs CodespaceType) Error {
codespace := err.codespace
if codespace == CodespaceUndefined {
codespace = cs
}
return &sdkError{
codespace: cs,
code: err.code,
cmnError: err.cmnError,
}
}
// Implements ABCIError.
// nolint: errcheck
func (err *sdkError) TraceSDK(format string, args ...interface{}) Error {
err.Trace(1, format, args...)
return err
}
// Implements ABCIError.
func (err *sdkError) Error() string {
return fmt.Sprintf(`ERROR:
Codespace: %s
Code: %d
Message: %#v
`, err.codespace, err.code, err.cmnError.Error())
}
// Implements Error.
func (err *sdkError) Codespace() CodespaceType {
return err.codespace
}
// Implements Error.
func (err *sdkError) Code() CodeType {
return err.code
}
// Implements ABCIError.
func (err *sdkError) ABCILog() string {
errMsg := err.cmnError.Error()
return encodeErrorLog(err.codespace, err.code, errMsg)
}
func encodeErrorLog(codespace CodespaceType, code CodeType, msg string) string {
jsonErr := humanReadableError{
Codespace: codespace,
Code: code,
Message: msg,
}
var buff bytes.Buffer
enc := json.NewEncoder(&buff)
enc.SetEscapeHTML(false)
if err := enc.Encode(jsonErr); err != nil {
panic(errors.Wrap(err, "failed to encode ABCI error log"))
}
return strings.TrimSpace(buff.String())
}
func (err *sdkError) Result() Result {
return Result{
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.Code()),
Codespace: string(err.Codespace()),
Log: err.ABCILog(),
}
}
// ResultFromError will return err.Result() if it implements sdk.Error
// Otherwise, it will use the reflecton from types/error to determine
// the code, codespace, and log.
//
// This is intended to provide a bridge to allow both error types
// to live side-by-side.
func ResultFromError(err error) Result {
if sdk, ok := err.(Error); ok {
return sdk.Result()
}
space, code, log := sdkerrors.ABCIInfo(err, false)
return Result{
Codespace: CodespaceType(space),
Code: CodeType(code),
Log: encodeErrorLog(CodespaceType(space), CodeType(code), log),
}
}
// ConvertError accepts a standard error and attempts to convert it to an sdk.Error.
// If the given error is already an sdk.Error, it'll simply be returned. Otherwise,
// it'll convert it to a types.Error. This is meant to provide a migration path
// away from sdk.Error in favor of types.Error.
func ConvertError(err error) Error {
if err == nil {
return nil
}
if sdkError, ok := err.(Error); ok {
return sdkError
}
space, code, log := sdkerrors.ABCIInfo(err, false)
return NewError(CodespaceType(space), CodeType(code), log)
}
//----------------------------------------
// REST error utilities
// appends a message to the head of the given error
func AppendMsgToErr(msg string, err string) string {
msgIdx := strings.Index(err, "message\":\"")
if msgIdx != -1 {
errMsg := err[msgIdx+len("message\":\"") : len(err)-2]
errMsg = fmt.Sprintf("%s; %s", msg, errMsg)
return fmt.Sprintf("%s%s%s",
err[:msgIdx+len("message\":\"")],
errMsg,
err[len(err)-2:],
)
}
return fmt.Sprintf("%s; %s", msg, err)
}
// returns the index of the message in the ABCI Log
// nolint:deadcode,unused
func mustGetMsgIndex(abciLog string) int {
msgIdx := strings.Index(abciLog, "message\":\"")
if msgIdx == -1 {
panic(fmt.Sprintf("invalid error format: %s", abciLog))
}
return msgIdx + len("message\":\"")
}
// parses the error into an object-like struct for exporting
type humanReadableError struct {
Codespace CodespaceType `json:"codespace"`
Code CodeType `json:"code"`
Message string `json:"message"`
}

View File

@ -4,6 +4,8 @@ import (
"errors"
"fmt"
"reflect"
abci "github.com/tendermint/tendermint/abci/types"
)
const (
@ -40,6 +42,43 @@ func ABCIInfo(err error, debug bool) (codespace string, code uint32, log string)
return abciCodespace(err), abciCode(err), encode(err)
}
// ResponseCheckTx returns an ABCI ResponseCheckTx object with fields filled in
// from the given error and gas values.
func ResponseCheckTx(err error, gw, gu uint64) abci.ResponseCheckTx {
space, code, log := ABCIInfo(err, false)
return abci.ResponseCheckTx{
Codespace: space,
Code: code,
Log: log,
GasWanted: int64(gw),
GasUsed: int64(gu),
}
}
// ResponseDeliverTx returns an ABCI ResponseDeliverTx object with fields filled in
// from the given error and gas values.
func ResponseDeliverTx(err error, gw, gu uint64) abci.ResponseDeliverTx {
space, code, log := ABCIInfo(err, false)
return abci.ResponseDeliverTx{
Codespace: space,
Code: code,
Log: log,
GasWanted: int64(gw),
GasUsed: int64(gu),
}
}
// QueryResult returns a ResponseQuery from an error. It will try to parse ABCI
// info from the error.
func QueryResult(err error) abci.ResponseQuery {
space, code, log := ABCIInfo(err, false)
return abci.ResponseQuery{
Codespace: space,
Code: code,
Log: log,
}
}
// The debugErrEncoder encodes the error with a stacktrace.
func debugErrEncoder(err error) string {
return fmt.Sprintf("%+v", err)

View File

@ -15,17 +15,17 @@ func TestABCInfo(t *testing.T) {
wantSpace string
wantLog string
}{
"plain weave error": {
"plain SDK error": {
err: ErrUnauthorized,
debug: false,
wantLog: "unauthorized",
wantCode: ErrUnauthorized.code,
wantSpace: RootCodespace,
},
"wrapped weave error": {
"wrapped SDK error": {
err: Wrap(Wrap(ErrUnauthorized, "foo"), "bar"),
debug: false,
wantLog: "bar: foo: unauthorized",
wantLog: "unauthorized: foo: bar",
wantCode: ErrUnauthorized.code,
wantSpace: RootCodespace,
},
@ -36,7 +36,7 @@ func TestABCInfo(t *testing.T) {
wantCode: 0,
wantSpace: "",
},
"nil weave error is not an error": {
"nil SDK error is not an error": {
err: (*Error)(nil),
debug: false,
wantLog: "",
@ -112,23 +112,23 @@ func TestABCIInfoStacktrace(t *testing.T) {
wantStacktrace bool
wantErrMsg string
}{
"wrapped weave error in debug mode provides stacktrace": {
"wrapped SDK error in debug mode provides stacktrace": {
err: Wrap(ErrUnauthorized, "wrapped"),
debug: true,
wantStacktrace: true,
wantErrMsg: "wrapped: unauthorized",
wantErrMsg: "unauthorized: wrapped",
},
"wrapped weave error in non-debug mode does not have stacktrace": {
"wrapped SDK error in non-debug mode does not have stacktrace": {
err: Wrap(ErrUnauthorized, "wrapped"),
debug: false,
wantStacktrace: false,
wantErrMsg: "wrapped: unauthorized",
wantErrMsg: "unauthorized: wrapped",
},
"wrapped stdlib error in debug mode provides stacktrace": {
err: Wrap(fmt.Errorf("stdlib"), "wrapped"),
debug: true,
wantStacktrace: true,
wantErrMsg: "wrapped: stdlib",
wantErrMsg: "stdlib: wrapped",
},
"wrapped stdlib error in non-debug mode does not have stacktrace": {
err: Wrap(fmt.Errorf("stdlib"), "wrapped"),
@ -163,7 +163,7 @@ func TestABCIInfoHidesStacktrace(t *testing.T) {
err := Wrap(ErrUnauthorized, "wrapped")
_, _, log := ABCIInfo(err, false)
if log != "wrapped: unauthorized" {
if log != "unauthorized: wrapped" {
t.Fatalf("unexpected message in non debug mode: %s", log)
}
}
@ -173,7 +173,7 @@ func TestRedact(t *testing.T) {
t.Error("reduct must not pass through panic error")
}
if err := Redact(ErrUnauthorized); !ErrUnauthorized.Is(err) {
t.Error("reduct should pass through weave error")
t.Error("reduct should pass through SDK error")
}
var cerr customErr
@ -203,12 +203,12 @@ func TestABCIInfoSerializeErr(t *testing.T) {
"single error": {
src: myErrDecode,
debug: false,
exp: "test: tx parse error",
exp: "tx parse error: test",
},
"second error": {
src: myErrAddr,
debug: false,
exp: "tester: invalid address",
exp: "invalid address: tester",
},
"single error with debug": {
src: myErrDecode,

View File

@ -44,32 +44,43 @@ var (
// ErrUnknownAddress to doc
ErrUnknownAddress = Register(RootCodespace, 9, "unknown address")
// ErrInsufficientCoins to doc (what is the difference between ErrInsufficientFunds???)
ErrInsufficientCoins = Register(RootCodespace, 10, "insufficient coins")
// ErrInvalidCoins to doc
ErrInvalidCoins = Register(RootCodespace, 11, "invalid coins")
ErrInvalidCoins = Register(RootCodespace, 10, "invalid coins")
// ErrOutOfGas to doc
ErrOutOfGas = Register(RootCodespace, 12, "out of gas")
ErrOutOfGas = Register(RootCodespace, 11, "out of gas")
// ErrMemoTooLarge to doc
ErrMemoTooLarge = Register(RootCodespace, 13, "memo too large")
ErrMemoTooLarge = Register(RootCodespace, 12, "memo too large")
// ErrInsufficientFee to doc
ErrInsufficientFee = Register(RootCodespace, 14, "insufficient fee")
ErrInsufficientFee = Register(RootCodespace, 13, "insufficient fee")
// ErrTooManySignatures to doc
ErrTooManySignatures = Register(RootCodespace, 15, "maximum numer of signatures exceeded")
ErrTooManySignatures = Register(RootCodespace, 14, "maximum number of signatures exceeded")
// ErrNoSignatures to doc
ErrNoSignatures = Register(RootCodespace, 16, "no signatures supplied")
ErrNoSignatures = Register(RootCodespace, 15, "no signatures supplied")
// ErrJSONMarshal defines an ABCI typed JSON marshalling error
ErrJSONMarshal = Register(RootCodespace, 17, "failed to marshal JSON bytes")
ErrJSONMarshal = Register(RootCodespace, 16, "failed to marshal JSON bytes")
// ErrJSONUnmarshal defines an ABCI typed JSON unmarshalling error
ErrJSONUnmarshal = Register(RootCodespace, 18, "failed to unmarshal JSON bytes")
ErrJSONUnmarshal = Register(RootCodespace, 17, "failed to unmarshal JSON bytes")
// ErrInvalidRequest defines an ABCI typed error where the request contains
// invalid data.
ErrInvalidRequest = Register(RootCodespace, 18, "invalid request")
// ErrTxInMempoolCache defines an ABCI typed error where a tx already exists
// in the mempool.
ErrTxInMempoolCache = Register(RootCodespace, 19, "tx already in mempool")
// ErrMempoolIsFull defines an ABCI typed error where the mempool is full.
ErrMempoolIsFull = Register(RootCodespace, 20, "mempool is full")
// ErrTxTooLarge defines an ABCI typed error where tx is too large.
ErrTxTooLarge = Register(RootCodespace, 21, "tx too large")
// ErrPanic is only set when we recover from a panic, so we know to
// redact potentially sensitive system info
@ -89,12 +100,10 @@ func Register(codespace string, code uint32, description string) *Error {
if e := getUsed(codespace, code); e != nil {
panic(fmt.Sprintf("error with code %d is already registered: %q", code, e.desc))
}
err := &Error{
code: code,
codespace: codespace,
desc: description,
}
err := New(codespace, code, description)
setUsed(err)
return err
}
@ -247,7 +256,7 @@ type wrappedError struct {
}
func (e *wrappedError) Error() string {
return fmt.Sprintf("%s: %s", e.msg, e.parent.Error())
return fmt.Sprintf("%s: %s", e.parent.Error(), e.msg)
}
func (e *wrappedError) Cause() error {

View File

@ -15,19 +15,19 @@ func TestStackTrace(t *testing.T) {
}{
"New gives us a stacktrace": {
err: Wrap(ErrNoSignatures, "name"),
wantError: "name: no signatures supplied",
wantError: "no signatures supplied: name",
},
"Wrapping stderr gives us a stacktrace": {
err: Wrap(fmt.Errorf("foo"), "standard"),
wantError: "standard: foo",
wantError: "foo: standard",
},
"Wrapping pkg/errors gives us clean stacktrace": {
err: Wrap(errors.New("bar"), "pkg"),
wantError: "pkg: bar",
wantError: "bar: pkg",
},
"Wrapping inside another function is still clean": {
err: Wrap(fmt.Errorf("indirect"), "do the do"),
wantError: "do the do: indirect",
wantError: "indirect: do the do",
},
}

View File

@ -1,138 +0,0 @@
package types
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
var codeTypes = []CodeType{
CodeInternal,
CodeTxDecode,
CodeInvalidSequence,
CodeUnauthorized,
CodeInsufficientFunds,
CodeUnknownRequest,
CodeInvalidAddress,
CodeInvalidPubKey,
CodeUnknownAddress,
CodeInsufficientCoins,
CodeInvalidCoins,
CodeOutOfGas,
CodeMemoTooLarge,
}
type errFn func(msg string) Error
var errFns = []errFn{
ErrInternal,
ErrTxDecode,
ErrInvalidSequence,
ErrUnauthorized,
ErrInsufficientFunds,
ErrUnknownRequest,
ErrInvalidAddress,
ErrInvalidPubKey,
ErrUnknownAddress,
ErrInsufficientCoins,
ErrInvalidCoins,
ErrOutOfGas,
ErrMemoTooLarge,
}
func TestCodeType(t *testing.T) {
require.True(t, CodeOK.IsOK())
for tcnum, c := range codeTypes {
msg := CodeToDefaultMsg(c)
require.NotEqual(t, unknownCodeMsg(c), msg, "Code expected to be known. tc #%d, code %d, msg %s", tcnum, c, msg)
}
msg := CodeToDefaultMsg(CodeOK)
require.Equal(t, unknownCodeMsg(CodeOK), msg)
}
func TestErrFn(t *testing.T) {
for i, errFn := range errFns {
err := errFn("")
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.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")
}
}
func TestAppendMsgToErr(t *testing.T) {
for i, errFn := range errFns {
err := errFn("")
errMsg := err.Stacktrace().Error()
abciLog := err.ABCILog()
// plain msg error
msg := AppendMsgToErr("something unexpected happened", errMsg)
require.Equal(
t,
fmt.Sprintf("something unexpected happened; %s", errMsg),
msg,
fmt.Sprintf("Should have formatted the error message of ABCI Log. tc #%d", i),
)
// ABCI Log msg error
msg = AppendMsgToErr("something unexpected happened", abciLog)
msgIdx := mustGetMsgIndex(abciLog)
require.Equal(
t,
fmt.Sprintf("%s%s; %s}",
abciLog[:msgIdx],
"something unexpected happened",
abciLog[msgIdx:len(abciLog)-1],
),
msg,
fmt.Sprintf("Should have formatted the error message of ABCI Log. tc #%d", i))
}
}
func TestResultFromError(t *testing.T) {
cases := map[string]struct {
err error
expect Result
}{
"sdk.Error": {
err: ErrUnauthorized("not owner"),
expect: Result{
Codespace: CodespaceRoot,
Code: CodeUnauthorized,
Log: `{"codespace":"sdk","code":4,"message":"not owner"}`,
},
},
"types/errors": {
err: sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "not owner"),
expect: Result{
Codespace: CodespaceRoot,
Code: CodeUnauthorized,
Log: `{"codespace":"sdk","code":4,"message":"not owner: unauthorized"}`,
},
},
"stdlib errors": {
err: fmt.Errorf("not owner"),
expect: Result{
Codespace: CodespaceType("undefined"),
Code: CodeInternal,
// note that we redact the internal errors in the new package to not leak eg. panics
Log: `{"codespace":"undefined","code":1,"message":"internal error"}`,
},
},
}
for name, tc := range cases {
tc := tc
t.Run(name, func(t *testing.T) {
res := ResultFromError(tc.err)
require.Equal(t, tc.expect, res)
})
}
}

View File

@ -1,7 +1,7 @@
package types
// Handler defines the core of the state transition function of an application.
type Handler func(ctx Context, msg Msg) Result
type Handler func(ctx Context, msg Msg) (*Result, error)
// AnteHandler authenticates transactions, before their internal messages are handled.
// If newCtx.IsZero(), ctx is used instead.

View File

@ -1,6 +1,9 @@
package types
import abci "github.com/tendermint/tendermint/abci/types"
import (
abci "github.com/tendermint/tendermint/abci/types"
)
// Type for querier functions on keepers to implement to handle custom queries
type Querier = func(ctx Context, path []string, req abci.RequestQuery) (res []byte, err Error)
// Querier defines a function type that a module querier must implement to handle
// custom client queries.
type Querier = func(ctx Context, path []string, req abci.RequestQuery) ([]byte, error)

View File

@ -12,36 +12,27 @@ import (
ctypes "github.com/tendermint/tendermint/rpc/core/types"
)
// Result is the union of ResponseFormat and ResponseCheckTx.
type Result struct {
// Code is the response code, is stored back on the chain.
Code CodeType
// Codespace is the string referring to the domain of an error
Codespace CodespaceType
// Data is any data returned from the app.
// Data has to be length prefixed in order to separate
// results from multiple msgs executions
Data []byte
// Log contains the txs log information. NOTE: nondeterministic.
Log string
// GasInfo defines tx execution gas context.
type GasInfo struct {
// GasWanted is the maximum units of work we allow this tx to perform.
GasWanted uint64
// GasUsed is the amount of gas actually consumed. NOTE: unimplemented
GasUsed uint64
// Events contains a slice of Event objects that were emitted during some
// execution.
Events Events
}
// TODO: In the future, more codes may be OK.
func (res Result) IsOK() bool {
return res.Code.IsOK()
// Result is the union of ResponseFormat and ResponseCheckTx.
type Result struct {
// Data is any data returned from message or handler execution. It MUST be length
// prefixed in order to separate data from multiple message executions.
Data []byte
// Log contains the log information from message or handler execution.
Log string
// Events contains a slice of Event objects that were emitted during message or
// handler execution.
Events Events
}
// ABCIMessageLogs represents a slice of ABCIMessageLog.
@ -50,7 +41,6 @@ type ABCIMessageLogs []ABCIMessageLog
// ABCIMessageLog defines a structure containing an indexed tx ABCI message log.
type ABCIMessageLog struct {
MsgIndex uint16 `json:"msg_index"`
Success bool `json:"success"`
Log string `json:"log"`
// Events contains a slice of Event objects that were emitted during some
@ -58,10 +48,9 @@ type ABCIMessageLog struct {
Events StringEvents `json:"events"`
}
func NewABCIMessageLog(i uint16, success bool, log string, events Events) ABCIMessageLog {
func NewABCIMessageLog(i uint16, log string, events Events) ABCIMessageLog {
return ABCIMessageLog{
MsgIndex: i,
Success: success,
Log: log,
Events: StringifyEvents(events.ToABCIEvents()),
}
@ -84,6 +73,7 @@ func (logs ABCIMessageLogs) String() (str string) {
type TxResponse struct {
Height int64 `json:"height"`
TxHash string `json:"txhash"`
Codespace string `json:"codespace,omitempty"`
Code uint32 `json:"code,omitempty"`
Data string `json:"data,omitempty"`
RawLog string `json:"raw_log,omitempty"`
@ -91,7 +81,6 @@ type TxResponse struct {
Info string `json:"info,omitempty"`
GasWanted int64 `json:"gas_wanted,omitempty"`
GasUsed int64 `json:"gas_used,omitempty"`
Codespace string `json:"codespace,omitempty"`
Tx Tx `json:"tx,omitempty"`
Timestamp string `json:"timestamp,omitempty"`
@ -111,6 +100,7 @@ func NewResponseResultTx(res *ctypes.ResultTx, tx Tx, timestamp string) TxRespon
return TxResponse{
TxHash: res.Hash.String(),
Height: res.Height,
Codespace: res.TxResult.Codespace,
Code: res.TxResult.Code,
Data: strings.ToUpper(hex.EncodeToString(res.TxResult.Data)),
RawLog: res.TxResult.Log,
@ -153,6 +143,7 @@ func newTxResponseCheckTx(res *ctypes.ResultBroadcastTxCommit) TxResponse {
return TxResponse{
Height: res.Height,
TxHash: txHash,
Codespace: res.CheckTx.Codespace,
Code: res.CheckTx.Code,
Data: strings.ToUpper(hex.EncodeToString(res.CheckTx.Data)),
RawLog: res.CheckTx.Log,
@ -161,7 +152,6 @@ func newTxResponseCheckTx(res *ctypes.ResultBroadcastTxCommit) TxResponse {
GasWanted: res.CheckTx.GasWanted,
GasUsed: res.CheckTx.GasUsed,
Events: StringifyEvents(res.CheckTx.Events),
Codespace: res.CheckTx.Codespace,
}
}
@ -180,6 +170,7 @@ func newTxResponseDeliverTx(res *ctypes.ResultBroadcastTxCommit) TxResponse {
return TxResponse{
Height: res.Height,
TxHash: txHash,
Codespace: res.DeliverTx.Codespace,
Code: res.DeliverTx.Code,
Data: strings.ToUpper(hex.EncodeToString(res.DeliverTx.Data)),
RawLog: res.DeliverTx.Log,
@ -188,7 +179,6 @@ func newTxResponseDeliverTx(res *ctypes.ResultBroadcastTxCommit) TxResponse {
GasWanted: res.DeliverTx.GasWanted,
GasUsed: res.DeliverTx.GasUsed,
Events: StringifyEvents(res.DeliverTx.Events),
Codespace: res.DeliverTx.Codespace,
}
}

View File

@ -7,17 +7,6 @@ import (
"github.com/stretchr/testify/require"
)
func TestResult(t *testing.T) {
var res Result
require.True(t, res.IsOK())
res.Data = []byte("data")
require.True(t, res.IsOK())
res.Code = CodeType(1)
require.False(t, res.IsOK())
}
func TestParseABCILog(t *testing.T) {
logs := `[{"log":"","msg_index":1,"success":true}]`
@ -26,12 +15,11 @@ func TestParseABCILog(t *testing.T) {
require.Len(t, res, 1)
require.Equal(t, res[0].Log, "")
require.Equal(t, res[0].MsgIndex, uint16(1))
require.True(t, res[0].Success)
}
func TestABCIMessageLog(t *testing.T) {
events := Events{NewEvent("transfer", NewAttribute("sender", "foo"))}
msgLog := NewABCIMessageLog(0, true, "", events)
msgLog := NewABCIMessageLog(0, "", events)
msgLogs := ABCIMessageLogs{msgLog}
bz, err := codec.Cdc.MarshalJSON(msgLogs)

View File

@ -17,7 +17,7 @@ type Msg interface {
// ValidateBasic does a simple validation check that
// doesn't require access to any other information.
ValidateBasic() Error
ValidateBasic() error
// Get the canonical byte representation of the Msg.
GetSignBytes() []byte
@ -37,13 +37,13 @@ type Tx interface {
// ValidateBasic does a simple and lightweight validation check that doesn't
// require access to any other information.
ValidateBasic() Error
ValidateBasic() error
}
//__________________________________________________________
// TxDecoder unmarshals transaction bytes
type TxDecoder func(txBytes []byte) (Tx, Error)
type TxDecoder func(txBytes []byte) (Tx, error)
// TxEncoder marshals transaction to bytes
type TxEncoder func(tx Tx) ([]byte, error)
@ -73,7 +73,7 @@ func (msg *TestMsg) GetSignBytes() []byte {
}
return MustSortJSON(bz)
}
func (msg *TestMsg) ValidateBasic() Error { return nil }
func (msg *TestMsg) ValidateBasic() error { return nil }
func (msg *TestMsg) GetSigners() []AccAddress {
return msg.signers
}

View File

@ -2,6 +2,7 @@ package ante_test
import (
"encoding/json"
"errors"
"fmt"
"math/rand"
"strings"
@ -26,14 +27,10 @@ func checkValidTx(t *testing.T, anteHandler sdk.AnteHandler, ctx sdk.Context, tx
}
// run the tx through the anteHandler and ensure it fails with the given code
func checkInvalidTx(t *testing.T, anteHandler sdk.AnteHandler, ctx sdk.Context, tx sdk.Tx, simulate bool, code sdk.CodeType) {
func checkInvalidTx(t *testing.T, anteHandler sdk.AnteHandler, ctx sdk.Context, tx sdk.Tx, simulate bool, expErr error) {
_, err := anteHandler(ctx, tx, simulate)
require.NotNil(t, err)
result := sdk.ResultFromError(err)
require.Equal(t, code, result.Code, fmt.Sprintf("Expected %v, got %v", code, result))
require.Equal(t, sdk.CodespaceRoot, result.Codespace)
require.True(t, errors.Is(expErr, err))
}
// Test that simulate transaction accurately estimates gas cost
@ -117,23 +114,23 @@ func TestAnteHandlerSigErrors(t *testing.T) {
require.Equal(t, expectedSigners, stdTx.GetSigners())
// Check no signatures fails
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeNoSignatures)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrNoSignatures)
// test num sigs dont match GetSigners
privs, accNums, seqs = []crypto.PrivKey{priv1}, []uint64{0}, []uint64{0}
tx = types.NewTestTx(ctx, msgs, privs, accNums, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrUnauthorized)
// test an unrecognized account
privs, accNums, seqs = []crypto.PrivKey{priv1, priv2, priv3}, []uint64{0, 1, 2}, []uint64{0, 0, 0}
tx = types.NewTestTx(ctx, msgs, privs, accNums, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnknownAddress)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrUnknownAddress)
// save the first account, but second is still unrecognized
acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1)
acc1.SetCoins(fee.Amount)
app.AccountKeeper.SetAccount(ctx, acc1)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnknownAddress)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrUnknownAddress)
}
// Test logic around account number checking with one signer and many signers.
@ -172,7 +169,7 @@ func TestAnteHandlerAccountNumbers(t *testing.T) {
// new tx from wrong account number
seqs = []uint64{1}
tx = types.NewTestTx(ctx, msgs, privs, []uint64{1}, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrUnauthorized)
// from correct account number
seqs = []uint64{1}
@ -185,7 +182,7 @@ func TestAnteHandlerAccountNumbers(t *testing.T) {
msgs = []sdk.Msg{msg1, msg2}
privs, accnums, seqs = []crypto.PrivKey{priv1, priv2}, []uint64{1, 0}, []uint64{2, 0}
tx = types.NewTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrUnauthorized)
// correct account numbers
privs, accnums, seqs = []crypto.PrivKey{priv1, priv2}, []uint64{0, 1}, []uint64{2, 0}
@ -228,7 +225,7 @@ func TestAnteHandlerAccountNumbersAtBlockHeightZero(t *testing.T) {
// new tx from wrong account number
seqs = []uint64{1}
tx = types.NewTestTx(ctx, msgs, privs, []uint64{1}, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrUnauthorized)
// from correct account number
seqs = []uint64{1}
@ -241,7 +238,7 @@ func TestAnteHandlerAccountNumbersAtBlockHeightZero(t *testing.T) {
msgs = []sdk.Msg{msg1, msg2}
privs, accnums, seqs = []crypto.PrivKey{priv1, priv2}, []uint64{1, 0}, []uint64{2, 0}
tx = types.NewTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrUnauthorized)
// correct account numbers
privs, accnums, seqs = []crypto.PrivKey{priv1, priv2}, []uint64{0, 0}, []uint64{2, 0}
@ -288,7 +285,7 @@ func TestAnteHandlerSequences(t *testing.T) {
checkValidTx(t, anteHandler, ctx, tx, false)
// test sending it again fails (replay protection)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrUnauthorized)
// fix sequence, should pass
seqs = []uint64{1}
@ -305,14 +302,14 @@ func TestAnteHandlerSequences(t *testing.T) {
checkValidTx(t, anteHandler, ctx, tx, false)
// replay fails
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrUnauthorized)
// tx from just second signer with incorrect sequence fails
msg = types.NewTestMsg(addr2)
msgs = []sdk.Msg{msg}
privs, accnums, seqs = []crypto.PrivKey{priv2}, []uint64{1}, []uint64{0}
tx = types.NewTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeUnauthorized)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrUnauthorized)
// fix the sequence and it passes
tx = types.NewTestTx(ctx, msgs, []crypto.PrivKey{priv2}, []uint64{1}, []uint64{1}, fee)
@ -348,11 +345,11 @@ func TestAnteHandlerFees(t *testing.T) {
// signer does not have enough funds to pay the fee
tx = types.NewTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInsufficientFunds)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrInsufficientFunds)
acc1.SetCoins(sdk.NewCoins(sdk.NewInt64Coin("atom", 149)))
app.AccountKeeper.SetAccount(ctx, acc1)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInsufficientFunds)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrInsufficientFunds)
require.True(t, app.SupplyKeeper.GetModuleAccount(ctx, types.FeeCollectorName).GetCoins().Empty())
require.True(sdk.IntEq(t, app.AccountKeeper.GetAccount(ctx, addr1).GetCoins().AmountOf("atom"), sdk.NewInt(149)))
@ -388,17 +385,17 @@ func TestAnteHandlerMemoGas(t *testing.T) {
// tx does not have enough gas
tx = types.NewTestTx(ctx, []sdk.Msg{msg}, privs, accnums, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeOutOfGas)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrOutOfGas)
// tx with memo doesn't have enough gas
fee = types.NewStdFee(801, sdk.NewCoins(sdk.NewInt64Coin("atom", 0)))
tx = types.NewTestTxWithMemo(ctx, []sdk.Msg{msg}, privs, accnums, seqs, fee, "abcininasidniandsinasindiansdiansdinaisndiasndiadninsd")
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeOutOfGas)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrOutOfGas)
// memo too large
fee = types.NewStdFee(50000, sdk.NewCoins(sdk.NewInt64Coin("atom", 0)))
tx = types.NewTestTxWithMemo(ctx, []sdk.Msg{msg}, privs, accnums, seqs, fee, strings.Repeat("01234567890", 500))
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeMemoTooLarge)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrMemoTooLarge)
// tx with memo has enough gas
fee = types.NewStdFee(50000, sdk.NewCoins(sdk.NewInt64Coin("atom", 0)))
@ -492,7 +489,7 @@ func TestAnteHandlerBadSignBytes(t *testing.T) {
chainID := ctx.ChainID()
chainID2 := chainID + "somemorestuff"
codeUnauth := sdk.CodeUnauthorized
errUnauth := sdkerrors.ErrUnauthorized
cases := []struct {
chainID string
@ -500,14 +497,14 @@ func TestAnteHandlerBadSignBytes(t *testing.T) {
seq uint64
fee types.StdFee
msgs []sdk.Msg
code sdk.CodeType
err error
}{
{chainID2, 0, 1, fee, msgs, codeUnauth}, // test wrong chain_id
{chainID, 0, 2, fee, msgs, codeUnauth}, // test wrong seqs
{chainID, 1, 1, fee, msgs, codeUnauth}, // test wrong accnum
{chainID, 0, 1, fee, []sdk.Msg{types.NewTestMsg(addr2)}, codeUnauth}, // test wrong msg
{chainID, 0, 1, fee2, msgs, codeUnauth}, // test wrong fee
{chainID, 0, 1, fee3, msgs, codeUnauth}, // test wrong fee
{chainID2, 0, 1, fee, msgs, errUnauth}, // test wrong chain_id
{chainID, 0, 2, fee, msgs, errUnauth}, // test wrong seqs
{chainID, 1, 1, fee, msgs, errUnauth}, // test wrong accnum
{chainID, 0, 1, fee, []sdk.Msg{types.NewTestMsg(addr2)}, errUnauth}, // test wrong msg
{chainID, 0, 1, fee2, msgs, errUnauth}, // test wrong fee
{chainID, 0, 1, fee3, msgs, errUnauth}, // test wrong fee
}
privs, seqs = []crypto.PrivKey{priv1}, []uint64{1}
@ -517,20 +514,20 @@ func TestAnteHandlerBadSignBytes(t *testing.T) {
types.StdSignBytes(cs.chainID, cs.accnum, cs.seq, cs.fee, cs.msgs, ""),
"",
)
checkInvalidTx(t, anteHandler, ctx, tx, false, cs.code)
checkInvalidTx(t, anteHandler, ctx, tx, false, cs.err)
}
// test wrong signer if public key exist
privs, accnums, seqs = []crypto.PrivKey{priv2}, []uint64{0}, []uint64{1}
tx = types.NewTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidPubKey)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrInvalidPubKey)
// test wrong signer if public doesn't exist
msg = types.NewTestMsg(addr2)
msgs = []sdk.Msg{msg}
privs, accnums, seqs = []crypto.PrivKey{priv1}, []uint64{1}, []uint64{0}
tx = types.NewTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidPubKey)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrInvalidPubKey)
}
func TestAnteHandlerSetPubKey(t *testing.T) {
@ -572,14 +569,14 @@ func TestAnteHandlerSetPubKey(t *testing.T) {
tx = types.NewTestTx(ctx, msgs, privs, []uint64{1}, seqs, fee)
sigs := tx.(types.StdTx).Signatures
sigs[0].PubKey = nil
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidPubKey)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrInvalidPubKey)
acc2 = app.AccountKeeper.GetAccount(ctx, addr2)
require.Nil(t, acc2.GetPubKey())
// test invalid signature and public key
tx = types.NewTestTx(ctx, msgs, privs, []uint64{1}, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidPubKey)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrInvalidPubKey)
acc2 = app.AccountKeeper.GetAccount(ctx, addr2)
require.Nil(t, acc2.GetPubKey())
@ -686,7 +683,7 @@ func TestAnteHandlerSigLimitExceeded(t *testing.T) {
privs, accnums, seqs := []crypto.PrivKey{priv1, priv2, priv3, priv4, priv5, priv6, priv7, priv8},
[]uint64{0, 1, 2, 3, 4, 5, 6, 7}, []uint64{0, 0, 0, 0, 0, 0, 0, 0}
tx = types.NewTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeTooManySignatures)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrTooManySignatures)
}
// Test custom SignatureVerificationGasConsumer
@ -717,7 +714,7 @@ func TestCustomSignatureVerificationGasConsumer(t *testing.T) {
fee := types.NewTestStdFee()
msgs := []sdk.Msg{msg}
tx = types.NewTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeInvalidPubKey)
checkInvalidTx(t, anteHandler, ctx, tx, false, sdkerrors.ErrInvalidPubKey)
// verify that an ed25519 account gets accepted
priv2 := ed25519.GenPrivKey()

View File

@ -61,8 +61,10 @@ func QueryTxsRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
err := r.ParseForm()
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest,
sdk.AppendMsgToErr("could not parse query parameters", err.Error()))
rest.WriteErrorResponse(
w, http.StatusBadRequest,
fmt.Sprintf("failed to parse query parameters: %s", err),
)
return
}

View File

@ -278,12 +278,12 @@ func adjustGasEstimate(estimate uint64, adjustment float64) uint64 {
}
func parseQueryResponse(cdc *codec.Codec, rawRes []byte) (uint64, error) {
var simulationResult sdk.Result
if err := cdc.UnmarshalBinaryLengthPrefixed(rawRes, &simulationResult); err != nil {
var gasUsed uint64
if err := cdc.UnmarshalBinaryLengthPrefixed(rawRes, &gasUsed); err != nil {
return 0, err
}
return simulationResult.GasUsed, nil
return gasUsed, nil
}
// PrepareTxBuilder populates a TxBuilder in preparation for the build of a Tx.

View File

@ -23,7 +23,7 @@ var (
func TestParseQueryResponse(t *testing.T) {
cdc := makeCodec()
sdkResBytes := cdc.MustMarshalBinaryLengthPrefixed(sdk.Result{GasUsed: 10})
sdkResBytes := cdc.MustMarshalBinaryLengthPrefixed(uint64(10))
gas, err := parseQueryResponse(cdc, sdkResBytes)
assert.Equal(t, gas, uint64(10))
assert.Nil(t, err)
@ -39,14 +39,16 @@ func TestCalculateGas(t *testing.T) {
if wantErr {
return nil, 0, errors.New("")
}
return cdc.MustMarshalBinaryLengthPrefixed(sdk.Result{GasUsed: gasUsed}), 0, nil
return cdc.MustMarshalBinaryLengthPrefixed(gasUsed), 0, nil
}
}
type args struct {
queryFuncGasUsed uint64
queryFuncWantErr bool
adjustment float64
}
tests := []struct {
name string
args args
@ -57,6 +59,7 @@ func TestCalculateGas(t *testing.T) {
{"error", args{0, true, 1.2}, 0, 0, true},
{"adjusted gas", args{10, false, 1.2}, 10, 12, false},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {

View File

@ -8,6 +8,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/auth/exported"
"github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/params/subspace"
@ -49,19 +50,19 @@ func (ak AccountKeeper) Logger(ctx sdk.Context) log.Logger {
}
// GetPubKey Returns the PubKey of the account at address
func (ak AccountKeeper) GetPubKey(ctx sdk.Context, addr sdk.AccAddress) (crypto.PubKey, sdk.Error) {
func (ak AccountKeeper) GetPubKey(ctx sdk.Context, addr sdk.AccAddress) (crypto.PubKey, error) {
acc := ak.GetAccount(ctx, addr)
if acc == nil {
return nil, sdk.ErrUnknownAddress(fmt.Sprintf("account %s does not exist", addr))
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "account %s does not exist", addr)
}
return acc.GetPubKey(), nil
}
// GetSequence Returns the Sequence of the account at address
func (ak AccountKeeper) GetSequence(ctx sdk.Context, addr sdk.AccAddress) (uint64, sdk.Error) {
func (ak AccountKeeper) GetSequence(ctx sdk.Context, addr sdk.AccAddress) (uint64, error) {
acc := ak.GetAccount(ctx, addr)
if acc == nil {
return 0, sdk.ErrUnknownAddress(fmt.Sprintf("account %s does not exist", addr))
return 0, sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "account %s does not exist", addr)
}
return acc.GetSequence(), nil
}

View File

@ -1,41 +1,40 @@
package keeper
import (
"fmt"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/auth/types"
)
// NewQuerier creates a querier for auth REST endpoints
func NewQuerier(keeper AccountKeeper) sdk.Querier {
return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, sdk.Error) {
return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) {
switch path[0] {
case types.QueryAccount:
return queryAccount(ctx, req, keeper)
default:
return nil, sdk.ErrUnknownRequest("unknown auth query endpoint")
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown query path: %s", path[0])
}
}
}
func queryAccount(ctx sdk.Context, req abci.RequestQuery, keeper AccountKeeper) ([]byte, sdk.Error) {
func queryAccount(ctx sdk.Context, req abci.RequestQuery, keeper AccountKeeper) ([]byte, error) {
var params types.QueryAccountParams
if err := keeper.cdc.UnmarshalJSON(req.Data, &params); err != nil {
return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
account := keeper.GetAccount(ctx, params.Address)
if account == nil {
return nil, sdk.ErrUnknownAddress(fmt.Sprintf("account %s does not exist", params.Address))
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "account %s does not exist", params.Address)
}
bz, err := codec.MarshalJSONIndent(keeper.cdc, account)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil

View File

@ -7,7 +7,7 @@ import (
// SupplyKeeper defines the expected supply Keeper (noalias)
type SupplyKeeper interface {
SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) sdk.Error
SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
GetModuleAccount(ctx sdk.Context, moduleName string) exported.ModuleAccountI
GetModuleAddress(moduleName string) sdk.AccAddress
}

View File

@ -10,6 +10,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/auth/exported"
)
@ -42,20 +43,29 @@ func (tx StdTx) GetMsgs() []sdk.Msg { return tx.Msgs }
// ValidateBasic does a simple and lightweight validation check that doesn't
// require access to any other information.
func (tx StdTx) ValidateBasic() sdk.Error {
func (tx StdTx) ValidateBasic() error {
stdSigs := tx.GetSignatures()
if tx.Fee.Gas > maxGasWanted {
return sdk.ErrGasOverflow(fmt.Sprintf("invalid gas supplied; %d > %d", tx.Fee.Gas, maxGasWanted))
return sdkerrors.Wrapf(
sdkerrors.ErrInvalidRequest,
"invalid gas supplied; %d > %d", tx.Fee.Gas, maxGasWanted,
)
}
if tx.Fee.Amount.IsAnyNegative() {
return sdk.ErrInsufficientFee(fmt.Sprintf("invalid fee %s amount provided", tx.Fee.Amount))
return sdkerrors.Wrapf(
sdkerrors.ErrInsufficientFee,
"invalid fee provided: %s", tx.Fee.Amount,
)
}
if len(stdSigs) == 0 {
return sdk.ErrNoSignatures("no signers")
return sdkerrors.ErrNoSignatures
}
if len(stdSigs) != len(tx.GetSigners()) {
return sdk.ErrUnauthorized("wrong number of signers")
return sdkerrors.Wrapf(
sdkerrors.ErrUnauthorized,
"wrong number of signers; expected %d, got %d", tx.GetSigners(), len(stdSigs),
)
}
return nil
@ -240,18 +250,18 @@ type StdSignature struct {
// DefaultTxDecoder logic for standard transaction decoding
func DefaultTxDecoder(cdc *codec.Codec) sdk.TxDecoder {
return func(txBytes []byte) (sdk.Tx, sdk.Error) {
return func(txBytes []byte) (sdk.Tx, error) {
var tx = StdTx{}
if len(txBytes) == 0 {
return nil, sdk.ErrTxDecode("txBytes are empty")
return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "tx bytes are empty")
}
// StdTx.Msg is an interface. The concrete types
// are registered by MakeTxCodec
err := cdc.UnmarshalBinaryLengthPrefixed(txBytes, &tx)
if err != nil {
return nil, sdk.ErrTxDecode("error decoding transaction").TraceSDK(err.Error())
return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, err.Error())
}
return tx, nil

View File

@ -13,6 +13,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
var (
@ -78,7 +79,8 @@ func TestTxValidateBasic(t *testing.T) {
err := tx.ValidateBasic()
require.Error(t, err)
require.Equal(t, sdk.CodeInsufficientFee, err.Result().Code)
_, code, _ := sdkerrors.ABCIInfo(err, false)
require.Equal(t, sdkerrors.ErrInsufficientFee.ABCICode(), code)
// require to fail validation when no signatures exist
privs, accNums, seqs := []crypto.PrivKey{}, []uint64{}, []uint64{}
@ -86,7 +88,8 @@ func TestTxValidateBasic(t *testing.T) {
err = tx.ValidateBasic()
require.Error(t, err)
require.Equal(t, sdk.CodeNoSignatures, err.Result().Code)
_, code, _ = sdkerrors.ABCIInfo(err, false)
require.Equal(t, sdkerrors.ErrNoSignatures.ABCICode(), code)
// require to fail validation when signatures do not match expected signers
privs, accNums, seqs = []crypto.PrivKey{priv1}, []uint64{0, 1}, []uint64{0, 0}
@ -94,7 +97,8 @@ func TestTxValidateBasic(t *testing.T) {
err = tx.ValidateBasic()
require.Error(t, err)
require.Equal(t, sdk.CodeUnauthorized, err.Result().Code)
_, code, _ = sdkerrors.ABCIInfo(err, false)
require.Equal(t, sdkerrors.ErrUnauthorized.ABCICode(), code)
// require to fail with invalid gas supplied
badFee = NewTestStdFee()
@ -103,7 +107,8 @@ func TestTxValidateBasic(t *testing.T) {
err = tx.ValidateBasic()
require.Error(t, err)
require.Equal(t, sdk.CodeGasOverflow, err.Result().Code)
_, code, _ = sdkerrors.ABCIInfo(err, false)
require.Equal(t, sdkerrors.ErrInvalidRequest.ABCICode(), code)
// require to pass when above criteria are matched
privs, accNums, seqs = []crypto.PrivKey{priv1, priv2}, []uint64{0, 1}, []uint64{0, 0}

View File

@ -1,25 +1,19 @@
// nolint
// autogenerated code using github.com/rigelrozanski/multitool
// aliases generated for the following subdirectories:
// ALIASGEN: github.com/cosmos/cosmos-sdk/x/bank/internal/keeper
// ALIASGEN: github.com/cosmos/cosmos-sdk/x/bank/internal/types
package bank
// nolint
import (
"github.com/cosmos/cosmos-sdk/x/bank/internal/keeper"
"github.com/cosmos/cosmos-sdk/x/bank/internal/types"
)
const (
QueryBalance = keeper.QueryBalance
DefaultCodespace = types.DefaultCodespace
CodeSendDisabled = types.CodeSendDisabled
CodeInvalidInputsOutputs = types.CodeInvalidInputsOutputs
ModuleName = types.ModuleName
QuerierRoute = types.QuerierRoute
RouterKey = types.RouterKey
DefaultParamspace = types.DefaultParamspace
DefaultSendEnabled = types.DefaultSendEnabled
QueryBalance = keeper.QueryBalance
ModuleName = types.ModuleName
QuerierRoute = types.QuerierRoute
RouterKey = types.RouterKey
DefaultParamspace = types.DefaultParamspace
DefaultSendEnabled = types.DefaultSendEnabled
EventTypeTransfer = types.EventTypeTransfer
AttributeKeyRecipient = types.AttributeKeyRecipient
@ -28,7 +22,6 @@ const (
)
var (
// functions aliases
RegisterInvariants = keeper.RegisterInvariants
NonnegativeBalanceInvariant = keeper.NonnegativeBalanceInvariant
NewBaseKeeper = keeper.NewBaseKeeper
@ -50,10 +43,8 @@ var (
ValidateInputsOutputs = types.ValidateInputsOutputs
ParamKeyTable = types.ParamKeyTable
NewQueryBalanceParams = types.NewQueryBalanceParams
// variable aliases
ModuleCdc = types.ModuleCdc
ParamStoreKeySendEnabled = types.ParamStoreKeySendEnabled
ModuleCdc = types.ModuleCdc
ParamStoreKeySendEnabled = types.ParamStoreKeySendEnabled
)
type (

View File

@ -34,10 +34,11 @@ func BenchmarkOneBankSendTxPerBlock(b *testing.B) {
// Committing, and what time comes from Check/Deliver Tx.
for i := 0; i < b.N; i++ {
benchmarkApp.BeginBlock(abci.RequestBeginBlock{})
x := benchmarkApp.Check(txs[i])
if !x.IsOK() {
_, _, err := benchmarkApp.Check(txs[i])
if err != nil {
panic("something is broken in checking transaction")
}
benchmarkApp.Deliver(txs[i])
benchmarkApp.EndBlock(abci.RequestEndBlock{})
benchmarkApp.Commit()
@ -63,10 +64,11 @@ func BenchmarkOneBankMultiSendTxPerBlock(b *testing.B) {
// Committing, and what time comes from Check/Deliver Tx.
for i := 0; i < b.N; i++ {
benchmarkApp.BeginBlock(abci.RequestBeginBlock{})
x := benchmarkApp.Check(txs[i])
if !x.IsOK() {
_, _, err := benchmarkApp.Check(txs[i])
if err != nil {
panic("something is broken in checking transaction")
}
benchmarkApp.Deliver(txs[i])
benchmarkApp.EndBlock(abci.RequestEndBlock{})
benchmarkApp.Commit()

View File

@ -1,16 +1,15 @@
package bank
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/bank/internal/keeper"
"github.com/cosmos/cosmos-sdk/x/bank/internal/types"
)
// NewHandler returns a handler for "bank" type messages.
func NewHandler(k keeper.Keeper) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
ctx = ctx.WithEventManager(sdk.NewEventManager())
switch msg := msg.(type) {
@ -21,25 +20,24 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
return handleMsgMultiSend(ctx, k, msg)
default:
errMsg := fmt.Sprintf("unrecognized bank message type: %T", msg)
return sdk.ErrUnknownRequest(errMsg).Result()
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized bank message type: %T", msg)
}
}
}
// Handle MsgSend.
func handleMsgSend(ctx sdk.Context, k keeper.Keeper, msg types.MsgSend) sdk.Result {
func handleMsgSend(ctx sdk.Context, k keeper.Keeper, msg types.MsgSend) (*sdk.Result, error) {
if !k.GetSendEnabled(ctx) {
return types.ErrSendDisabled(k.Codespace()).Result()
return nil, types.ErrSendDisabled
}
if k.BlacklistedAddr(msg.ToAddress) {
return sdk.ErrUnauthorized(fmt.Sprintf("%s is not allowed to receive transactions", msg.ToAddress)).Result()
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive transactions", msg.ToAddress)
}
err := k.SendCoins(ctx, msg.FromAddress, msg.ToAddress, msg.Amount)
if err != nil {
return err.Result()
return nil, err
}
ctx.EventManager().EmitEvent(
@ -49,25 +47,25 @@ func handleMsgSend(ctx sdk.Context, k keeper.Keeper, msg types.MsgSend) sdk.Resu
),
)
return sdk.Result{Events: ctx.EventManager().Events()}
return &sdk.Result{Events: ctx.EventManager().Events()}, nil
}
// Handle MsgMultiSend.
func handleMsgMultiSend(ctx sdk.Context, k keeper.Keeper, msg types.MsgMultiSend) sdk.Result {
func handleMsgMultiSend(ctx sdk.Context, k keeper.Keeper, msg types.MsgMultiSend) (*sdk.Result, error) {
// NOTE: totalIn == totalOut should already have been checked
if !k.GetSendEnabled(ctx) {
return types.ErrSendDisabled(k.Codespace()).Result()
return nil, types.ErrSendDisabled
}
for _, out := range msg.Outputs {
if k.BlacklistedAddr(out.Address) {
return sdk.ErrUnauthorized(fmt.Sprintf("%s is not allowed to receive transactions", out.Address)).Result()
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive transactions", out.Address)
}
}
err := k.InputOutputCoins(ctx, msg.Inputs, msg.Outputs)
if err != nil {
return err.Result()
return nil, err
}
ctx.EventManager().EmitEvent(
@ -77,5 +75,5 @@ func handleMsgMultiSend(ctx sdk.Context, k keeper.Keeper, msg types.MsgMultiSend
),
)
return sdk.Result{Events: ctx.EventManager().Events()}
return &sdk.Result{Events: ctx.EventManager().Events()}, nil
}

View File

@ -4,17 +4,20 @@ import (
"strings"
"testing"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
func TestInvalidMsg(t *testing.T) {
h := NewHandler(nil)
res := h(sdk.NewContext(nil, abci.Header{}, false, nil), sdk.NewTestMsg())
require.False(t, res.IsOK())
require.True(t, strings.Contains(res.Log, "unrecognized bank message type"))
res, err := h(sdk.NewContext(nil, abci.Header{}, false, nil), sdk.NewTestMsg())
require.Error(t, err)
require.Nil(t, res)
_, _, log := sdkerrors.ABCIInfo(err, false)
require.True(t, strings.Contains(log, "unrecognized bank message type"))
}

View File

@ -7,6 +7,7 @@ import (
"github.com/tendermint/tendermint/libs/log"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
vestexported "github.com/cosmos/cosmos-sdk/x/auth/vesting/exported"
"github.com/cosmos/cosmos-sdk/x/bank/internal/types"
@ -20,8 +21,8 @@ var _ Keeper = (*BaseKeeper)(nil)
type Keeper interface {
SendKeeper
DelegateCoins(ctx sdk.Context, delegatorAddr, moduleAccAddr sdk.AccAddress, amt sdk.Coins) sdk.Error
UndelegateCoins(ctx sdk.Context, moduleAccAddr, delegatorAddr sdk.AccAddress, amt sdk.Coins) sdk.Error
DelegateCoins(ctx sdk.Context, delegatorAddr, moduleAccAddr sdk.AccAddress, amt sdk.Coins) error
UndelegateCoins(ctx sdk.Context, moduleAccAddr, delegatorAddr sdk.AccAddress, amt sdk.Coins) error
}
// BaseKeeper manages transfers between accounts. It implements the Keeper interface.
@ -33,13 +34,13 @@ type BaseKeeper struct {
}
// NewBaseKeeper returns a new BaseKeeper
func NewBaseKeeper(ak types.AccountKeeper,
paramSpace params.Subspace,
codespace sdk.CodespaceType, blacklistedAddrs map[string]bool) BaseKeeper {
func NewBaseKeeper(
ak types.AccountKeeper, paramSpace params.Subspace, blacklistedAddrs map[string]bool,
) BaseKeeper {
ps := paramSpace.WithKeyTable(types.ParamKeyTable())
return BaseKeeper{
BaseSendKeeper: NewBaseSendKeeper(ak, ps, codespace, blacklistedAddrs),
BaseSendKeeper: NewBaseSendKeeper(ak, ps, blacklistedAddrs),
ak: ak,
paramSpace: ps,
}
@ -50,33 +51,32 @@ func NewBaseKeeper(ak types.AccountKeeper,
// vesting and vested coins.
// The coins are then transferred from the delegator address to a ModuleAccount address.
// If any of the delegation amounts are negative, an error is returned.
func (keeper BaseKeeper) DelegateCoins(ctx sdk.Context, delegatorAddr, moduleAccAddr sdk.AccAddress, amt sdk.Coins) sdk.Error {
func (keeper BaseKeeper) DelegateCoins(ctx sdk.Context, delegatorAddr, moduleAccAddr sdk.AccAddress, amt sdk.Coins) error {
delegatorAcc := keeper.ak.GetAccount(ctx, delegatorAddr)
if delegatorAcc == nil {
return sdk.ErrUnknownAddress(fmt.Sprintf("account %s does not exist", delegatorAddr))
return sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "account %s does not exist", delegatorAddr)
}
moduleAcc := keeper.ak.GetAccount(ctx, moduleAccAddr)
if moduleAcc == nil {
return sdk.ErrUnknownAddress(fmt.Sprintf("module account %s does not exist", moduleAccAddr))
return sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", moduleAccAddr)
}
if !amt.IsValid() {
return sdk.ErrInvalidCoins(amt.String())
return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, amt.String())
}
oldCoins := delegatorAcc.GetCoins()
_, hasNeg := oldCoins.SafeSub(amt)
if hasNeg {
return sdk.ErrInsufficientCoins(
fmt.Sprintf("insufficient account funds; %s < %s", oldCoins, amt),
return sdkerrors.Wrapf(
sdkerrors.ErrInsufficientFunds, "insufficient account funds; %s < %s", oldCoins, amt,
)
}
if err := trackDelegation(delegatorAcc, ctx.BlockHeader().Time, amt); err != nil {
return sdk.ErrInternal(fmt.Sprintf("failed to track delegation: %v", err))
return sdkerrors.Wrap(err, "failed to track delegation")
}
keeper.ak.SetAccount(ctx, delegatorAcc)
@ -94,28 +94,27 @@ func (keeper BaseKeeper) DelegateCoins(ctx sdk.Context, delegatorAddr, moduleAcc
// vesting and vested coins.
// The coins are then transferred from a ModuleAccount address to the delegator address.
// If any of the undelegation amounts are negative, an error is returned.
func (keeper BaseKeeper) UndelegateCoins(ctx sdk.Context, moduleAccAddr, delegatorAddr sdk.AccAddress, amt sdk.Coins) sdk.Error {
func (keeper BaseKeeper) UndelegateCoins(ctx sdk.Context, moduleAccAddr, delegatorAddr sdk.AccAddress, amt sdk.Coins) error {
delegatorAcc := keeper.ak.GetAccount(ctx, delegatorAddr)
if delegatorAcc == nil {
return sdk.ErrUnknownAddress(fmt.Sprintf("account %s does not exist", delegatorAddr))
return sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "account %s does not exist", delegatorAddr)
}
moduleAcc := keeper.ak.GetAccount(ctx, moduleAccAddr)
if moduleAcc == nil {
return sdk.ErrUnknownAddress(fmt.Sprintf("module account %s does not exist", moduleAccAddr))
return sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "module account %s does not exist", moduleAccAddr)
}
if !amt.IsValid() {
return sdk.ErrInvalidCoins(amt.String())
return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, amt.String())
}
oldCoins := moduleAcc.GetCoins()
newCoins, hasNeg := oldCoins.SafeSub(amt)
if hasNeg {
return sdk.ErrInsufficientCoins(
fmt.Sprintf("insufficient account funds; %s < %s", oldCoins, amt),
return sdkerrors.Wrapf(
sdkerrors.ErrInsufficientFunds, "insufficient account funds; %s < %s", oldCoins, amt,
)
}
@ -125,7 +124,7 @@ func (keeper BaseKeeper) UndelegateCoins(ctx sdk.Context, moduleAccAddr, delegat
}
if err := trackUndelegation(delegatorAcc, amt); err != nil {
return sdk.ErrInternal(fmt.Sprintf("failed to track undelegation: %v", err))
return sdkerrors.Wrap(err, "failed to track undelegation")
}
keeper.ak.SetAccount(ctx, delegatorAcc)
@ -137,12 +136,12 @@ func (keeper BaseKeeper) UndelegateCoins(ctx sdk.Context, moduleAccAddr, delegat
type SendKeeper interface {
ViewKeeper
InputOutputCoins(ctx sdk.Context, inputs []types.Input, outputs []types.Output) sdk.Error
SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) sdk.Error
InputOutputCoins(ctx sdk.Context, inputs []types.Input, outputs []types.Output) error
SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error
SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Error)
AddCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Error)
SetCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) sdk.Error
SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, error)
AddCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, error)
SetCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) error
GetSendEnabled(ctx sdk.Context) bool
SetSendEnabled(ctx sdk.Context, enabled bool)
@ -165,11 +164,12 @@ type BaseSendKeeper struct {
}
// NewBaseSendKeeper returns a new BaseSendKeeper.
func NewBaseSendKeeper(ak types.AccountKeeper,
paramSpace params.Subspace, codespace sdk.CodespaceType, blacklistedAddrs map[string]bool) BaseSendKeeper {
func NewBaseSendKeeper(
ak types.AccountKeeper, paramSpace params.Subspace, blacklistedAddrs map[string]bool,
) BaseSendKeeper {
return BaseSendKeeper{
BaseViewKeeper: NewBaseViewKeeper(ak, codespace),
BaseViewKeeper: NewBaseViewKeeper(ak),
ak: ak,
paramSpace: paramSpace,
blacklistedAddrs: blacklistedAddrs,
@ -177,7 +177,7 @@ func NewBaseSendKeeper(ak types.AccountKeeper,
}
// InputOutputCoins handles a list of inputs and outputs
func (keeper BaseSendKeeper) InputOutputCoins(ctx sdk.Context, inputs []types.Input, outputs []types.Output) sdk.Error {
func (keeper BaseSendKeeper) InputOutputCoins(ctx sdk.Context, inputs []types.Input, outputs []types.Output) error {
// Safety check ensuring that when sending coins the keeper must maintain the
// Check supply invariant and validity of Coins.
if err := types.ValidateInputsOutputs(inputs, outputs); err != nil {
@ -216,7 +216,7 @@ func (keeper BaseSendKeeper) InputOutputCoins(ctx sdk.Context, inputs []types.In
}
// SendCoins moves coins from one account to another
func (keeper BaseSendKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) sdk.Error {
func (keeper BaseSendKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error {
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeTransfer,
@ -245,10 +245,9 @@ func (keeper BaseSendKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress,
// SubtractCoins subtracts amt from the coins at the addr.
//
// CONTRACT: If the account is a vesting account, the amount has to be spendable.
func (keeper BaseSendKeeper) SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Error) {
func (keeper BaseSendKeeper) SubtractCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, error) {
if !amt.IsValid() {
return nil, sdk.ErrInvalidCoins(amt.String())
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, amt.String())
}
oldCoins, spendableCoins := sdk.NewCoins(), sdk.NewCoins()
@ -263,8 +262,8 @@ func (keeper BaseSendKeeper) SubtractCoins(ctx sdk.Context, addr sdk.AccAddress,
// So the check here is sufficient instead of subtracting from oldCoins.
_, hasNeg := spendableCoins.SafeSub(amt)
if hasNeg {
return amt, sdk.ErrInsufficientCoins(
fmt.Sprintf("insufficient account funds; %s < %s", spendableCoins, amt),
return amt, sdkerrors.Wrapf(
sdkerrors.ErrInsufficientFunds, "insufficient account funds; %s < %s", spendableCoins, amt,
)
}
@ -275,18 +274,17 @@ func (keeper BaseSendKeeper) SubtractCoins(ctx sdk.Context, addr sdk.AccAddress,
}
// AddCoins adds amt to the coins at the addr.
func (keeper BaseSendKeeper) AddCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, sdk.Error) {
func (keeper BaseSendKeeper) AddCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Coins, error) {
if !amt.IsValid() {
return nil, sdk.ErrInvalidCoins(amt.String())
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, amt.String())
}
oldCoins := keeper.GetCoins(ctx, addr)
newCoins := oldCoins.Add(amt)
if newCoins.IsAnyNegative() {
return amt, sdk.ErrInsufficientCoins(
fmt.Sprintf("insufficient account funds; %s < %s", oldCoins, amt),
return amt, sdkerrors.Wrapf(
sdkerrors.ErrInsufficientFunds, "insufficient account funds; %s < %s", oldCoins, amt,
)
}
@ -295,10 +293,9 @@ func (keeper BaseSendKeeper) AddCoins(ctx sdk.Context, addr sdk.AccAddress, amt
}
// SetCoins sets the coins at the addr.
func (keeper BaseSendKeeper) SetCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) sdk.Error {
func (keeper BaseSendKeeper) SetCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) error {
if !amt.IsValid() {
return sdk.ErrInvalidCoins(amt.String())
sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, amt.String())
}
acc := keeper.ak.GetAccount(ctx, addr)
@ -340,19 +337,16 @@ var _ ViewKeeper = (*BaseViewKeeper)(nil)
type ViewKeeper interface {
GetCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
HasCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) bool
Codespace() sdk.CodespaceType
}
// BaseViewKeeper implements a read only keeper implementation of ViewKeeper.
type BaseViewKeeper struct {
ak types.AccountKeeper
codespace sdk.CodespaceType
ak types.AccountKeeper
}
// NewBaseViewKeeper returns a new BaseViewKeeper.
func NewBaseViewKeeper(ak types.AccountKeeper, codespace sdk.CodespaceType) BaseViewKeeper {
return BaseViewKeeper{ak: ak, codespace: codespace}
func NewBaseViewKeeper(ak types.AccountKeeper) BaseViewKeeper {
return BaseViewKeeper{ak: ak}
}
// Logger returns a module-specific logger.
@ -374,11 +368,6 @@ func (keeper BaseViewKeeper) HasCoins(ctx sdk.Context, addr sdk.AccAddress, amt
return keeper.GetCoins(ctx, addr).IsAllGTE(amt)
}
// Codespace returns the keeper's codespace.
func (keeper BaseViewKeeper) Codespace() sdk.CodespaceType {
return keeper.codespace
}
// CONTRACT: assumes that amt is valid.
func trackDelegation(acc authexported.Account, blockTime time.Time, amt sdk.Coins) error {
vacc, ok := acc.(vestexported.VestingAccount)

View File

@ -65,8 +65,7 @@ func TestKeeper(t *testing.T) {
require.True(t, app.BankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
require.True(t, app.BankKeeper.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5))))
err2 := app.BankKeeper.SendCoins(ctx, addr, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 50)))
require.Implements(t, (*sdk.Error)(nil), err2)
app.BankKeeper.SendCoins(ctx, addr, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 50)))
require.True(t, app.BankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
require.True(t, app.BankKeeper.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5))))
@ -109,7 +108,7 @@ func TestSendKeeper(t *testing.T) {
blacklistedAddrs := make(map[string]bool)
paramSpace := app.ParamsKeeper.Subspace("newspace")
sendKeeper := keep.NewBaseSendKeeper(app.AccountKeeper, paramSpace, types.DefaultCodespace, blacklistedAddrs)
sendKeeper := keep.NewBaseSendKeeper(app.AccountKeeper, paramSpace, blacklistedAddrs)
app.BankKeeper.SetSendEnabled(ctx, true)
addr := sdk.AccAddress([]byte("addr1"))
@ -136,8 +135,7 @@ func TestSendKeeper(t *testing.T) {
require.True(t, sendKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
require.True(t, sendKeeper.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5))))
err := sendKeeper.SendCoins(ctx, addr, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 50)))
require.Implements(t, (*sdk.Error)(nil), err)
sendKeeper.SendCoins(ctx, addr, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 50)))
require.True(t, sendKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
require.True(t, sendKeeper.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5))))
@ -149,7 +147,7 @@ func TestSendKeeper(t *testing.T) {
// validate coins with invalid denoms or negative values cannot be sent
// NOTE: We must use the Coin literal as the constructor does not allow
// negative values.
err = sendKeeper.SendCoins(ctx, addr, addr2, sdk.Coins{sdk.Coin{Denom: "FOOCOIN", Amount: sdk.NewInt(-5)}})
err := sendKeeper.SendCoins(ctx, addr, addr2, sdk.Coins{sdk.Coin{Denom: "FOOCOIN", Amount: sdk.NewInt(-5)}})
require.Error(t, err)
}
@ -202,7 +200,7 @@ func TestViewKeeper(t *testing.T) {
app, ctx := createTestApp(false)
//paramSpace := app.ParamsKeeper.Subspace(types.DefaultParamspace)
viewKeeper := keep.NewBaseViewKeeper(app.AccountKeeper, types.DefaultCodespace)
viewKeeper := keep.NewBaseViewKeeper(app.AccountKeeper)
addr := sdk.AccAddress([]byte("addr1"))
acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr)

View File

@ -1,12 +1,11 @@
package keeper
import (
"fmt"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/bank/internal/types"
)
@ -17,24 +16,24 @@ const (
// NewQuerier returns a new sdk.Keeper instance.
func NewQuerier(k Keeper) sdk.Querier {
return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, sdk.Error) {
return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) {
switch path[0] {
case QueryBalance:
return queryBalance(ctx, req, k)
default:
return nil, sdk.ErrUnknownRequest("unknown bank query endpoint")
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown query path: %s", path[0])
}
}
}
// queryBalance fetch an account's balance for the supplied height.
// Height and account address are passed as first and second path components respectively.
func queryBalance(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) {
func queryBalance(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) {
var params types.QueryBalanceParams
if err := types.ModuleCdc.UnmarshalJSON(req.Data, &params); err != nil {
return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
coins := k.GetCoins(ctx, params.Address)
@ -44,7 +43,7 @@ func queryBalance(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk
bz, err := codec.MarshalJSONIndent(types.ModuleCdc, coins)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil

View File

@ -1,33 +1,13 @@
package types
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
// Bank errors reserve 100 ~ 199.
const (
DefaultCodespace sdk.CodespaceType = ModuleName
CodeSendDisabled sdk.CodeType = 101
CodeInvalidInputsOutputs sdk.CodeType = 102
// x/bank module sentinel errors
var (
ErrNoInputs = sdkerrors.Register(ModuleName, 1, "no inputs to send transaction")
ErrNoOutputs = sdkerrors.Register(ModuleName, 2, "no outputs to send transaction")
ErrInputOutputMismatch = sdkerrors.Register(ModuleName, 3, "sum inputs != sum outputs")
ErrSendDisabled = sdkerrors.Register(ModuleName, 4, "send transactions are disabled")
)
// ErrNoInputs is an error
func ErrNoInputs(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidInputsOutputs, "no inputs to send transaction")
}
// ErrNoOutputs is an error
func ErrNoOutputs(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidInputsOutputs, "no outputs to send transaction")
}
// ErrInputOutputMismatch is an error
func ErrInputOutputMismatch(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidInputsOutputs, "sum inputs != sum outputs")
}
// ErrSendDisabled is an error
func ErrSendDisabled(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeSendDisabled, "send transactions are currently disabled")
}

View File

@ -2,6 +2,7 @@ package types
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
// RouterKey is they name of the bank module
@ -28,18 +29,18 @@ func (msg MsgSend) Route() string { return RouterKey }
func (msg MsgSend) Type() string { return "send" }
// ValidateBasic Implements Msg.
func (msg MsgSend) ValidateBasic() sdk.Error {
func (msg MsgSend) ValidateBasic() error {
if msg.FromAddress.Empty() {
return sdk.ErrInvalidAddress("missing sender address")
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing sender address")
}
if msg.ToAddress.Empty() {
return sdk.ErrInvalidAddress("missing recipient address")
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing recipient address")
}
if !msg.Amount.IsValid() {
return sdk.ErrInvalidCoins("send amount is invalid: " + msg.Amount.String())
return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, msg.Amount.String())
}
if !msg.Amount.IsAllPositive() {
return sdk.ErrInsufficientCoins("send amount must be positive")
return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, msg.Amount.String())
}
return nil
}
@ -74,14 +75,14 @@ func (msg MsgMultiSend) Route() string { return RouterKey }
func (msg MsgMultiSend) Type() string { return "multisend" }
// ValidateBasic Implements Msg.
func (msg MsgMultiSend) ValidateBasic() sdk.Error {
func (msg MsgMultiSend) ValidateBasic() error {
// this just makes sure all the inputs and outputs are properly formatted,
// not that they actually have the money inside
if len(msg.Inputs) == 0 {
return ErrNoInputs(DefaultCodespace).TraceSDK("")
return ErrNoInputs
}
if len(msg.Outputs) == 0 {
return ErrNoOutputs(DefaultCodespace).TraceSDK("")
return ErrNoOutputs
}
return ValidateInputsOutputs(msg.Inputs, msg.Outputs)
@ -108,15 +109,15 @@ type Input struct {
}
// ValidateBasic - validate transaction input
func (in Input) ValidateBasic() sdk.Error {
func (in Input) ValidateBasic() error {
if len(in.Address) == 0 {
return sdk.ErrInvalidAddress(in.Address.String())
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "input address missing")
}
if !in.Coins.IsValid() {
return sdk.ErrInvalidCoins(in.Coins.String())
return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, in.Coins.String())
}
if !in.Coins.IsAllPositive() {
return sdk.ErrInvalidCoins(in.Coins.String())
return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, in.Coins.String())
}
return nil
}
@ -136,15 +137,15 @@ type Output struct {
}
// ValidateBasic - validate transaction output
func (out Output) ValidateBasic() sdk.Error {
func (out Output) ValidateBasic() error {
if len(out.Address) == 0 {
return sdk.ErrInvalidAddress(out.Address.String())
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "output address missing")
}
if !out.Coins.IsValid() {
return sdk.ErrInvalidCoins(out.Coins.String())
return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, out.Coins.String())
}
if !out.Coins.IsAllPositive() {
return sdk.ErrInvalidCoins(out.Coins.String())
return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, out.Coins.String())
}
return nil
}
@ -159,26 +160,28 @@ func NewOutput(addr sdk.AccAddress, coins sdk.Coins) Output {
// ValidateInputsOutputs validates that each respective input and output is
// valid and that the sum of inputs is equal to the sum of outputs.
func ValidateInputsOutputs(inputs []Input, outputs []Output) sdk.Error {
func ValidateInputsOutputs(inputs []Input, outputs []Output) error {
var totalIn, totalOut sdk.Coins
for _, in := range inputs {
if err := in.ValidateBasic(); err != nil {
return err.TraceSDK("")
return err
}
totalIn = totalIn.Add(in.Coins)
}
for _, out := range outputs {
if err := out.ValidateBasic(); err != nil {
return err.TraceSDK("")
return err
}
totalOut = totalOut.Add(out.Coins)
}
// make sure inputs and outputs match
if !totalIn.IsEqual(totalOut) {
return ErrInputOutputMismatch(DefaultCodespace)
return ErrInputOutputMismatch
}
return nil

View File

@ -1,7 +1,6 @@
package simulation
import (
"errors"
"math/rand"
"github.com/tendermint/tendermint/crypto"
@ -115,9 +114,9 @@ func sendMsgSend(
privkeys...,
)
res := app.Deliver(tx)
if !res.IsOK() {
return errors.New(res.Log)
_, _, err = app.Deliver(tx)
if err != nil {
return err
}
return nil
@ -259,9 +258,9 @@ func sendMsgMultiSend(
privkeys...,
)
res := app.Deliver(tx)
if !res.IsOK() {
return errors.New(res.Log)
_, _, err = app.Deliver(tx)
if err != nil {
return err
}
return nil

View File

@ -1,38 +1,30 @@
// nolint
// autogenerated code using github.com/rigelrozanski/multitool
// aliases generated for the following subdirectories:
// ALIASGEN: github.com/cosmos/cosmos-sdk/x/crisis/types
package crisis
// nolint
import (
"github.com/cosmos/cosmos-sdk/x/crisis/internal/keeper"
"github.com/cosmos/cosmos-sdk/x/crisis/internal/types"
)
const (
DefaultCodespace = types.DefaultCodespace
CodeInvalidInput = types.CodeInvalidInput
ModuleName = types.ModuleName
DefaultParamspace = types.DefaultParamspace
ModuleName = types.ModuleName
DefaultParamspace = types.DefaultParamspace
EventTypeInvariant = types.EventTypeInvariant
AttributeValueCrisis = types.AttributeValueCrisis
AttributeKeyRoute = types.AttributeKeyRoute
)
var (
// functions aliases
RegisterCodec = types.RegisterCodec
ErrNilSender = types.ErrNilSender
ErrUnknownInvariant = types.ErrUnknownInvariant
NewGenesisState = types.NewGenesisState
DefaultGenesisState = types.DefaultGenesisState
NewMsgVerifyInvariant = types.NewMsgVerifyInvariant
ParamKeyTable = types.ParamKeyTable
NewInvarRoute = types.NewInvarRoute
NewKeeper = keeper.NewKeeper
// variable aliases
RegisterCodec = types.RegisterCodec
ErrNoSender = types.ErrNoSender
ErrUnknownInvariant = types.ErrUnknownInvariant
NewGenesisState = types.NewGenesisState
DefaultGenesisState = types.DefaultGenesisState
NewMsgVerifyInvariant = types.NewMsgVerifyInvariant
ParamKeyTable = types.ParamKeyTable
NewInvarRoute = types.NewInvarRoute
NewKeeper = keeper.NewKeeper
ModuleCdc = types.ModuleCdc
ParamStoreKeyConstantFee = types.ParamStoreKeyConstantFee
)

View File

@ -1,9 +1,8 @@
package crisis
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/crisis/internal/keeper"
"github.com/cosmos/cosmos-sdk/x/crisis/internal/types"
)
@ -12,7 +11,7 @@ import (
const RouterKey = types.ModuleName
func NewHandler(k keeper.Keeper) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
ctx = ctx.WithEventManager(sdk.NewEventManager())
switch msg := msg.(type) {
@ -20,18 +19,16 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
return handleMsgVerifyInvariant(ctx, msg, k)
default:
errMsg := fmt.Sprintf("unrecognized crisis message type: %T", msg)
return sdk.ErrUnknownRequest(errMsg).Result()
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized crisis message type: %T", msg)
}
}
}
func handleMsgVerifyInvariant(ctx sdk.Context, msg types.MsgVerifyInvariant, k keeper.Keeper) sdk.Result {
// remove the constant fee
func handleMsgVerifyInvariant(ctx sdk.Context, msg types.MsgVerifyInvariant, k keeper.Keeper) (*sdk.Result, error) {
constantFee := sdk.NewCoins(k.GetConstantFee(ctx))
if err := k.SendCoinsFromAccountToFeeCollector(ctx, msg.Sender, constantFee); err != nil {
return err.Result()
return nil, err
}
// use a cached context to avoid gas costs during invariants
@ -51,7 +48,7 @@ func handleMsgVerifyInvariant(ctx sdk.Context, msg types.MsgVerifyInvariant, k k
}
if !found {
return types.ErrUnknownInvariant(types.DefaultCodespace).Result()
return nil, types.ErrUnknownInvariant
}
if stop {
@ -86,5 +83,5 @@ func handleMsgVerifyInvariant(ctx sdk.Context, msg types.MsgVerifyInvariant, k k
),
})
return sdk.Result{Events: ctx.EventManager().Events()}
return &sdk.Result{Events: ctx.EventManager().Events()}, nil
}

View File

@ -69,14 +69,18 @@ func TestHandleMsgVerifyInvariant(t *testing.T) {
switch tc.expectedResult {
case "fail":
res := h(ctx, tc.msg)
require.False(t, res.IsOK())
res, err := h(ctx, tc.msg)
require.Error(t, err)
require.Nil(t, res)
case "pass":
res := h(ctx, tc.msg)
require.True(t, res.IsOK())
res, err := h(ctx, tc.msg)
require.NoError(t, err)
require.NotNil(t, res)
case "panic":
require.Panics(t, func() {
_ = h(ctx, tc.msg)
h(ctx, tc.msg)
})
}
})
@ -92,7 +96,10 @@ func TestHandleMsgVerifyInvariantWithNotEnoughSenderCoins(t *testing.T) {
h := crisis.NewHandler(app.CrisisKeeper)
msg := crisis.NewMsgVerifyInvariant(sender, testModuleName, dummyRouteWhichPasses.Route)
require.False(t, h(ctx, msg).IsOK())
res, err := h(ctx, msg)
require.Error(t, err)
require.Nil(t, res)
}
func TestHandleMsgVerifyInvariantWithInvariantBrokenAndNotEnoughPoolCoins(t *testing.T) {
@ -106,8 +113,9 @@ func TestHandleMsgVerifyInvariantWithInvariantBrokenAndNotEnoughPoolCoins(t *tes
h := crisis.NewHandler(app.CrisisKeeper)
msg := crisis.NewMsgVerifyInvariant(sender, testModuleName, dummyRouteWhichFails.Route)
var res sdk.Result
var res *sdk.Result
require.Panics(t, func() {
res = h(ctx, msg)
res, _ = h(ctx, msg)
}, fmt.Sprintf("%v", res))
}

View File

@ -90,6 +90,6 @@ func (k Keeper) AssertInvariants(ctx sdk.Context) {
func (k Keeper) InvCheckPeriod() uint { return k.invCheckPeriod }
// SendCoinsFromAccountToFeeCollector transfers amt to the fee collector account.
func (k Keeper) SendCoinsFromAccountToFeeCollector(ctx sdk.Context, senderAddr sdk.AccAddress, amt sdk.Coins) sdk.Error {
func (k Keeper) SendCoinsFromAccountToFeeCollector(ctx sdk.Context, senderAddr sdk.AccAddress, amt sdk.Coins) error {
return k.supplyKeeper.SendCoinsFromAccountToModule(ctx, senderAddr, k.feeCollectorName, amt)
}

View File

@ -1,23 +1,11 @@
package types
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
const (
// default codespace for crisis module
DefaultCodespace sdk.CodespaceType = ModuleName
// CodeInvalidInput is the codetype for invalid input for the crisis module
CodeInvalidInput sdk.CodeType = 103
// x/crisis module sentinel errors
var (
ErrNoSender = sdkerrors.Register(ModuleName, 1, "sender address is empty")
ErrUnknownInvariant = sdkerrors.Register(ModuleName, 2, "unknown invariant")
)
// ErrNilSender - no sender provided for the input
func ErrNilSender(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidInput, "sender address is nil")
}
// ErrUnknownInvariant - unknown invariant provided
func ErrUnknownInvariant(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidInput, "unknown invariant")
}

View File

@ -6,5 +6,5 @@ import (
// SupplyKeeper defines the expected supply keeper (noalias)
type SupplyKeeper interface {
SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) sdk.Error
SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
}

View File

@ -39,9 +39,9 @@ func (msg MsgVerifyInvariant) GetSignBytes() []byte {
}
// quick validity check
func (msg MsgVerifyInvariant) ValidateBasic() sdk.Error {
func (msg MsgVerifyInvariant) ValidateBasic() error {
if msg.Sender.Empty() {
return ErrNilSender(DefaultCodespace)
return ErrNoSender
}
return nil
}

View File

@ -10,11 +10,6 @@ import (
const (
DefaultParamspace = keeper.DefaultParamspace
DefaultCodespace = types.DefaultCodespace
CodeInvalidInput = types.CodeInvalidInput
CodeNoDistributionInfo = types.CodeNoDistributionInfo
CodeNoValidatorCommission = types.CodeNoValidatorCommission
CodeSetWithdrawAddrDisabled = types.CodeSetWithdrawAddrDisabled
ModuleName = types.ModuleName
StoreKey = types.StoreKey
RouterKey = types.RouterKey
@ -70,11 +65,13 @@ var (
CreateTestInputAdvanced = keeper.CreateTestInputAdvanced
RegisterCodec = types.RegisterCodec
NewDelegatorStartingInfo = types.NewDelegatorStartingInfo
ErrNilDelegatorAddr = types.ErrNilDelegatorAddr
ErrNilWithdrawAddr = types.ErrNilWithdrawAddr
ErrNilValidatorAddr = types.ErrNilValidatorAddr
ErrNoDelegationDistInfo = types.ErrNoDelegationDistInfo
ErrEmptyDelegatorAddr = types.ErrEmptyDelegatorAddr
ErrEmptyWithdrawAddr = types.ErrEmptyWithdrawAddr
ErrEmptyValidatorAddr = types.ErrEmptyValidatorAddr
ErrEmptyDelegationDistInfo = types.ErrEmptyDelegationDistInfo
ErrNoValidatorDistInfo = types.ErrNoValidatorDistInfo
ErrNoValidatorExists = types.ErrNoValidatorExists
ErrNoDelegationExists = types.ErrNoDelegationExists
ErrNoValidatorCommission = types.ErrNoValidatorCommission
ErrSetWithdrawAddrDisabled = types.ErrSetWithdrawAddrDisabled
ErrBadDistribution = types.ErrBadDistribution
@ -134,7 +131,6 @@ type (
Hooks = keeper.Hooks
Keeper = keeper.Keeper
DelegatorStartingInfo = types.DelegatorStartingInfo
CodeType = types.CodeType
FeePool = types.FeePool
DelegatorWithdrawInfo = types.DelegatorWithdrawInfo
ValidatorOutstandingRewardsRecord = types.ValidatorOutstandingRewardsRecord

View File

@ -1,16 +1,15 @@
package distribution
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/distribution/keeper"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
)
func NewHandler(k keeper.Keeper) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
ctx = ctx.WithEventManager(sdk.NewEventManager())
switch msg := msg.(type) {
@ -27,18 +26,17 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
return handleMsgFundCommunityPool(ctx, msg, k)
default:
errMsg := fmt.Sprintf("unrecognized distribution message type: %T", msg)
return sdk.ErrUnknownRequest(errMsg).Result()
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized distribution message type: %T", msg)
}
}
}
// These functions assume everything has been authenticated (ValidateBasic passed, and signatures checked)
func handleMsgModifyWithdrawAddress(ctx sdk.Context, msg types.MsgSetWithdrawAddress, k keeper.Keeper) sdk.Result {
func handleMsgModifyWithdrawAddress(ctx sdk.Context, msg types.MsgSetWithdrawAddress, k keeper.Keeper) (*sdk.Result, error) {
err := k.SetWithdrawAddr(ctx, msg.DelegatorAddress, msg.WithdrawAddress)
if err != nil {
return err.Result()
return nil, err
}
ctx.EventManager().EmitEvent(
@ -49,13 +47,13 @@ func handleMsgModifyWithdrawAddress(ctx sdk.Context, msg types.MsgSetWithdrawAdd
),
)
return sdk.Result{Events: ctx.EventManager().Events()}
return &sdk.Result{Events: ctx.EventManager().Events()}, nil
}
func handleMsgWithdrawDelegatorReward(ctx sdk.Context, msg types.MsgWithdrawDelegatorReward, k keeper.Keeper) sdk.Result {
func handleMsgWithdrawDelegatorReward(ctx sdk.Context, msg types.MsgWithdrawDelegatorReward, k keeper.Keeper) (*sdk.Result, error) {
_, err := k.WithdrawDelegationRewards(ctx, msg.DelegatorAddress, msg.ValidatorAddress)
if err != nil {
return err.Result()
return nil, err
}
ctx.EventManager().EmitEvent(
@ -66,13 +64,13 @@ func handleMsgWithdrawDelegatorReward(ctx sdk.Context, msg types.MsgWithdrawDele
),
)
return sdk.Result{Events: ctx.EventManager().Events()}
return &sdk.Result{Events: ctx.EventManager().Events()}, nil
}
func handleMsgWithdrawValidatorCommission(ctx sdk.Context, msg types.MsgWithdrawValidatorCommission, k keeper.Keeper) sdk.Result {
func handleMsgWithdrawValidatorCommission(ctx sdk.Context, msg types.MsgWithdrawValidatorCommission, k keeper.Keeper) (*sdk.Result, error) {
_, err := k.WithdrawValidatorCommission(ctx, msg.ValidatorAddress)
if err != nil {
return err.Result()
return nil, err
}
ctx.EventManager().EmitEvent(
@ -83,12 +81,12 @@ func handleMsgWithdrawValidatorCommission(ctx sdk.Context, msg types.MsgWithdraw
),
)
return sdk.Result{Events: ctx.EventManager().Events()}
return &sdk.Result{Events: ctx.EventManager().Events()}, nil
}
func handleMsgFundCommunityPool(ctx sdk.Context, msg types.MsgFundCommunityPool, k keeper.Keeper) sdk.Result {
func handleMsgFundCommunityPool(ctx sdk.Context, msg types.MsgFundCommunityPool, k keeper.Keeper) (*sdk.Result, error) {
if err := k.FundCommunityPool(ctx, msg.Amount, msg.Depositor); err != nil {
return sdk.ResultFromError(err)
return nil, err
}
ctx.EventManager().EmitEvent(
@ -99,18 +97,17 @@ func handleMsgFundCommunityPool(ctx sdk.Context, msg types.MsgFundCommunityPool,
),
)
return sdk.Result{Events: ctx.EventManager().Events()}
return &sdk.Result{Events: ctx.EventManager().Events()}, nil
}
func NewCommunityPoolSpendProposalHandler(k Keeper) govtypes.Handler {
return func(ctx sdk.Context, content govtypes.Content) sdk.Error {
return func(ctx sdk.Context, content govtypes.Content) error {
switch c := content.(type) {
case types.CommunityPoolSpendProposal:
return keeper.HandleCommunityPoolSpendProposal(ctx, k, c)
default:
errMsg := fmt.Sprintf("unrecognized distr proposal content type: %T", c)
return sdk.ErrUnknownRequest(errMsg)
return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized distr proposal content type: %T", c)
}
}
}

View File

@ -16,9 +16,15 @@ func TestAllocateTokensToValidatorWithCommission(t *testing.T) {
// create validator with 50% commission
commission := staking.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
msg := staking.NewMsgCreateValidator(valOpAddr1, valConsPk1,
sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), staking.Description{}, commission, sdk.OneInt())
require.True(t, sh(ctx, msg).IsOK())
msg := staking.NewMsgCreateValidator(
valOpAddr1, valConsPk1,
sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), staking.Description{}, commission, sdk.OneInt(),
)
res, err := sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
val := sk.Validator(ctx, valOpAddr1)
// allocate tokens
@ -45,13 +51,19 @@ func TestAllocateTokensToManyValidators(t *testing.T) {
commission := staking.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
msg := staking.NewMsgCreateValidator(valOpAddr1, valConsPk1,
sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), staking.Description{}, commission, sdk.OneInt())
require.True(t, sh(ctx, msg).IsOK())
res, err := sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
// create second validator with 0% commission
commission = staking.NewCommissionRates(sdk.NewDec(0), sdk.NewDec(0), sdk.NewDec(0))
msg = staking.NewMsgCreateValidator(valOpAddr2, valConsPk2,
sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), staking.Description{}, commission, sdk.OneInt())
require.True(t, sh(ctx, msg).IsOK())
res, err = sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
abciValA := abci.Validator{
Address: valConsPk1.Address(),
@ -76,7 +88,7 @@ func TestAllocateTokensToManyValidators(t *testing.T) {
feeCollector := supplyKeeper.GetModuleAccount(ctx, k.feeCollectorName)
require.NotNil(t, feeCollector)
err := feeCollector.SetCoins(fees)
err = feeCollector.SetCoins(fees)
require.NoError(t, err)
ak.SetAccount(ctx, feeCollector)
@ -116,19 +128,25 @@ func TestAllocateTokensTruncation(t *testing.T) {
commission := staking.NewCommissionRates(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), sdk.NewDec(0))
msg := staking.NewMsgCreateValidator(valOpAddr1, valConsPk1,
sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(110)), staking.Description{}, commission, sdk.OneInt())
require.True(t, sh(ctx, msg).IsOK())
res, err := sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
// create second validator with 10% commission
commission = staking.NewCommissionRates(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), sdk.NewDec(0))
msg = staking.NewMsgCreateValidator(valOpAddr2, valConsPk2,
sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), staking.Description{}, commission, sdk.OneInt())
require.True(t, sh(ctx, msg).IsOK())
res, err = sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
// create third validator with 10% commission
commission = staking.NewCommissionRates(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(1, 1), sdk.NewDec(0))
msg = staking.NewMsgCreateValidator(valOpAddr3, valConsPk3,
sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), staking.Description{}, commission, sdk.OneInt())
require.True(t, sh(ctx, msg).IsOK())
res, err = sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
abciValA := abci.Validator{
Address: valConsPk1.Address(),
@ -159,7 +177,7 @@ func TestAllocateTokensTruncation(t *testing.T) {
feeCollector := supplyKeeper.GetModuleAccount(ctx, k.feeCollectorName)
require.NotNil(t, feeCollector)
err := feeCollector.SetCoins(fees)
err = feeCollector.SetCoins(fees)
require.NoError(t, err)
ak.SetAccount(ctx, feeCollector)

View File

@ -136,10 +136,10 @@ func (k Keeper) calculateDelegationRewards(ctx sdk.Context, val exported.Validat
return rewards
}
func (k Keeper) withdrawDelegationRewards(ctx sdk.Context, val exported.ValidatorI, del exported.DelegationI) (sdk.Coins, sdk.Error) {
func (k Keeper) withdrawDelegationRewards(ctx sdk.Context, val exported.ValidatorI, del exported.DelegationI) (sdk.Coins, error) {
// check existence of delegator starting info
if !k.HasDelegatorStartingInfo(ctx, del.GetValidatorAddr(), del.GetDelegatorAddr()) {
return nil, types.ErrNoDelegationDistInfo(k.codespace)
return nil, types.ErrEmptyDelegationDistInfo
}
// end current period and calculate rewards

View File

@ -15,9 +15,13 @@ func TestCalculateRewardsBasic(t *testing.T) {
// create validator with 50% commission
commission := staking.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
msg := staking.NewMsgCreateValidator(valOpAddr1, valConsPk1,
sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), staking.Description{}, commission, sdk.OneInt())
require.True(t, sh(ctx, msg).IsOK())
msg := staking.NewMsgCreateValidator(
valOpAddr1, valConsPk1, sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), staking.Description{}, commission, sdk.OneInt(),
)
res, err := sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
// end block to bond validator
staking.EndBlocker(ctx, sk)
@ -72,8 +76,10 @@ func TestCalculateRewardsAfterSlash(t *testing.T) {
valTokens := sdk.TokensFromConsensusPower(valPower)
msg := staking.NewMsgCreateValidator(valOpAddr1, valConsPk1,
sdk.NewCoin(sdk.DefaultBondDenom, valTokens), staking.Description{}, commission, sdk.OneInt())
got := sh(ctx, msg)
require.True(t, got.IsOK(), "%v", got)
res, err := sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
// end block to bond validator
staking.EndBlocker(ctx, sk)
@ -135,7 +141,10 @@ func TestCalculateRewardsAfterManySlashes(t *testing.T) {
commission := staking.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
msg := staking.NewMsgCreateValidator(valOpAddr1, valConsPk1,
sdk.NewCoin(sdk.DefaultBondDenom, valTokens), staking.Description{}, commission, sdk.OneInt())
require.True(t, sh(ctx, msg).IsOK())
res, err := sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
// end block to bond validator
staking.EndBlocker(ctx, sk)
@ -207,7 +216,10 @@ func TestCalculateRewardsMultiDelegator(t *testing.T) {
commission := staking.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
msg := staking.NewMsgCreateValidator(valOpAddr1, valConsPk1,
sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), staking.Description{}, commission, sdk.OneInt())
require.True(t, sh(ctx, msg).IsOK())
res, err := sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
// end block to bond validator
staking.EndBlocker(ctx, sk)
@ -226,7 +238,11 @@ func TestCalculateRewardsMultiDelegator(t *testing.T) {
// second delegation
msg2 := staking.NewMsgDelegate(sdk.AccAddress(valOpAddr2), valOpAddr1, sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)))
require.True(t, sh(ctx, msg2).IsOK())
res, err = sh(ctx, msg2)
require.NoError(t, err)
require.NotNil(t, res)
del2 := sk.Delegation(ctx, sdk.AccAddress(valOpAddr2), valOpAddr1)
// fetch updated validator
@ -280,7 +296,10 @@ func TestWithdrawDelegationRewardsBasic(t *testing.T) {
sdk.NewCoin(sdk.DefaultBondDenom, valTokens),
staking.Description{}, commission, sdk.OneInt(),
)
require.True(t, sh(ctx, msg).IsOK())
res, err := sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
// assert correct initial balance
expTokens := balanceTokens.Sub(valTokens)
@ -308,7 +327,7 @@ func TestWithdrawDelegationRewardsBasic(t *testing.T) {
require.Equal(t, uint64(2), k.GetValidatorHistoricalReferenceCount(ctx))
// withdraw rewards
_, err := k.WithdrawDelegationRewards(ctx, sdk.AccAddress(valOpAddr1), valOpAddr1)
_, err = k.WithdrawDelegationRewards(ctx, sdk.AccAddress(valOpAddr1), valOpAddr1)
require.Nil(t, err)
// historical count should still be 2 (added one record, cleared one)
@ -343,7 +362,10 @@ func TestCalculateRewardsAfterManySlashesInSameBlock(t *testing.T) {
commission := staking.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
msg := staking.NewMsgCreateValidator(valOpAddr1, valConsPk1,
sdk.NewCoin(sdk.DefaultBondDenom, valTokens), staking.Description{}, commission, sdk.OneInt())
require.True(t, sh(ctx, msg).IsOK())
res, err := sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
// end block to bond validator
staking.EndBlocker(ctx, sk)
@ -410,7 +432,10 @@ func TestCalculateRewardsMultiDelegatorMultiSlash(t *testing.T) {
valTokens := sdk.TokensFromConsensusPower(power)
msg := staking.NewMsgCreateValidator(valOpAddr1, valConsPk1,
sdk.NewCoin(sdk.DefaultBondDenom, valTokens), staking.Description{}, commission, sdk.OneInt())
require.True(t, sh(ctx, msg).IsOK())
res, err := sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
// end block to bond validator
staking.EndBlocker(ctx, sk)
@ -436,7 +461,11 @@ func TestCalculateRewardsMultiDelegatorMultiSlash(t *testing.T) {
delTokens := sdk.TokensFromConsensusPower(100)
msg2 := staking.NewMsgDelegate(sdk.AccAddress(valOpAddr2), valOpAddr1,
sdk.NewCoin(sdk.DefaultBondDenom, delTokens))
require.True(t, sh(ctx, msg2).IsOK())
res, err = sh(ctx, msg2)
require.NoError(t, err)
require.NotNil(t, res)
del2 := sk.Delegation(ctx, sdk.AccAddress(valOpAddr2), valOpAddr1)
// end block
@ -491,7 +520,10 @@ func TestCalculateRewardsMultiDelegatorMultWithdraw(t *testing.T) {
commission := staking.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
msg := staking.NewMsgCreateValidator(valOpAddr1, valConsPk1,
sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), staking.Description{}, commission, sdk.OneInt())
require.True(t, sh(ctx, msg).IsOK())
res, err := sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
// end block to bond validator
staking.EndBlocker(ctx, sk)
@ -511,7 +543,9 @@ func TestCalculateRewardsMultiDelegatorMultWithdraw(t *testing.T) {
// second delegation
msg2 := staking.NewMsgDelegate(sdk.AccAddress(valOpAddr2), valOpAddr1, sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)))
require.True(t, sh(ctx, msg2).IsOK())
res, err = sh(ctx, msg2)
require.NoError(t, err)
require.NotNil(t, res)
// historical count should be 3 (second delegation init)
require.Equal(t, uint64(3), k.GetValidatorHistoricalReferenceCount(ctx))

View File

@ -7,7 +7,7 @@ import (
// DistributeFromFeePool distributes funds from the distribution module account to
// a receiver address while updating the community pool
func (k Keeper) DistributeFromFeePool(ctx sdk.Context, amount sdk.Coins, receiveAddr sdk.AccAddress) sdk.Error {
func (k Keeper) DistributeFromFeePool(ctx sdk.Context, amount sdk.Coins, receiveAddr sdk.AccAddress) error {
feePool := k.GetFeePool(ctx)
// NOTE the community pool isn't a module account, however its coins
@ -15,8 +15,9 @@ func (k Keeper) DistributeFromFeePool(ctx sdk.Context, amount sdk.Coins, receive
// must be reduced separately from the SendCoinsFromModuleToAccount call
newPool, negative := feePool.CommunityPool.SafeSub(sdk.NewDecCoins(amount))
if negative {
return types.ErrBadDistribution(k.codespace)
return types.ErrBadDistribution
}
feePool.CommunityPool = newPool
err := k.supplyKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, receiveAddr, amount)

View File

@ -5,6 +5,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
"github.com/cosmos/cosmos-sdk/x/params"
@ -19,17 +20,17 @@ type Keeper struct {
stakingKeeper types.StakingKeeper
supplyKeeper types.SupplyKeeper
codespace sdk.CodespaceType
blacklistedAddrs map[string]bool
feeCollectorName string // name of the FeeCollector ModuleAccount
}
// NewKeeper creates a new distribution Keeper instance
func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, paramSpace params.Subspace,
sk types.StakingKeeper, supplyKeeper types.SupplyKeeper, codespace sdk.CodespaceType,
feeCollectorName string, blacklistedAddrs map[string]bool) Keeper {
func NewKeeper(
cdc *codec.Codec, key sdk.StoreKey, paramSpace params.Subspace,
sk types.StakingKeeper, supplyKeeper types.SupplyKeeper, feeCollectorName string,
blacklistedAddrs map[string]bool,
) Keeper {
// ensure distribution module account is set
if addr := supplyKeeper.GetModuleAddress(types.ModuleName); addr == nil {
@ -42,7 +43,6 @@ func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, paramSpace params.Subspace,
paramSpace: paramSpace.WithKeyTable(ParamKeyTable()),
stakingKeeper: sk,
supplyKeeper: supplyKeeper,
codespace: codespace,
feeCollectorName: feeCollectorName,
blacklistedAddrs: blacklistedAddrs,
}
@ -54,13 +54,13 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger {
}
// SetWithdrawAddr sets a new address that will receive the rewards upon withdrawal
func (k Keeper) SetWithdrawAddr(ctx sdk.Context, delegatorAddr sdk.AccAddress, withdrawAddr sdk.AccAddress) sdk.Error {
func (k Keeper) SetWithdrawAddr(ctx sdk.Context, delegatorAddr sdk.AccAddress, withdrawAddr sdk.AccAddress) error {
if k.blacklistedAddrs[withdrawAddr.String()] {
return sdk.ErrUnauthorized(fmt.Sprintf("%s is blacklisted from receiving external funds", withdrawAddr))
return sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s is blacklisted from receiving external funds", withdrawAddr)
}
if !k.GetWithdrawAddrEnabled(ctx) {
return types.ErrSetWithdrawAddrDisabled(k.codespace)
return types.ErrSetWithdrawAddrDisabled
}
ctx.EventManager().EmitEvent(
@ -75,15 +75,15 @@ func (k Keeper) SetWithdrawAddr(ctx sdk.Context, delegatorAddr sdk.AccAddress, w
}
// withdraw rewards from a delegation
func (k Keeper) WithdrawDelegationRewards(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) (sdk.Coins, sdk.Error) {
func (k Keeper) WithdrawDelegationRewards(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) (sdk.Coins, error) {
val := k.stakingKeeper.Validator(ctx, valAddr)
if val == nil {
return nil, types.ErrNoValidatorDistInfo(k.codespace)
return nil, types.ErrNoValidatorDistInfo
}
del := k.stakingKeeper.Delegation(ctx, delAddr, valAddr)
if del == nil {
return nil, types.ErrNoDelegationDistInfo(k.codespace)
return nil, types.ErrEmptyDelegationDistInfo
}
// withdraw rewards
@ -106,11 +106,11 @@ func (k Keeper) WithdrawDelegationRewards(ctx sdk.Context, delAddr sdk.AccAddres
}
// withdraw validator commission
func (k Keeper) WithdrawValidatorCommission(ctx sdk.Context, valAddr sdk.ValAddress) (sdk.Coins, sdk.Error) {
func (k Keeper) WithdrawValidatorCommission(ctx sdk.Context, valAddr sdk.ValAddress) (sdk.Coins, error) {
// fetch validator accumulated commission
accumCommission := k.GetValidatorAccumulatedCommission(ctx, valAddr)
if accumCommission.IsZero() {
return nil, types.ErrNoValidatorCommission(k.codespace)
return nil, types.ErrNoValidatorCommission
}
commission, remainder := accumCommission.TruncateDecimal()
@ -147,6 +147,7 @@ func (k Keeper) GetTotalRewards(ctx sdk.Context) (totalRewards sdk.DecCoins) {
return false
},
)
return totalRewards
}

View File

@ -4,13 +4,14 @@ import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
)
// HandleCommunityPoolSpendProposal is a handler for executing a passed community spend proposal
func HandleCommunityPoolSpendProposal(ctx sdk.Context, k Keeper, p types.CommunityPoolSpendProposal) sdk.Error {
func HandleCommunityPoolSpendProposal(ctx sdk.Context, k Keeper, p types.CommunityPoolSpendProposal) error {
if k.blacklistedAddrs[p.Recipient.String()] {
return sdk.ErrUnauthorized(fmt.Sprintf("%s is blacklisted from receiving external funds", p.Recipient))
return sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s is blacklisted from receiving external funds", p.Recipient)
}
err := k.DistributeFromFeePool(ctx, p.Amount, p.Recipient)

View File

@ -2,18 +2,18 @@ package keeper
import (
"encoding/json"
"fmt"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
"github.com/cosmos/cosmos-sdk/x/staking/exported"
)
func NewQuerier(k Keeper) sdk.Querier {
return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, sdk.Error) {
return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) {
switch path[0] {
case types.QueryParams:
return queryParams(ctx, path[1:], req, k)
@ -43,82 +43,93 @@ func NewQuerier(k Keeper) sdk.Querier {
return queryCommunityPool(ctx, path[1:], req, k)
default:
return nil, sdk.ErrUnknownRequest("unknown distr query endpoint")
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown query path: %s", path[0])
}
}
}
func queryParams(ctx sdk.Context, path []string, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) {
func queryParams(ctx sdk.Context, path []string, req abci.RequestQuery, k Keeper) ([]byte, error) {
switch path[0] {
case types.ParamCommunityTax:
bz, err := codec.MarshalJSONIndent(k.cdc, k.GetCommunityTax(ctx))
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
case types.ParamBaseProposerReward:
bz, err := codec.MarshalJSONIndent(k.cdc, k.GetBaseProposerReward(ctx))
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
case types.ParamBonusProposerReward:
bz, err := codec.MarshalJSONIndent(k.cdc, k.GetBonusProposerReward(ctx))
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
case types.ParamWithdrawAddrEnabled:
bz, err := codec.MarshalJSONIndent(k.cdc, k.GetWithdrawAddrEnabled(ctx))
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
default:
return nil, sdk.ErrUnknownRequest(fmt.Sprintf("%s is not a valid query request path", req.Path))
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "%s is not a valid query request path", req.Path)
}
}
func queryValidatorOutstandingRewards(ctx sdk.Context, path []string, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) {
func queryValidatorOutstandingRewards(ctx sdk.Context, path []string, req abci.RequestQuery, k Keeper) ([]byte, error) {
var params types.QueryValidatorOutstandingRewardsParams
err := k.cdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
rewards := k.GetValidatorOutstandingRewards(ctx, params.ValidatorAddress)
if rewards == nil {
rewards = sdk.DecCoins{}
}
bz, err := codec.MarshalJSONIndent(k.cdc, rewards)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
}
func queryValidatorCommission(ctx sdk.Context, path []string, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) {
func queryValidatorCommission(ctx sdk.Context, path []string, req abci.RequestQuery, k Keeper) ([]byte, error) {
var params types.QueryValidatorCommissionParams
err := k.cdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
commission := k.GetValidatorAccumulatedCommission(ctx, params.ValidatorAddress)
if commission == nil {
commission = sdk.DecCoins{}
}
bz, err := codec.MarshalJSONIndent(k.cdc, commission)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
}
func queryValidatorSlashes(ctx sdk.Context, path []string, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) {
func queryValidatorSlashes(ctx sdk.Context, path []string, req abci.RequestQuery, k Keeper) ([]byte, error) {
var params types.QueryValidatorSlashesParams
err := k.cdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
events := make([]types.ValidatorSlashEvent, 0)
k.IterateValidatorSlashEventsBetween(ctx, params.ValidatorAddress, params.StartingHeight, params.EndingHeight,
func(height uint64, event types.ValidatorSlashEvent) (stop bool) {
@ -126,18 +137,20 @@ func queryValidatorSlashes(ctx sdk.Context, path []string, req abci.RequestQuery
return false
},
)
bz, err := codec.MarshalJSONIndent(k.cdc, events)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
}
func queryDelegationRewards(ctx sdk.Context, _ []string, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) {
func queryDelegationRewards(ctx sdk.Context, _ []string, req abci.RequestQuery, k Keeper) ([]byte, error) {
var params types.QueryDelegationRewardsParams
err := k.cdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
// cache-wrap context as to not persist state changes during querying
@ -145,14 +158,12 @@ func queryDelegationRewards(ctx sdk.Context, _ []string, req abci.RequestQuery,
val := k.stakingKeeper.Validator(ctx, params.ValidatorAddress)
if val == nil {
// TODO: Should use ErrNoValidatorFound from staking/types
return nil, sdk.ErrInternal(fmt.Sprintf("validator %s does not exist", params.ValidatorAddress))
return nil, sdkerrors.Wrap(types.ErrNoValidatorExists, params.ValidatorAddress.String())
}
del := k.stakingKeeper.Delegation(ctx, params.DelegatorAddress, params.ValidatorAddress)
if del == nil {
// TODO: Should use ErrNoDelegation from staking/types
return nil, sdk.ErrInternal("delegation does not exist")
return nil, types.ErrNoDelegationExists
}
endingPeriod := k.incrementValidatorPeriod(ctx, val)
@ -163,17 +174,17 @@ func queryDelegationRewards(ctx sdk.Context, _ []string, req abci.RequestQuery,
bz, err := codec.MarshalJSONIndent(k.cdc, rewards)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
}
func queryDelegatorTotalRewards(ctx sdk.Context, _ []string, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) {
func queryDelegatorTotalRewards(ctx sdk.Context, _ []string, req abci.RequestQuery, k Keeper) ([]byte, error) {
var params types.QueryDelegatorParams
err := k.cdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
// cache-wrap context as to not persist state changes during querying
@ -192,24 +203,26 @@ func queryDelegatorTotalRewards(ctx sdk.Context, _ []string, req abci.RequestQue
delRewards = append(delRewards, types.NewDelegationDelegatorReward(valAddr, delReward))
total = total.Add(delReward)
return false
},
)
totalRewards := types.NewQueryDelegatorTotalRewardsResponse(delRewards, total)
bz, err := json.Marshal(totalRewards)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
}
func queryDelegatorValidators(ctx sdk.Context, _ []string, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) {
func queryDelegatorValidators(ctx sdk.Context, _ []string, req abci.RequestQuery, k Keeper) ([]byte, error) {
var params types.QueryDelegatorParams
err := k.cdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
// cache-wrap context as to not persist state changes during querying
@ -227,16 +240,17 @@ func queryDelegatorValidators(ctx sdk.Context, _ []string, req abci.RequestQuery
bz, err := codec.MarshalJSONIndent(k.cdc, validators)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
}
func queryDelegatorWithdrawAddress(ctx sdk.Context, _ []string, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) {
func queryDelegatorWithdrawAddress(ctx sdk.Context, _ []string, req abci.RequestQuery, k Keeper) ([]byte, error) {
var params types.QueryDelegatorWithdrawAddrParams
err := k.cdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
// cache-wrap context as to not persist state changes during querying
@ -245,20 +259,22 @@ func queryDelegatorWithdrawAddress(ctx sdk.Context, _ []string, req abci.Request
bz, err := codec.MarshalJSONIndent(k.cdc, withdrawAddr)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
}
func queryCommunityPool(ctx sdk.Context, _ []string, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) {
func queryCommunityPool(ctx sdk.Context, _ []string, req abci.RequestQuery, k Keeper) ([]byte, error) {
pool := k.GetFeePoolCommunityCoins(ctx)
if pool == nil {
pool = sdk.DecCoins{}
}
bz, err := k.cdc.MarshalJSON(pool)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
}

View File

@ -189,10 +189,16 @@ func TestQueries(t *testing.T) {
// test delegation rewards query
sh := staking.NewHandler(sk)
comm := staking.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
msg := staking.NewMsgCreateValidator(valOpAddr1, valConsPk1,
sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), staking.Description{}, comm, sdk.OneInt())
require.True(t, sh(ctx, msg).IsOK())
msg := staking.NewMsgCreateValidator(
valOpAddr1, valConsPk1, sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)), staking.Description{}, comm, sdk.OneInt(),
)
res, err := sh(ctx, msg)
require.NoError(t, err)
require.NotNil(t, res)
staking.EndBlocker(ctx, sk)
val := sk.Validator(ctx, valOpAddr1)
rewards := getQueriedDelegationRewards(t, ctx, cdc, querier, sdk.AccAddress(valOpAddr1), valOpAddr1)
require.True(t, rewards.IsZero())

View File

@ -119,11 +119,11 @@ func CreateTestInputAdvanced(t *testing.T, isCheckTx bool, initPower int64,
blacklistedAddrs[distrAcc.GetAddress().String()] = true
cdc := MakeTestCodec()
pk := params.NewKeeper(cdc, keyParams, tkeyParams, params.DefaultCodespace)
pk := params.NewKeeper(cdc, keyParams, tkeyParams)
ctx := sdk.NewContext(ms, abci.Header{ChainID: "foochainid"}, isCheckTx, log.NewNopLogger())
accountKeeper := auth.NewAccountKeeper(cdc, keyAcc, pk.Subspace(auth.DefaultParamspace), auth.ProtoBaseAccount)
bankKeeper := bank.NewBaseKeeper(accountKeeper, pk.Subspace(bank.DefaultParamspace), bank.DefaultCodespace, blacklistedAddrs)
bankKeeper := bank.NewBaseKeeper(accountKeeper, pk.Subspace(bank.DefaultParamspace), blacklistedAddrs)
maccPerms := map[string][]string{
auth.FeeCollectorName: nil,
types.ModuleName: nil,
@ -132,10 +132,10 @@ func CreateTestInputAdvanced(t *testing.T, isCheckTx bool, initPower int64,
}
supplyKeeper := supply.NewKeeper(cdc, keySupply, accountKeeper, bankKeeper, maccPerms)
sk := staking.NewKeeper(cdc, keyStaking, supplyKeeper, pk.Subspace(staking.DefaultParamspace), staking.DefaultCodespace)
sk := staking.NewKeeper(cdc, keyStaking, supplyKeeper, pk.Subspace(staking.DefaultParamspace))
sk.SetParams(ctx, staking.DefaultParams())
keeper := NewKeeper(cdc, keyDistr, pk.Subspace(DefaultParamspace), sk, supplyKeeper, types.DefaultCodespace, auth.FeeCollectorName, blacklistedAddrs)
keeper := NewKeeper(cdc, keyDistr, pk.Subspace(DefaultParamspace), sk, supplyKeeper, auth.FeeCollectorName, blacklistedAddrs)
initCoins := sdk.NewCoins(sdk.NewCoin(sk.BondDenom(ctx), initTokens))
totalSupply := sdk.NewCoins(sdk.NewCoin(sk.BondDenom(ctx), initTokens.MulRaw(int64(len(TestAddrs)))))

View File

@ -1,7 +1,6 @@
package simulation
import (
"errors"
"fmt"
"math/rand"
@ -109,9 +108,9 @@ func SimulateMsgSetWithdrawAddress(ak types.AccountKeeper, k keeper.Keeper) simu
simAccount.PrivKey,
)
res := app.Deliver(tx)
if !res.IsOK() {
return simulation.NoOpMsg(types.ModuleName), nil, errors.New(res.Log)
_, _, err = app.Deliver(tx)
if err != nil {
return simulation.NoOpMsg(types.ModuleName), nil, err
}
return simulation.NewOperationMsg(msg, true, ""), nil, nil
@ -155,9 +154,9 @@ func SimulateMsgWithdrawDelegatorReward(ak types.AccountKeeper, k keeper.Keeper,
simAccount.PrivKey,
)
res := app.Deliver(tx)
if !res.IsOK() {
return simulation.NoOpMsg(types.ModuleName), nil, errors.New(res.Log)
_, _, err = app.Deliver(tx)
if err != nil {
return simulation.NoOpMsg(types.ModuleName), nil, err
}
return simulation.NewOperationMsg(msg, true, ""), nil, nil
@ -204,9 +203,9 @@ func SimulateMsgWithdrawValidatorCommission(ak types.AccountKeeper, k keeper.Kee
simAccount.PrivKey,
)
res := app.Deliver(tx)
if !res.IsOK() {
return simulation.NoOpMsg(types.ModuleName), nil, errors.New(res.Log)
_, _, err = app.Deliver(tx)
if err != nil {
return simulation.NoOpMsg(types.ModuleName), nil, err
}
return simulation.NewOperationMsg(msg, true, ""), nil, nil
@ -254,9 +253,9 @@ func SimulateMsgFundCommunityPool(ak types.AccountKeeper, k keeper.Keeper, sk st
funder.PrivKey,
)
res := app.Deliver(tx)
if !res.IsOK() {
return simulation.NoOpMsg(types.ModuleName), nil, errors.New(res.Log)
_, _, err = app.Deliver(tx)
if err != nil {
return simulation.NoOpMsg(types.ModuleName), nil, err
}
return simulation.NewOperationMsg(msg, true, ""), nil, nil

View File

@ -1,47 +1,21 @@
// nolint
package types
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
type CodeType = sdk.CodeType
const (
DefaultCodespace sdk.CodespaceType = "distr"
CodeInvalidInput CodeType = 103
CodeNoDistributionInfo CodeType = 104
CodeNoValidatorCommission CodeType = 105
CodeSetWithdrawAddrDisabled CodeType = 106
// x/distribution module sentinel errors
var (
ErrEmptyDelegatorAddr = sdkerrors.Register(ModuleName, 1, "delegator address is empty")
ErrEmptyWithdrawAddr = sdkerrors.Register(ModuleName, 2, "withdraw address is empty")
ErrEmptyValidatorAddr = sdkerrors.Register(ModuleName, 3, "validator address is empty")
ErrEmptyDelegationDistInfo = sdkerrors.Register(ModuleName, 4, "no delegation distribution info")
ErrNoValidatorDistInfo = sdkerrors.Register(ModuleName, 5, "no validator distribution info")
ErrNoValidatorCommission = sdkerrors.Register(ModuleName, 6, "no validator commission to withdraw")
ErrSetWithdrawAddrDisabled = sdkerrors.Register(ModuleName, 7, "set withdraw address disabled")
ErrBadDistribution = sdkerrors.Register(ModuleName, 8, "community pool does not have sufficient coins to distribute")
ErrInvalidProposalAmount = sdkerrors.Register(ModuleName, 9, "invalid community pool spend proposal amount")
ErrEmptyProposalRecipient = sdkerrors.Register(ModuleName, 10, "invalid community pool spend proposal recipient")
ErrNoValidatorExists = sdkerrors.Register(ModuleName, 11, "validator does not exist")
ErrNoDelegationExists = sdkerrors.Register(ModuleName, 12, "delegation does not exist")
)
func ErrNilDelegatorAddr(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidInput, "delegator address is nil")
}
func ErrNilWithdrawAddr(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidInput, "withdraw address is nil")
}
func ErrNilValidatorAddr(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidInput, "validator address is nil")
}
func ErrNoDelegationDistInfo(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeNoDistributionInfo, "no delegation distribution info")
}
func ErrNoValidatorDistInfo(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeNoDistributionInfo, "no validator distribution info")
}
func ErrNoValidatorCommission(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeNoValidatorCommission, "no validator commission to withdraw")
}
func ErrSetWithdrawAddrDisabled(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeSetWithdrawAddrDisabled, "set withdraw address disabled")
}
func ErrBadDistribution(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidInput, "community pool does not have sufficient coins to distribute")
}
func ErrInvalidProposalAmount(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidInput, "invalid community pool spend proposal amount")
}
func ErrEmptyProposalRecipient(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidInput, "invalid community pool spend proposal recipient")
}

View File

@ -70,7 +70,7 @@ type SupplyKeeper interface {
// TODO remove with genesis 2-phases refactor https://github.com/cosmos/cosmos-sdk/issues/2862
SetModuleAccount(sdk.Context, supplyexported.ModuleAccountI)
SendCoinsFromModuleToModule(ctx sdk.Context, senderModule string, recipientModule string, amt sdk.Coins) sdk.Error
SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) sdk.Error
SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) sdk.Error
SendCoinsFromModuleToModule(ctx sdk.Context, senderModule string, recipientModule string, amt sdk.Coins) error
SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error
SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
}

View File

@ -3,6 +3,7 @@ package types
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
// Verify interface at compile time
@ -36,13 +37,14 @@ func (msg MsgSetWithdrawAddress) GetSignBytes() []byte {
}
// quick validity check
func (msg MsgSetWithdrawAddress) ValidateBasic() sdk.Error {
func (msg MsgSetWithdrawAddress) ValidateBasic() error {
if msg.DelegatorAddress.Empty() {
return ErrNilDelegatorAddr(DefaultCodespace)
return ErrEmptyDelegatorAddr
}
if msg.WithdrawAddress.Empty() {
return ErrNilWithdrawAddr(DefaultCodespace)
return ErrEmptyWithdrawAddr
}
return nil
}
@ -74,12 +76,12 @@ func (msg MsgWithdrawDelegatorReward) GetSignBytes() []byte {
}
// quick validity check
func (msg MsgWithdrawDelegatorReward) ValidateBasic() sdk.Error {
func (msg MsgWithdrawDelegatorReward) ValidateBasic() error {
if msg.DelegatorAddress.Empty() {
return ErrNilDelegatorAddr(DefaultCodespace)
return ErrEmptyDelegatorAddr
}
if msg.ValidatorAddress.Empty() {
return ErrNilValidatorAddr(DefaultCodespace)
return ErrEmptyValidatorAddr
}
return nil
}
@ -110,9 +112,9 @@ func (msg MsgWithdrawValidatorCommission) GetSignBytes() []byte {
}
// quick validity check
func (msg MsgWithdrawValidatorCommission) ValidateBasic() sdk.Error {
func (msg MsgWithdrawValidatorCommission) ValidateBasic() error {
if msg.ValidatorAddress.Empty() {
return ErrNilValidatorAddr(DefaultCodespace)
return ErrEmptyValidatorAddr
}
return nil
}
@ -155,12 +157,12 @@ func (msg MsgFundCommunityPool) GetSignBytes() []byte {
}
// ValidateBasic performs basic MsgFundCommunityPool message validation.
func (msg MsgFundCommunityPool) ValidateBasic() sdk.Error {
func (msg MsgFundCommunityPool) ValidateBasic() error {
if !msg.Amount.IsValid() {
return sdk.ErrInvalidCoins(msg.Amount.String())
return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, msg.Amount.String())
}
if msg.Depositor.Empty() {
return sdk.ErrInvalidAddress(msg.Depositor.String())
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, msg.Depositor.String())
}
return nil

View File

@ -47,17 +47,18 @@ func (csp CommunityPoolSpendProposal) ProposalRoute() string { return RouterKey
func (csp CommunityPoolSpendProposal) ProposalType() string { return ProposalTypeCommunityPoolSpend }
// ValidateBasic runs basic stateless validity checks
func (csp CommunityPoolSpendProposal) ValidateBasic() sdk.Error {
err := govtypes.ValidateAbstract(DefaultCodespace, csp)
func (csp CommunityPoolSpendProposal) ValidateBasic() error {
err := govtypes.ValidateAbstract(csp)
if err != nil {
return err
}
if !csp.Amount.IsValid() {
return ErrInvalidProposalAmount(DefaultCodespace)
return ErrInvalidProposalAmount
}
if csp.Recipient.Empty() {
return ErrEmptyProposalRecipient(DefaultCodespace)
return ErrEmptyProposalRecipient
}
return nil
}

View File

@ -8,23 +8,19 @@ import (
// nolint
const (
ModuleName = types.ModuleName
StoreKey = types.StoreKey
RouterKey = types.RouterKey
QuerierRoute = types.QuerierRoute
DefaultParamspace = types.DefaultParamspace
QueryEvidence = types.QueryEvidence
QueryAllEvidence = types.QueryAllEvidence
QueryParameters = types.QueryParameters
CodeNoEvidenceHandlerExists = types.CodeNoEvidenceHandlerExists
CodeInvalidEvidence = types.CodeInvalidEvidence
CodeNoEvidenceExists = types.CodeNoEvidenceExists
TypeMsgSubmitEvidence = types.TypeMsgSubmitEvidence
DefaultCodespace = types.DefaultCodespace
EventTypeSubmitEvidence = types.EventTypeSubmitEvidence
AttributeValueCategory = types.AttributeValueCategory
AttributeKeyEvidenceHash = types.AttributeKeyEvidenceHash
DefaultMaxEvidenceAge = types.DefaultMaxEvidenceAge
ModuleName = types.ModuleName
StoreKey = types.StoreKey
RouterKey = types.RouterKey
QuerierRoute = types.QuerierRoute
DefaultParamspace = types.DefaultParamspace
QueryEvidence = types.QueryEvidence
QueryAllEvidence = types.QueryAllEvidence
QueryParameters = types.QueryParameters
TypeMsgSubmitEvidence = types.TypeMsgSubmitEvidence
EventTypeSubmitEvidence = types.EventTypeSubmitEvidence
AttributeValueCategory = types.AttributeValueCategory
AttributeKeyEvidenceHash = types.AttributeKeyEvidenceHash
DefaultMaxEvidenceAge = types.DefaultMaxEvidenceAge
)
var (

View File

@ -32,8 +32,7 @@ func (suite *GenesisTestSuite) SetupTest() {
// recreate keeper in order to use custom testing types
evidenceKeeper := evidence.NewKeeper(
cdc, app.GetKey(evidence.StoreKey), app.GetSubspace(evidence.ModuleName),
evidence.DefaultCodespace, app.StakingKeeper, app.SlashingKeeper,
cdc, app.GetKey(evidence.StoreKey), app.GetSubspace(evidence.ModuleName), app.StakingKeeper, app.SlashingKeeper,
)
router := evidence.NewRouter()
router = router.AddRoute(types.TestEvidenceRouteEquivocation, types.TestEquivocationHandler(*evidenceKeeper))

View File

@ -1,13 +1,12 @@
package evidence
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
func NewHandler(k Keeper) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
ctx = ctx.WithEventManager(sdk.NewEventManager())
switch msg := msg.(type) {
@ -15,14 +14,14 @@ func NewHandler(k Keeper) sdk.Handler {
return handleMsgSubmitEvidence(ctx, k, msg)
default:
return sdk.ErrUnknownRequest(fmt.Sprintf("unrecognized %s message type: %T", ModuleName, msg)).Result()
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", ModuleName, msg)
}
}
}
func handleMsgSubmitEvidence(ctx sdk.Context, k Keeper, msg MsgSubmitEvidence) sdk.Result {
func handleMsgSubmitEvidence(ctx sdk.Context, k Keeper, msg MsgSubmitEvidence) (*sdk.Result, error) {
if err := k.SubmitEvidence(ctx, msg.Evidence); err != nil {
return sdk.ConvertError(err).Result()
return nil, err
}
ctx.EventManager().EmitEvent(
@ -33,8 +32,8 @@ func handleMsgSubmitEvidence(ctx sdk.Context, k Keeper, msg MsgSubmitEvidence) s
),
)
return sdk.Result{
return &sdk.Result{
Data: msg.Evidence.Hash(),
Events: ctx.EventManager().Events(),
}
}, nil
}

View File

@ -31,8 +31,7 @@ func (suite *HandlerTestSuite) SetupTest() {
// recreate keeper in order to use custom testing types
evidenceKeeper := evidence.NewKeeper(
cdc, app.GetKey(evidence.StoreKey), app.GetSubspace(evidence.ModuleName),
evidence.DefaultCodespace, app.StakingKeeper, app.SlashingKeeper,
cdc, app.GetKey(evidence.StoreKey), app.GetSubspace(evidence.ModuleName), app.StakingKeeper, app.SlashingKeeper,
)
router := evidence.NewRouter()
router = router.AddRoute(types.TestEvidenceRouteEquivocation, types.TestEquivocationHandler(*evidenceKeeper))
@ -66,8 +65,9 @@ func (suite *HandlerTestSuite) TestMsgSubmitEvidence_Valid() {
ctx := suite.ctx.WithIsCheckTx(false)
msg := evidence.NewMsgSubmitEvidence(e, s)
res := suite.handler(ctx, msg)
suite.True(res.IsOK())
res, err := suite.handler(ctx, msg)
suite.NoError(err)
suite.NotNil(res)
suite.Equal(e.Hash().Bytes(), res.Data)
}
@ -94,8 +94,9 @@ func (suite *HandlerTestSuite) TestMsgSubmitEvidence_Invalid() {
ctx := suite.ctx.WithIsCheckTx(false)
msg := evidence.NewMsgSubmitEvidence(e, s)
res := suite.handler(ctx, msg)
suite.False(res.IsOK())
res, err := suite.handler(ctx, msg)
suite.Error(err)
suite.Nil(res)
}
func TestHandlerTestSuite(t *testing.T) {

View File

@ -28,8 +28,9 @@ func (suite *KeeperTestSuite) TestHandleDoubleSign() {
operatorAddr, val := valAddresses[0], pubkeys[0]
// create validator
res := staking.NewHandler(suite.app.StakingKeeper)(ctx, newTestMsgCreateValidator(operatorAddr, val, amt))
suite.True(res.IsOK(), res.Log)
res, err := staking.NewHandler(suite.app.StakingKeeper)(ctx, newTestMsgCreateValidator(operatorAddr, val, amt))
suite.NoError(err)
suite.NotNil(res)
// execute end-blocker and verify validator attributes
staking.EndBlocker(ctx, suite.app.StakingKeeper)
@ -78,8 +79,9 @@ func (suite *KeeperTestSuite) TestHandleDoubleSign() {
validator, _ := suite.app.StakingKeeper.GetValidator(ctx, operatorAddr)
totalBond := validator.TokensFromShares(del.GetShares()).TruncateInt()
msgUnbond := staking.NewMsgUndelegate(sdk.AccAddress(operatorAddr), operatorAddr, sdk.NewCoin(stakingParams.BondDenom, totalBond))
res = staking.NewHandler(suite.app.StakingKeeper)(ctx, msgUnbond)
suite.True(res.IsOK())
res, err = staking.NewHandler(suite.app.StakingKeeper)(ctx, msgUnbond)
suite.NoError(err)
suite.NotNil(res)
}
func (suite *KeeperTestSuite) TestHandleDoubleSign_TooOld() {
@ -92,8 +94,9 @@ func (suite *KeeperTestSuite) TestHandleDoubleSign_TooOld() {
operatorAddr, val := valAddresses[0], pubkeys[0]
// create validator
res := staking.NewHandler(suite.app.StakingKeeper)(ctx, newTestMsgCreateValidator(operatorAddr, val, amt))
suite.True(res.IsOK(), res.Log)
res, err := staking.NewHandler(suite.app.StakingKeeper)(ctx, newTestMsgCreateValidator(operatorAddr, val, amt))
suite.NoError(err)
suite.NotNil(res)
// execute end-blocker and verify validator attributes
staking.EndBlocker(ctx, suite.app.StakingKeeper)

View File

@ -9,6 +9,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/store/prefix"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/evidence/exported"
"github.com/cosmos/cosmos-sdk/x/evidence/internal/types"
"github.com/cosmos/cosmos-sdk/x/params"
@ -24,11 +25,10 @@ type Keeper struct {
router types.Router
stakingKeeper types.StakingKeeper
slashingKeeper types.SlashingKeeper
codespace sdk.CodespaceType
}
func NewKeeper(
cdc *codec.Codec, storeKey sdk.StoreKey, paramSpace params.Subspace, codespace sdk.CodespaceType,
cdc *codec.Codec, storeKey sdk.StoreKey, paramSpace params.Subspace,
stakingKeeper types.StakingKeeper, slashingKeeper types.SlashingKeeper,
) *Keeper {
@ -43,7 +43,6 @@ func NewKeeper(
paramSpace: paramSpace,
stakingKeeper: stakingKeeper,
slashingKeeper: slashingKeeper,
codespace: codespace,
}
}
@ -74,7 +73,7 @@ func (k *Keeper) SetRouter(rtr types.Router) {
// no handler exists, an error is returned.
func (k Keeper) GetEvidenceHandler(evidenceRoute string) (types.Handler, error) {
if !k.router.HasRoute(evidenceRoute) {
return nil, types.ErrNoEvidenceHandlerExists(k.codespace, evidenceRoute)
return nil, sdkerrors.Wrap(types.ErrNoEvidenceHandlerExists, evidenceRoute)
}
return k.router.GetRoute(evidenceRoute), nil
@ -86,15 +85,15 @@ func (k Keeper) GetEvidenceHandler(evidenceRoute string) (types.Handler, error)
// persisted.
func (k Keeper) SubmitEvidence(ctx sdk.Context, evidence exported.Evidence) error {
if _, ok := k.GetEvidence(ctx, evidence.Hash()); ok {
return types.ErrEvidenceExists(k.codespace, evidence.Hash().String())
return sdkerrors.Wrap(types.ErrEvidenceExists, evidence.Hash().String())
}
if !k.router.HasRoute(evidence.Route()) {
return types.ErrNoEvidenceHandlerExists(k.codespace, evidence.Route())
return sdkerrors.Wrap(types.ErrNoEvidenceHandlerExists, evidence.Route())
}
handler := k.router.GetRoute(evidence.Route())
if err := handler(ctx, evidence); err != nil {
return types.ErrInvalidEvidence(k.codespace, err.Error())
return sdkerrors.Wrap(types.ErrInvalidEvidence, err.Error())
}
ctx.EventManager().EmitEvent(

View File

@ -66,8 +66,7 @@ func (suite *KeeperTestSuite) SetupTest() {
// recreate keeper in order to use custom testing types
evidenceKeeper := evidence.NewKeeper(
cdc, app.GetKey(evidence.StoreKey), app.GetSubspace(evidence.ModuleName),
evidence.DefaultCodespace, app.StakingKeeper, app.SlashingKeeper,
cdc, app.GetKey(evidence.StoreKey), app.GetSubspace(evidence.ModuleName), app.StakingKeeper, app.SlashingKeeper,
)
router := evidence.NewRouter()
router = router.AddRoute(types.TestEvidenceRouteEquivocation, types.TestEquivocationHandler(*evidenceKeeper))

View File

@ -14,7 +14,7 @@ import (
)
func NewQuerier(k Keeper) sdk.Querier {
return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, sdk.Error) {
return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) {
var (
res []byte
err error
@ -31,10 +31,10 @@ func NewQuerier(k Keeper) sdk.Querier {
res, err = queryAllEvidence(ctx, req, k)
default:
err = sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown %s query endpoint", types.ModuleName)
err = sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown %s query endpoint: %s", types.ModuleName, path[0])
}
return res, sdk.ConvertError(err)
return res, err
}
}
@ -64,7 +64,7 @@ func queryEvidence(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, er
evidence, ok := k.GetEvidence(ctx, hash)
if !ok {
return nil, types.ErrNoEvidenceExists(k.codespace, params.EvidenceHash)
return nil, sdkerrors.Wrap(types.ErrNoEvidenceExists, params.EvidenceHash)
}
res, err := codec.MarshalJSONIndent(k.cdc, evidence)

View File

@ -2,57 +2,13 @@
package types
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
// Error codes specific to the evidence module
const (
DefaultCodespace sdk.CodespaceType = ModuleName
CodeNoEvidenceHandlerExists sdk.CodeType = 1
CodeInvalidEvidence sdk.CodeType = 2
CodeNoEvidenceExists sdk.CodeType = 3
CodeEvidenceExists sdk.CodeType = 4
// x/evidence module sentinel errors
var (
ErrNoEvidenceHandlerExists = sdkerrors.Register(ModuleName, 1, "unregistered handler for evidence type")
ErrInvalidEvidence = sdkerrors.Register(ModuleName, 2, "invalid evidence")
ErrNoEvidenceExists = sdkerrors.Register(ModuleName, 3, "evidence does not exist")
ErrEvidenceExists = sdkerrors.Register(ModuleName, 4, "evidence already exists")
)
// ErrNoEvidenceHandlerExists returns a typed ABCI error for an invalid evidence
// handler route.
func ErrNoEvidenceHandlerExists(codespace sdk.CodespaceType, route string) error {
return sdkerrors.New(
string(codespace),
uint32(CodeNoEvidenceHandlerExists),
fmt.Sprintf("route '%s' does not have a registered evidence handler", route),
)
}
// ErrInvalidEvidence returns a typed ABCI error for invalid evidence.
func ErrInvalidEvidence(codespace sdk.CodespaceType, msg string) error {
return sdkerrors.New(
string(codespace),
uint32(CodeInvalidEvidence),
fmt.Sprintf("invalid evidence: %s", msg),
)
}
// ErrNoEvidenceExists returns a typed ABCI error for Evidence that does not exist
// for a given hash.
func ErrNoEvidenceExists(codespace sdk.CodespaceType, hash string) error {
return sdkerrors.New(
string(codespace),
uint32(CodeNoEvidenceExists),
fmt.Sprintf("evidence with hash %s does not exist", hash),
)
}
// ErrEvidenceExists returns a typed ABCI error for Evidence that already exists
// by hash in state.
func ErrEvidenceExists(codespace sdk.CodespaceType, hash string) error {
return sdkerrors.New(
string(codespace),
uint32(CodeEvidenceExists),
fmt.Sprintf("evidence with hash %s already exists", hash),
)
}

View File

@ -33,15 +33,15 @@ func (m MsgSubmitEvidence) Route() string { return RouterKey }
func (m MsgSubmitEvidence) Type() string { return TypeMsgSubmitEvidence }
// ValidateBasic performs basic (non-state-dependant) validation on a MsgSubmitEvidence.
func (m MsgSubmitEvidence) ValidateBasic() sdk.Error {
func (m MsgSubmitEvidence) ValidateBasic() error {
if m.Evidence == nil {
return sdk.ConvertError(ErrInvalidEvidence(DefaultCodespace, "missing evidence"))
return sdkerrors.Wrap(ErrInvalidEvidence, "missing evidence")
}
if err := m.Evidence.ValidateBasic(); err != nil {
return sdk.ConvertError(err)
return err
}
if m.Submitter.Empty() {
return sdk.ConvertError(sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, m.Submitter.String()))
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, m.Submitter.String())
}
return nil

View File

@ -1,6 +1,7 @@
package rest
import (
"fmt"
"net/http"
"github.com/cosmos/cosmos-sdk/client/context"
@ -14,15 +15,19 @@ import (
func QueryGenesisTxs(cliCtx context.CLIContext, w http.ResponseWriter) {
resultGenesis, err := cliCtx.Client.Genesis()
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError,
sdk.AppendMsgToErr("could not retrieve genesis from client", err.Error()))
rest.WriteErrorResponse(
w, http.StatusInternalServerError,
fmt.Sprintf("failed to retrieve genesis from client: %s", err),
)
return
}
appState, err := types.GenesisStateFromGenDoc(cliCtx.Codec, *resultGenesis.Genesis)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError,
sdk.AppendMsgToErr("could not decode genesis doc", err.Error()))
rest.WriteErrorResponse(
w, http.StatusInternalServerError,
fmt.Sprintf("failed to decode genesis doc: %s", err),
)
return
}
@ -31,8 +36,10 @@ func QueryGenesisTxs(cliCtx context.CLIContext, w http.ResponseWriter) {
for i, tx := range genState.GenTxs {
err := cliCtx.Codec.UnmarshalJSON(tx, &genTxs[i])
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError,
sdk.AppendMsgToErr("could not decode genesis transaction", err.Error()))
rest.WriteErrorResponse(
w, http.StatusInternalServerError,
fmt.Sprintf("failed to decode genesis transaction: %s", err),
)
return
}
}

View File

@ -65,7 +65,7 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) {
} else {
proposal.Status = StatusFailed
tagValue = types.AttributeValueProposalFailed
logMsg = fmt.Sprintf("passed, but failed on execution: %s", err.ABCILog())
logMsg = fmt.Sprintf("passed, but failed on execution: %s", err)
}
} else {
proposal.Status = StatusRejected

View File

@ -32,8 +32,9 @@ func TestTickExpiredDepositPeriod(t *testing.T) {
input.addrs[0],
)
res := govHandler(ctx, newProposalMsg)
require.True(t, res.IsOK())
res, err := govHandler(ctx, newProposalMsg)
require.NoError(t, err)
require.NotNil(t, res)
inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
@ -81,8 +82,9 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) {
input.addrs[0],
)
res := govHandler(ctx, newProposalMsg)
require.True(t, res.IsOK())
res, err := govHandler(ctx, newProposalMsg)
require.NoError(t, err)
require.NotNil(t, res)
inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, inactiveQueue.Valid())
@ -102,8 +104,9 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) {
input.addrs[0],
)
res = govHandler(ctx, newProposalMsg2)
require.True(t, res.IsOK())
res, err = govHandler(ctx, newProposalMsg2)
require.NoError(t, err)
require.NotNil(t, res)
newHeader = ctx.BlockHeader()
newHeader.Time = ctx.BlockHeader().Time.Add(input.keeper.GetDepositParams(ctx).MaxDepositPeriod).Add(time.Duration(-1) * time.Second)
@ -152,8 +155,10 @@ func TestTickPassedDepositPeriod(t *testing.T) {
input.addrs[0],
)
res := govHandler(ctx, newProposalMsg)
require.True(t, res.IsOK())
res, err := govHandler(ctx, newProposalMsg)
require.NoError(t, err)
require.NotNil(t, res)
proposalID := GetProposalIDFromBytes(res.Data)
inactiveQueue = input.keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
@ -169,8 +174,10 @@ func TestTickPassedDepositPeriod(t *testing.T) {
inactiveQueue.Close()
newDepositMsg := NewMsgDeposit(input.addrs[1], proposalID, sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 5)})
res = govHandler(ctx, newDepositMsg)
require.True(t, res.IsOK())
res, err = govHandler(ctx, newDepositMsg)
require.NoError(t, err)
require.NotNil(t, res)
activeQueue = input.keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time)
require.False(t, activeQueue.Valid())
@ -197,8 +204,10 @@ func TestTickPassedVotingPeriod(t *testing.T) {
proposalCoins := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, sdk.TokensFromConsensusPower(5))}
newProposalMsg := NewMsgSubmitProposal(keep.TestProposal, proposalCoins, input.addrs[0])
res := govHandler(ctx, newProposalMsg)
require.True(t, res.IsOK())
res, err := govHandler(ctx, newProposalMsg)
require.NoError(t, err)
require.NotNil(t, res)
proposalID := GetProposalIDFromBytes(res.Data)
newHeader := ctx.BlockHeader()
@ -206,8 +215,10 @@ func TestTickPassedVotingPeriod(t *testing.T) {
ctx = ctx.WithBlockHeader(newHeader)
newDepositMsg := NewMsgDeposit(input.addrs[1], proposalID, proposalCoins)
res = govHandler(ctx, newDepositMsg)
require.True(t, res.IsOK())
res, err = govHandler(ctx, newDepositMsg)
require.NoError(t, err)
require.NotNil(t, res)
newHeader = ctx.BlockHeader()
newHeader.Time = ctx.BlockHeader().Time.Add(input.keeper.GetDepositParams(ctx).MaxDepositPeriod).Add(input.keeper.GetVotingParams(ctx).VotingPeriod)
@ -259,8 +270,10 @@ func TestProposalPassedEndblocker(t *testing.T) {
proposalCoins := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, sdk.TokensFromConsensusPower(10))}
newDepositMsg := NewMsgDeposit(input.addrs[0], proposal.ProposalID, proposalCoins)
res := handler(ctx, newDepositMsg)
require.True(t, res.IsOK())
res, err := handler(ctx, newDepositMsg)
require.NoError(t, err)
require.NotNil(t, res)
macc = input.keeper.GetGovernanceAccount(ctx)
require.NotNil(t, macc)
@ -308,8 +321,10 @@ func TestEndBlockerProposalHandlerFailed(t *testing.T) {
proposalCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.TokensFromConsensusPower(10)))
newDepositMsg := NewMsgDeposit(input.addrs[0], proposal.ProposalID, proposalCoins)
res := handler(ctx, newDepositMsg)
require.True(t, res.IsOK())
res, err := handler(ctx, newDepositMsg)
require.NoError(t, err)
require.NotNil(t, res)
err = input.keeper.AddVote(ctx, proposal.ProposalID, input.addrs[0], OptionYes)
require.NoError(t, err)

View File

@ -1,62 +1,47 @@
// nolint
// autogenerated code using github.com/rigelrozanski/multitool
// aliases generated for the following subdirectories:
// ALIASGEN: github.com/cosmos/cosmos-sdk/x/gov/keeper
// ALIASGEN: github.com/cosmos/cosmos-sdk/x/gov/types
package gov
// nolint
import (
"github.com/cosmos/cosmos-sdk/x/gov/keeper"
"github.com/cosmos/cosmos-sdk/x/gov/types"
)
const (
MaxDescriptionLength = types.MaxDescriptionLength
MaxTitleLength = types.MaxTitleLength
DefaultCodespace = types.DefaultCodespace
CodeUnknownProposal = types.CodeUnknownProposal
CodeInactiveProposal = types.CodeInactiveProposal
CodeAlreadyActiveProposal = types.CodeAlreadyActiveProposal
CodeAlreadyFinishedProposal = types.CodeAlreadyFinishedProposal
CodeAddressNotStaked = types.CodeAddressNotStaked
CodeInvalidContent = types.CodeInvalidContent
CodeInvalidProposalType = types.CodeInvalidProposalType
CodeInvalidVote = types.CodeInvalidVote
CodeInvalidGenesis = types.CodeInvalidGenesis
CodeInvalidProposalStatus = types.CodeInvalidProposalStatus
CodeProposalHandlerNotExists = types.CodeProposalHandlerNotExists
DefaultPeriod = types.DefaultPeriod
ModuleName = types.ModuleName
StoreKey = types.StoreKey
RouterKey = types.RouterKey
QuerierRoute = types.QuerierRoute
DefaultParamspace = types.DefaultParamspace
TypeMsgDeposit = types.TypeMsgDeposit
TypeMsgVote = types.TypeMsgVote
TypeMsgSubmitProposal = types.TypeMsgSubmitProposal
StatusNil = types.StatusNil
StatusDepositPeriod = types.StatusDepositPeriod
StatusVotingPeriod = types.StatusVotingPeriod
StatusPassed = types.StatusPassed
StatusRejected = types.StatusRejected
StatusFailed = types.StatusFailed
ProposalTypeText = types.ProposalTypeText
QueryParams = types.QueryParams
QueryProposals = types.QueryProposals
QueryProposal = types.QueryProposal
QueryDeposits = types.QueryDeposits
QueryDeposit = types.QueryDeposit
QueryVotes = types.QueryVotes
QueryVote = types.QueryVote
QueryTally = types.QueryTally
ParamDeposit = types.ParamDeposit
ParamVoting = types.ParamVoting
ParamTallying = types.ParamTallying
OptionEmpty = types.OptionEmpty
OptionYes = types.OptionYes
OptionAbstain = types.OptionAbstain
OptionNo = types.OptionNo
OptionNoWithVeto = types.OptionNoWithVeto
MaxDescriptionLength = types.MaxDescriptionLength
MaxTitleLength = types.MaxTitleLength
DefaultPeriod = types.DefaultPeriod
ModuleName = types.ModuleName
StoreKey = types.StoreKey
RouterKey = types.RouterKey
QuerierRoute = types.QuerierRoute
DefaultParamspace = types.DefaultParamspace
TypeMsgDeposit = types.TypeMsgDeposit
TypeMsgVote = types.TypeMsgVote
TypeMsgSubmitProposal = types.TypeMsgSubmitProposal
StatusNil = types.StatusNil
StatusDepositPeriod = types.StatusDepositPeriod
StatusVotingPeriod = types.StatusVotingPeriod
StatusPassed = types.StatusPassed
StatusRejected = types.StatusRejected
StatusFailed = types.StatusFailed
ProposalTypeText = types.ProposalTypeText
QueryParams = types.QueryParams
QueryProposals = types.QueryProposals
QueryProposal = types.QueryProposal
QueryDeposits = types.QueryDeposits
QueryDeposit = types.QueryDeposit
QueryVotes = types.QueryVotes
QueryVote = types.QueryVote
QueryTally = types.QueryTally
ParamDeposit = types.ParamDeposit
ParamVoting = types.ParamVoting
ParamTallying = types.ParamTallying
OptionEmpty = types.OptionEmpty
OptionYes = types.OptionYes
OptionAbstain = types.OptionAbstain
OptionNo = types.OptionNo
OptionNoWithVeto = types.OptionNoWithVeto
)
var (

View File

@ -29,7 +29,7 @@ func TestImportExportQueues(t *testing.T) {
require.NoError(t, err)
proposalID2 := proposal2.ProposalID
err, votingStarted := input.keeper.AddDeposit(ctx, proposalID2, input.addrs[0], input.keeper.GetDepositParams(ctx).MinDeposit)
votingStarted, err := input.keeper.AddDeposit(ctx, proposalID2, input.addrs[0], input.keeper.GetDepositParams(ctx).MinDeposit)
require.NoError(t, err)
require.True(t, votingStarted)

View File

@ -4,12 +4,13 @@ import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/gov/types"
)
// NewHandler creates an sdk.Handler for all the gov type messages
func NewHandler(keeper Keeper) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
ctx = ctx.WithEventManager(sdk.NewEventManager())
switch msg := msg.(type) {
@ -23,21 +24,20 @@ func NewHandler(keeper Keeper) sdk.Handler {
return handleMsgVote(ctx, keeper, msg)
default:
errMsg := fmt.Sprintf("unrecognized gov message type: %T", msg)
return sdk.ErrUnknownRequest(errMsg).Result()
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", ModuleName, msg)
}
}
}
func handleMsgSubmitProposal(ctx sdk.Context, keeper Keeper, msg MsgSubmitProposal) sdk.Result {
func handleMsgSubmitProposal(ctx sdk.Context, keeper Keeper, msg MsgSubmitProposal) (*sdk.Result, error) {
proposal, err := keeper.SubmitProposal(ctx, msg.Content)
if err != nil {
return err.Result()
return nil, err
}
err, votingStarted := keeper.AddDeposit(ctx, proposal.ProposalID, msg.Proposer, msg.InitialDeposit)
votingStarted, err := keeper.AddDeposit(ctx, proposal.ProposalID, msg.Proposer, msg.InitialDeposit)
if err != nil {
return err.Result()
return nil, err
}
ctx.EventManager().EmitEvent(
@ -56,16 +56,16 @@ func handleMsgSubmitProposal(ctx sdk.Context, keeper Keeper, msg MsgSubmitPropos
}
ctx.EventManager().EmitEvent(submitEvent)
return sdk.Result{
return &sdk.Result{
Data: GetProposalIDBytes(proposal.ProposalID),
Events: ctx.EventManager().Events(),
}
}, nil
}
func handleMsgDeposit(ctx sdk.Context, keeper Keeper, msg MsgDeposit) sdk.Result {
err, votingStarted := keeper.AddDeposit(ctx, msg.ProposalID, msg.Depositor, msg.Amount)
func handleMsgDeposit(ctx sdk.Context, keeper Keeper, msg MsgDeposit) (*sdk.Result, error) {
votingStarted, err := keeper.AddDeposit(ctx, msg.ProposalID, msg.Depositor, msg.Amount)
if err != nil {
return err.Result()
return nil, err
}
ctx.EventManager().EmitEvent(
@ -85,13 +85,13 @@ func handleMsgDeposit(ctx sdk.Context, keeper Keeper, msg MsgDeposit) sdk.Result
)
}
return sdk.Result{Events: ctx.EventManager().Events()}
return &sdk.Result{Events: ctx.EventManager().Events()}, nil
}
func handleMsgVote(ctx sdk.Context, keeper Keeper, msg MsgVote) sdk.Result {
func handleMsgVote(ctx sdk.Context, keeper Keeper, msg MsgVote) (*sdk.Result, error) {
err := keeper.AddVote(ctx, msg.ProposalID, msg.Voter, msg.Option)
if err != nil {
return err.Result()
return nil, err
}
ctx.EventManager().EmitEvent(
@ -102,6 +102,5 @@ func handleMsgVote(ctx sdk.Context, keeper Keeper, msg MsgVote) sdk.Result {
),
)
return sdk.Result{Events: ctx.EventManager().Events()}
return &sdk.Result{Events: ctx.EventManager().Events()}, nil
}

View File

@ -15,7 +15,8 @@ func TestInvalidMsg(t *testing.T) {
k := Keeper{}
h := NewHandler(k)
res := h(sdk.NewContext(nil, abci.Header{}, false, nil), sdk.NewTestMsg())
require.False(t, res.IsOK())
require.True(t, strings.Contains(res.Log, "unrecognized gov message type"))
res, err := h(sdk.NewContext(nil, abci.Header{}, false, nil), sdk.NewTestMsg())
require.Error(t, err)
require.Nil(t, res)
require.True(t, strings.Contains(err.Error(), "unrecognized gov message type"))
}

View File

@ -4,6 +4,7 @@ import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/gov/types"
)
@ -93,22 +94,22 @@ func (keeper Keeper) IterateDeposits(ctx sdk.Context, proposalID uint64, cb func
// AddDeposit adds or updates a deposit of a specific depositor on a specific proposal
// Activates voting period when appropriate
func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress, depositAmount sdk.Coins) (sdk.Error, bool) {
func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress, depositAmount sdk.Coins) (bool, error) {
// Checks to see if proposal exists
proposal, ok := keeper.GetProposal(ctx, proposalID)
if !ok {
return types.ErrUnknownProposal(keeper.codespace, proposalID), false
return false, sdkerrors.Wrapf(types.ErrUnknownProposal, "%d", proposalID)
}
// Check if proposal is still depositable
if (proposal.Status != types.StatusDepositPeriod) && (proposal.Status != types.StatusVotingPeriod) {
return types.ErrInactiveProposal(keeper.codespace, proposalID), false
return false, sdkerrors.Wrapf(types.ErrInactiveProposal, "%d", proposalID)
}
// update the governance module's account coins pool
err := keeper.supplyKeeper.SendCoinsFromAccountToModule(ctx, depositorAddr, types.ModuleName, depositAmount)
if err != nil {
return err, false
return false, err
}
// Update proposal
@ -139,7 +140,7 @@ func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID uint64, depositorAdd
)
keeper.SetDeposit(ctx, deposit)
return nil, activatedVotingPeriod
return activatedVotingPeriod, nil
}
// RefundDeposits refunds and deletes all the deposits on a specific proposal

View File

@ -33,7 +33,7 @@ func TestDeposits(t *testing.T) {
require.True(t, proposal.VotingStartTime.Equal(time.Time{}))
// Check first deposit
err, votingStarted := keeper.AddDeposit(ctx, proposalID, TestAddrs[0], fourStake)
votingStarted, err := keeper.AddDeposit(ctx, proposalID, TestAddrs[0], fourStake)
require.NoError(t, err)
require.False(t, votingStarted)
deposit, found = keeper.GetDeposit(ctx, proposalID, TestAddrs[0])
@ -46,7 +46,7 @@ func TestDeposits(t *testing.T) {
require.Equal(t, addr0Initial.Sub(fourStake), ak.GetAccount(ctx, TestAddrs[0]).GetCoins())
// Check a second deposit from same address
err, votingStarted = keeper.AddDeposit(ctx, proposalID, TestAddrs[0], fiveStake)
votingStarted, err = keeper.AddDeposit(ctx, proposalID, TestAddrs[0], fiveStake)
require.NoError(t, err)
require.False(t, votingStarted)
deposit, found = keeper.GetDeposit(ctx, proposalID, TestAddrs[0])
@ -59,7 +59,7 @@ func TestDeposits(t *testing.T) {
require.Equal(t, addr0Initial.Sub(fourStake).Sub(fiveStake), ak.GetAccount(ctx, TestAddrs[0]).GetCoins())
// Check third deposit from a new address
err, votingStarted = keeper.AddDeposit(ctx, proposalID, TestAddrs[1], fourStake)
votingStarted, err = keeper.AddDeposit(ctx, proposalID, TestAddrs[1], fourStake)
require.NoError(t, err)
require.True(t, votingStarted)
deposit, found = keeper.GetDeposit(ctx, proposalID, TestAddrs[1])

View File

@ -29,9 +29,6 @@ type Keeper struct {
// The codec codec for binary encoding/decoding.
cdc *codec.Codec
// Reserved codespace
codespace sdk.CodespaceType
// Proposal router
router types.Router
}
@ -45,7 +42,7 @@ type Keeper struct {
// CONTRACT: the parameter Subspace must have the param key table already initialized
func NewKeeper(
cdc *codec.Codec, key sdk.StoreKey, paramSpace types.ParamSubspace,
supplyKeeper types.SupplyKeeper, sk types.StakingKeeper, codespace sdk.CodespaceType, rtr types.Router,
supplyKeeper types.SupplyKeeper, sk types.StakingKeeper, rtr types.Router,
) Keeper {
// ensure governance module account is set
@ -64,7 +61,6 @@ func NewKeeper(
supplyKeeper: supplyKeeper,
sk: sk,
cdc: cdc,
codespace: codespace,
router: rtr,
}
}

View File

@ -5,13 +5,14 @@ import (
"github.com/cosmos/cosmos-sdk/client"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/gov/types"
)
// SubmitProposal create new proposal given a content
func (keeper Keeper) SubmitProposal(ctx sdk.Context, content types.Content) (types.Proposal, sdk.Error) {
func (keeper Keeper) SubmitProposal(ctx sdk.Context, content types.Content) (types.Proposal, error) {
if !keeper.router.HasRoute(content.ProposalRoute()) {
return types.Proposal{}, types.ErrNoProposalHandlerExists(keeper.codespace, content)
return types.Proposal{}, sdkerrors.Wrap(types.ErrNoProposalHandlerExists, content.ProposalRoute())
}
// Execute the proposal content in a cache-wrapped context to validate the
@ -20,7 +21,7 @@ func (keeper Keeper) SubmitProposal(ctx sdk.Context, content types.Content) (typ
cacheCtx, _ := ctx.CacheContext()
handler := keeper.router.GetRoute(content.ProposalRoute())
if err := handler(cacheCtx, content); err != nil {
return types.Proposal{}, types.ErrInvalidProposalContent(keeper.codespace, err.Result().Log)
return types.Proposal{}, sdkerrors.Wrap(types.ErrInvalidProposalContent, err.Error())
}
proposalID, err := keeper.GetProposalID(ctx)
@ -149,12 +150,13 @@ func (keeper Keeper) GetProposalsFiltered(ctx sdk.Context, params types.QueryPro
}
// GetProposalID gets the highest proposal ID
func (keeper Keeper) GetProposalID(ctx sdk.Context) (proposalID uint64, err sdk.Error) {
func (keeper Keeper) GetProposalID(ctx sdk.Context) (proposalID uint64, err error) {
store := ctx.KVStore(keeper.storeKey)
bz := store.Get(types.ProposalIDKey)
if bz == nil {
return 0, types.ErrInvalidGenesis(keeper.codespace, "initial proposal ID hasn't been set")
return 0, sdkerrors.Wrap(types.ErrInvalidGenesis, "initial proposal ID hasn't been set")
}
proposalID = types.GetProposalIDFromBytes(bz)
return proposalID, nil
}

View File

@ -1,6 +1,7 @@
package keeper
import (
"errors"
"strings"
"testing"
"time"
@ -51,12 +52,12 @@ func TestActivateVotingPeriod(t *testing.T) {
type validProposal struct{}
func (validProposal) GetTitle() string { return "title" }
func (validProposal) GetDescription() string { return "description" }
func (validProposal) ProposalRoute() string { return types.RouterKey }
func (validProposal) ProposalType() string { return types.ProposalTypeText }
func (validProposal) String() string { return "" }
func (validProposal) ValidateBasic() sdk.Error { return nil }
func (validProposal) GetTitle() string { return "title" }
func (validProposal) GetDescription() string { return "description" }
func (validProposal) ProposalRoute() string { return types.RouterKey }
func (validProposal) ProposalType() string { return types.ProposalTypeText }
func (validProposal) String() string { return "" }
func (validProposal) ValidateBasic() error { return nil }
type invalidProposalTitle1 struct{ validProposal }
@ -80,8 +81,8 @@ func (invalidProposalRoute) ProposalRoute() string { return "nonexistingroute" }
type invalidProposalValidation struct{ validProposal }
func (invalidProposalValidation) ValidateBasic() sdk.Error {
return sdk.NewError(sdk.CodespaceUndefined, sdk.CodeInternal, "")
func (invalidProposalValidation) ValidateBasic() error {
return errors.New("invalid proposal")
}
func registerTestCodec(cdc *codec.Codec) {
@ -101,7 +102,7 @@ func TestSubmitProposal(t *testing.T) {
testCases := []struct {
content types.Content
expectedErr sdk.Error
expectedErr error
}{
{validProposal{}, nil},
// Keeper does not check the validity of title and description, no error
@ -110,14 +111,14 @@ func TestSubmitProposal(t *testing.T) {
{invalidProposalDesc1{}, nil},
{invalidProposalDesc2{}, nil},
// error only when invalid route
{invalidProposalRoute{}, types.ErrNoProposalHandlerExists(types.DefaultCodespace, invalidProposalRoute{})},
{invalidProposalRoute{}, types.ErrNoProposalHandlerExists},
// Keeper does not call ValidateBasic, msg.ValidateBasic does
{invalidProposalValidation{}, nil},
}
for _, tc := range testCases {
for i, tc := range testCases {
_, err := keeper.SubmitProposal(ctx, tc.content)
require.Equal(t, tc.expectedErr, err, "unexpected type of error: %s", err)
require.True(t, errors.Is(tc.expectedErr, err), "tc #%d; got: %v, expected: %v", i, err, tc.expectedErr)
}
}

View File

@ -1,19 +1,18 @@
package keeper
import (
"fmt"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/gov/types"
)
// NewQuerier creates a new gov Querier instance
func NewQuerier(keeper Keeper) sdk.Querier {
return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, sdk.Error) {
return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) {
switch path[0] {
case types.QueryParams:
return queryParams(ctx, path[1:], req, keeper)
@ -40,94 +39,100 @@ func NewQuerier(keeper Keeper) sdk.Querier {
return queryTally(ctx, path[1:], req, keeper)
default:
return nil, sdk.ErrUnknownRequest("unknown gov query endpoint")
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown query path: %s", path[0])
}
}
}
func queryParams(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
func queryParams(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, error) {
switch path[0] {
case types.ParamDeposit:
bz, err := codec.MarshalJSONIndent(keeper.cdc, keeper.GetDepositParams(ctx))
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
case types.ParamVoting:
bz, err := codec.MarshalJSONIndent(keeper.cdc, keeper.GetVotingParams(ctx))
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
case types.ParamTallying:
bz, err := codec.MarshalJSONIndent(keeper.cdc, keeper.GetTallyParams(ctx))
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
default:
return nil, sdk.ErrUnknownRequest(fmt.Sprintf("%s is not a valid query request path", req.Path))
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "%s is not a valid query request path", req.Path)
}
}
// nolint: unparam
func queryProposal(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
func queryProposal(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, error) {
var params types.QueryProposalParams
err := keeper.cdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
proposal, ok := keeper.GetProposal(ctx, params.ProposalID)
if !ok {
return nil, types.ErrUnknownProposal(types.DefaultCodespace, params.ProposalID)
return nil, sdkerrors.Wrapf(types.ErrUnknownProposal, "%d", params.ProposalID)
}
bz, err := codec.MarshalJSONIndent(keeper.cdc, proposal)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
}
// nolint: unparam
func queryDeposit(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
func queryDeposit(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, error) {
var params types.QueryDepositParams
err := keeper.cdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
deposit, _ := keeper.GetDeposit(ctx, params.ProposalID, params.Depositor)
bz, err := codec.MarshalJSONIndent(keeper.cdc, deposit)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
}
// nolint: unparam
func queryVote(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
func queryVote(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, error) {
var params types.QueryVoteParams
err := keeper.cdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
vote, _ := keeper.GetVote(ctx, params.ProposalID, params.Voter)
bz, err := codec.MarshalJSONIndent(keeper.cdc, vote)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
}
// nolint: unparam
func queryDeposits(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
func queryDeposits(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, error) {
var params types.QueryProposalParams
err := keeper.cdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
deposits := keeper.GetDeposits(ctx, params.ProposalID)
@ -137,24 +142,25 @@ func queryDeposits(ctx sdk.Context, path []string, req abci.RequestQuery, keeper
bz, err := codec.MarshalJSONIndent(keeper.cdc, deposits)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
}
// nolint: unparam
func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, error) {
var params types.QueryProposalParams
err := keeper.cdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
proposalID := params.ProposalID
proposal, ok := keeper.GetProposal(ctx, proposalID)
if !ok {
return nil, types.ErrUnknownProposal(types.DefaultCodespace, proposalID)
return nil, sdkerrors.Wrapf(types.ErrUnknownProposal, "%d", proposalID)
}
var tallyResult types.TallyResult
@ -162,8 +168,10 @@ func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Ke
switch {
case proposal.Status == types.StatusDepositPeriod:
tallyResult = types.EmptyTallyResult()
case proposal.Status == types.StatusPassed || proposal.Status == types.StatusRejected:
tallyResult = proposal.FinalTallyResult
default:
// proposal is in voting period
_, _, tallyResult = keeper.Tally(ctx, proposal)
@ -171,18 +179,18 @@ func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Ke
bz, err := codec.MarshalJSONIndent(keeper.cdc, tallyResult)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
}
// nolint: unparam
func queryVotes(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
func queryVotes(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, error) {
var params types.QueryProposalVotesParams
err := keeper.cdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
votes := keeper.GetVotes(ctx, params.ProposalID)
@ -199,17 +207,17 @@ func queryVotes(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Ke
bz, err := codec.MarshalJSONIndent(keeper.cdc, votes)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil
}
func queryProposals(ctx sdk.Context, _ []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
func queryProposals(ctx sdk.Context, _ []string, req abci.RequestQuery, keeper Keeper) ([]byte, error) {
var params types.QueryProposalsParams
err := keeper.cdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("failed to parse params", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
proposals := keeper.GetProposalsFiltered(ctx, params)
@ -219,7 +227,7 @@ func queryProposals(ctx sdk.Context, _ []string, req abci.RequestQuery, keeper K
bz, err := codec.MarshalJSONIndent(keeper.cdc, proposals)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to JSON marshal result: %s", err.Error()))
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
}
return bz, nil

View File

@ -156,7 +156,7 @@ func TestQueries(t *testing.T) {
proposal1, err := keeper.SubmitProposal(ctx, tp)
require.NoError(t, err)
deposit1 := types.NewDeposit(proposal1.ProposalID, TestAddrs[0], oneCoins)
err, _ = keeper.AddDeposit(ctx, deposit1.ProposalID, deposit1.Depositor, deposit1.Amount)
_, err = keeper.AddDeposit(ctx, deposit1.ProposalID, deposit1.Depositor, deposit1.Amount)
require.NoError(t, err)
proposal1.TotalDeposit = proposal1.TotalDeposit.Add(deposit1.Amount)
@ -164,7 +164,7 @@ func TestQueries(t *testing.T) {
proposal2, err := keeper.SubmitProposal(ctx, tp)
require.NoError(t, err)
deposit2 := types.NewDeposit(proposal2.ProposalID, TestAddrs[0], consCoins)
err, _ = keeper.AddDeposit(ctx, deposit2.ProposalID, deposit2.Depositor, deposit2.Amount)
_, err = keeper.AddDeposit(ctx, deposit2.ProposalID, deposit2.Depositor, deposit2.Amount)
require.NoError(t, err)
proposal2.TotalDeposit = proposal2.TotalDeposit.Add(deposit2.Amount)
@ -173,14 +173,14 @@ func TestQueries(t *testing.T) {
proposal3, err := keeper.SubmitProposal(ctx, tp)
require.NoError(t, err)
deposit3 := types.NewDeposit(proposal3.ProposalID, TestAddrs[1], oneCoins)
err, _ = keeper.AddDeposit(ctx, deposit3.ProposalID, deposit3.Depositor, deposit3.Amount)
_, err = keeper.AddDeposit(ctx, deposit3.ProposalID, deposit3.Depositor, deposit3.Amount)
require.NoError(t, err)
proposal3.TotalDeposit = proposal3.TotalDeposit.Add(deposit3.Amount)
// TestAddrs[1] deposits on proposals #2 & #3
deposit4 := types.NewDeposit(proposal2.ProposalID, TestAddrs[1], depositParams.MinDeposit)
err, _ = keeper.AddDeposit(ctx, deposit4.ProposalID, deposit4.Depositor, deposit4.Amount)
_, err = keeper.AddDeposit(ctx, deposit4.ProposalID, deposit4.Depositor, deposit4.Amount)
require.NoError(t, err)
proposal2.TotalDeposit = proposal2.TotalDeposit.Add(deposit4.Amount)
@ -188,7 +188,7 @@ func TestQueries(t *testing.T) {
proposal2.VotingEndTime = proposal2.VotingEndTime.Add(types.DefaultPeriod)
deposit5 := types.NewDeposit(proposal3.ProposalID, TestAddrs[1], depositParams.MinDeposit)
err, _ = keeper.AddDeposit(ctx, deposit5.ProposalID, deposit5.Depositor, deposit5.Amount)
_, err = keeper.AddDeposit(ctx, deposit5.ProposalID, deposit5.Depositor, deposit5.Amount)
require.NoError(t, err)
proposal3.TotalDeposit = proposal3.TotalDeposit.Add(deposit5.Amount)

View File

@ -139,19 +139,19 @@ func createTestInput(t *testing.T, isCheckTx bool, initPower int64) (sdk.Context
blacklistedAddrs[notBondedPool.GetAddress().String()] = true
blacklistedAddrs[bondPool.GetAddress().String()] = true
pk := params.NewKeeper(cdc, keyParams, tkeyParams, params.DefaultCodespace)
pk := params.NewKeeper(cdc, keyParams, tkeyParams)
accountKeeper := auth.NewAccountKeeper(cdc, keyAcc, pk.Subspace(auth.DefaultParamspace), auth.ProtoBaseAccount)
bankKeeper := bank.NewBaseKeeper(accountKeeper, pk.Subspace(bank.DefaultParamspace), bank.DefaultCodespace, blacklistedAddrs)
bankKeeper := bank.NewBaseKeeper(accountKeeper, pk.Subspace(bank.DefaultParamspace), blacklistedAddrs)
supplyKeeper := supply.NewKeeper(cdc, keySupply, accountKeeper, bankKeeper, maccPerms)
sk := staking.NewKeeper(cdc, keyStaking, supplyKeeper, pk.Subspace(staking.DefaultParamspace), staking.DefaultCodespace)
sk := staking.NewKeeper(cdc, keyStaking, supplyKeeper, pk.Subspace(staking.DefaultParamspace))
sk.SetParams(ctx, staking.DefaultParams())
rtr := types.NewRouter().
AddRoute(types.RouterKey, types.ProposalHandler)
keeper := NewKeeper(
cdc, keyGov, pk.Subspace(types.DefaultParamspace).WithKeyTable(types.ParamKeyTable()), supplyKeeper, sk, types.DefaultCodespace, rtr,
cdc, keyGov, pk.Subspace(types.DefaultParamspace).WithKeyTable(types.ParamKeyTable()), supplyKeeper, sk, rtr,
)
keeper.SetProposalID(ctx, types.DefaultStartingProposalID)

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