Merge PR #5421: Refactor Error Handling
This commit is contained in:
parent
3c82b66347
commit
9a183ffbcc
15
CHANGELOG.md
15
CHANGELOG.md
|
@ -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
|
||||
|
|
176
baseapp/abci.go
176
baseapp/abci.go
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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
|
||||
}
|
||||
```
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
361
types/errors.go
361
types/errors.go
|
@ -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"`
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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",
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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, ¶ms); 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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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"))
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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, ¶ms); 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
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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, ¶ms)
|
||||
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, ¶ms)
|
||||
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, ¶ms)
|
||||
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, ¶ms)
|
||||
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, ¶ms)
|
||||
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, ¶ms)
|
||||
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, ¶ms)
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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)))))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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"))
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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, ¶ms)
|
||||
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, ¶ms)
|
||||
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, ¶ms)
|
||||
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, ¶ms)
|
||||
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, ¶ms)
|
||||
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, ¶ms)
|
||||
|
||||
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, ¶ms)
|
||||
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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue