diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml deleted file mode 100644 index f58e2ed1e..000000000 --- a/.github/workflows/docs.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Documentation -# This job builds and deploys documenation to github pages. -# It runs on every push to master. -on: - push: - branches: - - master - -jobs: - build-and-deploy: - runs-on: ubuntu-latest - container: - image: tendermintdev/docker-website-deployment - steps: - - name: Checkout 🛎️ - uses: actions/checkout@v2.3.1 - with: - persist-credentials: false - fetch-depth: 0 - - - name: Install and Build 🔧 - run: | - apk add rsync - make build-docs LEDGER_ENABLED=false - - - name: Deploy 🚀 - uses: JamesIves/github-pages-deploy-action@4.1.1 - with: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - BRANCH: gh-pages - FOLDER: ~/output diff --git a/Makefile b/Makefile index a26681ea8..68bf071dd 100644 --- a/Makefile +++ b/Makefile @@ -369,24 +369,33 @@ devdoc-update: ### Protobuf ### ############################################################################### +containerProtoVer=v0.2 +containerProtoImage=tendermintdev/sdk-proto-gen:$(containerProtoVer) +containerProtoGen=cosmos-sdk-proto-gen-$(containerProtoVer) +containerProtoGenSwagger=cosmos-sdk-proto-gen-swagger-$(containerProtoVer) +containerProtoFmt=cosmos-sdk-proto-fmt-$(containerProtoVer) + proto-all: proto-format proto-lint proto-gen proto-gen: @echo "Generating Protobuf files" - $(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace tendermintdev/sdk-proto-gen:v0.1 sh ./scripts/protocgen.sh - -proto-format: - @echo "Formatting Protobuf files" - $(DOCKER) run --rm -v $(CURDIR):/workspace \ - --workdir /workspace tendermintdev/docker-build-proto \ - find ./ -not -path "./third_party/*" -name *.proto -exec clang-format -i {} \; + @if docker ps -a --format '{{.Names}}' | grep -Eq "^${containerProtoGen}$$"; then docker start -a $(containerProtoGen); else docker run --name $(containerProtoGen) -v $(CURDIR):/workspace --workdir /workspace $(containerProtoImage) \ + sh ./scripts/protocgen.sh; fi # This generates the SDK's custom wrapper for google.protobuf.Any. It should only be run manually when needed proto-gen-any: - $(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace tendermintdev/sdk-proto-gen sh ./scripts/protocgen-any.sh + @echo "Generating Protobuf Any" + $(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace $(containerProtoImage) sh ./scripts/protocgen-any.sh proto-swagger-gen: - $(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace tendermintdev/sdk-proto-gen sh ./scripts/protoc-swagger-gen.sh + @echo "Generating Protobuf Swagger" + @if docker ps -a --format '{{.Names}}' | grep -Eq "^${containerProtoGenSwagger}$$"; then docker start -a $(containerProtoGenSwagger); else docker run --name $(containerProtoGenSwagger) -v $(CURDIR):/workspace --workdir /workspace $(containerProtoImage) \ + sh ./scripts/protoc-swagger-gen.sh; fi + +proto-format: + @echo "Formatting Protobuf files" + @if docker ps -a --format '{{.Names}}' | grep -Eq "^${containerProtoFmt}$$"; then docker start -a $(containerProtoFmt); else docker run --name $(containerProtoFmt) -v $(CURDIR):/workspace --workdir /workspace $(containerProtoImage) \ + find ./ -not -path "./third_party/*" -name *.proto -exec clang-format -i {}; fi proto-lint: @$(DOCKER_BUF) lint --error-format=json @@ -394,6 +403,7 @@ proto-lint: proto-check-breaking: @$(DOCKER_BUF) breaking --against $(HTTPS_GIT)#branch=master + TM_URL = https://raw.githubusercontent.com/tendermint/tendermint/v0.34.0-rc6/proto/tendermint GOGO_PROTO_URL = https://raw.githubusercontent.com/regen-network/protobuf/cosmos COSMOS_PROTO_URL = https://raw.githubusercontent.com/regen-network/cosmos-proto/master diff --git a/docs/README.md b/docs/README.md index 18398752a..0a81978d3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -48,36 +48,36 @@ aside: false ## Get Started - **[SDK Intro](./intro/overview.md)**: High-level overview of the Cosmos SDK. -- **[Quick Start Guide](./using-the-sdk/quick-start.md)**: Scaffold a standard Cosmos SDK app and run a node. -- **[SDK Application Tutorial](https://github.com/cosmos/sdk-application-tutorial)**: A tutorial that showcases how to build an SDK-based blockchain from scratch and explains the basic principles of the SDK in the process. +- **[Starport](https://github.com/tendermint/starport/blob/develop/docs/README.md)**: A developer-friendly interface to the Cosmos SDK to scaffold a standard Cosmos SDK blockchain app. +- **[SDK Application Tutorial](https://github.com/cosmos/sdk-application-tutorial)**: A tutorial that showcases how to build a Cosmos SDK-based blockchain from scratch and explains the basic principles of the SDK in the process. ## Reference -- **[Basics](./basics/)**: Documentation on the basic concepts of the Cosmos SDK, like the standard anatomy of an application, the transaction lifecycle and accounts management. -- **[Core](./core/)**: Documentation on the core concepts of the Cosmos SDK, like `baseapp`, the `store` or the `server`. -- **[Building Modules](./building-modules/)**: Important concepts for module developers like `message`s, `keeper`s, `handler`s and `querier`s. +- **[Basics](./basics/)**: Documentation on the basic concepts of the Cosmos SDK, like the standard anatomy of an application, the transaction lifecycle, and accounts management. +- **[Core](./core/)**: Documentation on the core concepts of the Cosmos SDK, like `baseapp`, the `store`, or the `server`. +- **[Building Modules](./building-modules/)**: Important concepts for module developers like `message`, `keeper`, `handler`, and `querier`. - **[IBC](./ibc/)**: Documentation for the IBC protocol integration and concepts. -- **[Running a Node, API, CLI](./run-node/)**: Documentation on how to run a node, and how to interact with it using the CLI and the API. +- **[Running a Node, API, CLI](./run-node/)**: Documentation on how to run a node and interact with the node using the CLI and the API. - **[Migrations](./migrations/)**: Migration guides for updating to Stargate. ## Other Resources -- **[Module Directory](../x/)**: Module implementations and their respective documentation. +- **[Module Directory](../x/)**: Cosmos SDK module implementations and their respective documentation. - **[Specifications](./spec/)**: Specifications of modules and other parts of the Cosmos SDK. - **[SDK API Reference](https://godoc.org/github.com/cosmos/cosmos-sdk)**: Godocs of the Cosmos SDK. - **[REST API spec](https://cosmos.network/rpc/)**: List of endpoints to interact with a `gaia` full-node through REST. ## Cosmos Hub -The Cosmos Hub (`gaia`) docs have moved [here](https://github.com/cosmos/gaia/tree/master/docs). +The Cosmos Hub (`gaia`) docs have moved to [github.com/cosmos/gaia](https://github.com/cosmos/gaia/tree/master/docs). ## Languages -The Cosmos-SDK is currently written in [Golang](https://golang.org/), though the +The Cosmos SDK is written in [Golang](https://golang.org/), though the framework could be implemented similarly in other languages. Contact us for information about funding an implementation in another language. ## Contribute -See [this file](https://github.com/cosmos/cosmos-sdk/blob/master/docs/DOCS_README.md) for details of the build process and +See the [DOCS_README.md](https://github.com/cosmos/cosmos-sdk/blob/master/docs/DOCS_README.md) for details of the build process and considerations when making changes. diff --git a/docs/architecture/README.md b/docs/architecture/README.md index f62d50891..310c503ce 100644 --- a/docs/architecture/README.md +++ b/docs/architecture/README.md @@ -41,7 +41,6 @@ Read about the [PROCESS](./PROCESS.md). ### Accepted -- [ADR 001: Coin Source Tracing](./adr-001-coin-source-tracing.md) - [ADR 002: SDK Documentation Structure](./adr-002-docs-structure.md) - [ADR 004: Split Denomination Keys](./adr-004-split-denomination-keys.md) - [ADR 006: Secret Store Replacement](./adr-006-secret-store-replacement.md) @@ -51,7 +50,6 @@ Read about the [PROCESS](./PROCESS.md). - [ADR 020: Protocol Buffer Transaction Encoding](./adr-020-protobuf-transaction-encoding.md) - [ADR 021: Protocol Buffer Query Encoding](./adr-021-protobuf-query-encoding.md) - [ADR 023: Protocol Buffer Naming and Versioning](./adr-023-protobuf-naming.md) -- [ADR 026: IBC Client Recovery Mechanisms](./adr-026-ibc-client-recovery-mechanisms.md) - [ADR 029: Fee Grant Module](./adr-029-fee-grant-module.md) - [ADR 030: Message Authorization Module](architecture/adr-030-authz-module.md) - [ADR 031: Protobuf Msg Services](./adr-031-msg-service.md) @@ -62,13 +60,11 @@ Read about the [PROCESS](./PROCESS.md). - [ADR 011: Generalize Genesis Accounts](./adr-011-generalize-genesis-accounts.md) - [ADR 012: State Accessors](./adr-012-state-accessors.md) - [ADR 013: Metrics](./adr-013-metrics.md) -- [ADR 015: IBC Packet Receiver](./adr-015-ibc-packet-receiver.md) - [ADR 016: Validator Consensus Key Rotation](./adr-016-validator-consensus-key-rotation.md) - [ADR 017: Historical Header Module](./adr-017-historical-header-module.md) - [ADR 018: Extendable Voting Periods](./adr-018-extendable-voting-period.md) - [ADR 022: Custom baseapp panic handling](./adr-022-custom-panic-handling.md) - [ADR 024: Coin Metadata](./adr-024-coin-metadata.md) -- [ADR 025: IBC Passive Channels](./adr-025-ibc-passive-channels.md) - [ADR 027: Deterministic Protobuf Serialization](./adr-027-deterministic-protobuf-serialization.md) - [ADR 028: Public Key Addresses](./adr-028-public-key-addresses.md) - [ADR 032: Typed Events](./adr-032-typed-events.md) @@ -76,4 +72,4 @@ Read about the [PROCESS](./PROCESS.md). - [ADR 035: Rosetta API Support](./adr-035-rosetta-api-support.md) - [ADR 037: Governance Split Votes](./adr-037-gov-split-vote.md) - [ADR 038: State Listening](./adr-038-state-listening.md) -- [ADR 039: Epoched Staking](./adr-039-epoched-staking.md) \ No newline at end of file +- [ADR 039: Epoched Staking](./adr-039-epoched-staking.md) diff --git a/docs/architecture/adr-001-coin-source-tracing.md b/docs/architecture/adr-001-coin-source-tracing.md deleted file mode 100644 index d5364d1c0..000000000 --- a/docs/architecture/adr-001-coin-source-tracing.md +++ /dev/null @@ -1,376 +0,0 @@ -# ADR 001: Coin Source Tracing - -## Changelog - -- 2020-07-09: Initial Draft -- 2020-08-11: Implementation changes - -## Status - -Accepted, Implemented - -## Context - -The specification for IBC cross-chain fungible token transfers -([ICS20](https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer)), needs to -be aware of the origin of any token denomination in order to relay a `Packet` which contains the sender -and recipient addressed in the -[`FungibleTokenPacketData`](https://github.com/cosmos/ibc/tree/master/spec/app/ics-020-fungible-token-transfer#data-structures). - -The Packet relay sending works based in 2 cases (per -[specification](https://github.com/cosmos/ibc/tree/master/spec/app/ics-020-fungible-token-transfer#packet-relay) and [Colin Axnér](https://github.com/colin-axner)'s description): - -1. Sender chain is acting as the source zone. The coins are transferred -to an escrow address (i.e locked) on the sender chain and then transferred -to the receiving chain through IBC TAO logic. It is expected that the -receiving chain will mint vouchers to the receiving address. - -2. Sender chain is acting as the sink zone. The coins (vouchers) are burned -on the sender chain and then transferred to the receiving chain though IBC -TAO logic. It is expected that the receiving chain, which had previously -sent the original denomination, will unescrow the fungible token and send -it to the receiving address. - -Another way of thinking of source and sink zones is through the token's -timeline. Each send to any chain other than the one it was previously -received from is a movement forwards in the token's timeline. This causes -trace to be added to the token's history and the destination port and -destination channel to be prefixed to the denomination. In these instances -the sender chain is acting as the source zone. When the token is sent back -to the chain it previously received from, the prefix is removed. This is -a backwards movement in the token's timeline and the sender chain -is acting as the sink zone. - -### Example - -Assume the following channel connections exist and that all channels use the port ID `transfer`: - -- chain `A` has channels with chain `B` and chain `C` with the IDs `channelToB` and `channelToC`, respectively -- chain `B` has channels with chain `A` and chain `C` with the IDs `channelToA` and `channelToC`, respectively -- chain `C` has channels with chain `A` and chain `B` with the IDs `channelToA` and `channelToB`, respectively - -These steps of transfer between chains occur in the following order: `A -> B -> C -> A -> C`. In particular: - -1. `A -> B`: sender chain is source zone. `A` sends packet with `denom` (escrowed on `A`), `B` receives `denom` and mints and sends voucher `transfer/channelToA/denom` to recipient. -2. `B -> C`: sender chain is source zone. `B` sends packet with `transfer/channelToA/denom` (escrowed on `B`), `C` receives `transfer/channelToA/denom` and mints and sends voucher `transfer/channelToB/transfer/channelToA/denom` to recipient. -3. `C -> A`: sender chain is source zone. `C` sends packet with `transfer/channelToB/transfer/channelToA/denom` (escrowed on `C`), `A` receives `transfer/channelToB/transfer/channelToA/denom` and mints and sends voucher `transfer/channelToC/transfer/channelToB/transfer/channelToA/denom` to recipient. -4. `A -> C`: sender chain is sink zone. `A` sends packet with `transfer/channelToC/transfer/channelToB/transfer/channelToA/denom` (burned on `A`), `C` receives `transfer/channelToC/transfer/channelToB/transfer/channelToA/denom`, and unescrows and sends `transfer/channelToB/transfer/channelToA/denom` to recipient. - -The token has a final denomination on chain `C` of `transfer/channelToB/transfer/channelToA/denom`, where `transfer/channelToB/transfer/channelToA` is the trace information. - -In this context, upon a receive of a cross-chain fungible token transfer, if the sender chain is the source of the token, the protocol prefixes the denomination with the port and channel identifiers in the following format: - -```typescript -prefix + denom = {destPortN}/{destChannelN}/.../{destPort0}/{destChannel0}/denom -``` - -Example: transferring `100 uatom` from port `HubPort` and channel `HubChannel` on the Hub to -Ethermint's port `EthermintPort` and channel `EthermintChannel` results in `100 -EthermintPort/EthermintChannel/uatom`, where `EthermintPort/EthermintChannel/uatom` is the new -denomination on the receiving chain. - -In the case those tokens are transferred back to the Hub (i.e the **source** chain), the prefix is -trimmed and the token denomination updated to the original one. - -### Problem - -The problem of adding additional information to the coin denomination is twofold: - -1. The ever increasing length if tokens are transferred to zones other than the source: - -If a token is transferred `n` times via IBC to a sink chain, the token denom will contain `n` pairs -of prefixes, as shown on the format example above. This poses a problem because, while port and -channel identifiers have a maximum length of 64 each, the SDK `Coin` type only accepts denoms up to -64 characters. Thus, a single cross-chain token, which again, is composed by the port and channels -identifiers plus the base denomination, can exceed the length validation for the SDK `Coins`. - -This can result in undesired behaviours such as tokens not being able to be transferred to multiple -sink chains if the denomination exceeds the length or unexpected `panics` due to denomination -validation failing on the receiving chain. - -2. The existence of special characters and uppercase letters on the denomination: - -In the SDK every time a `Coin` is initialized through the constructor function `NewCoin`, a validation -of a coin's denom is performed according to a -[Regex](https://github.com/cosmos/cosmos-sdk/blob/a940214a4923a3bf9a9161cd14bd3072299cd0c9/types/coin.go#L583), -where only lowercase alphanumeric characters are accepted. While this is desirable for native denominations -to keep a clean UX, it presents a challenge for IBC as ports and channels might be randomly -generated with special and uppercase characters as per the [ICS 024 - Host -Requirements](https://github.com/cosmos/ibc/tree/master/spec/core/ics-024-host-requirements#paths-identifiers-separators) -specification. - -## Decision - -The issues outlined above, are applicable only to SDK-based chains, and thus the proposed solution -are do not require specification changes that would result in modification to other implementations -of the ICS20 spec. - -Instead of adding the identifiers on the coin denomination directly, the proposed solution hashes -the denomination prefix in order to get a consistent length for all the cross-chain fungible tokens. - -This will be used for internal storage only, and when transferred via IBC to a different chain, the -denomination specified on the packed data will be the full prefix path of the identifiers needed to -trace the token back to the originating chain, as specified on ICS20. - -The new proposed format will be the following: - -```golang -ibcDenom = "ibc/" + hash(trace path + "/" + base denom) -``` - -The hash function will be a SHA256 hash of the fields of the `DenomTrace`: - -```protobuf -// DenomTrace contains the base denomination for ICS20 fungible tokens and the source tracing -// information -message DenomTrace { - // chain of port/channel identifiers used for tracing the source of the fungible token - string path = 1; - // base denomination of the relayed fungible token - string base_denom = 2; -} -``` - -The `IBCDenom` function constructs the `Coin` denomination used when creating the ICS20 fungible token packet data: - -```golang -// Hash returns the hex bytes of the SHA256 hash of the DenomTrace fields using the following formula: -// -// hash = sha256(tracePath + "/" + baseDenom) -func (dt DenomTrace) Hash() tmbytes.HexBytes { - return tmhash.Sum(dt.Path + "/" + dt.BaseDenom) -} - -// IBCDenom a coin denomination for an ICS20 fungible token in the format 'ibc/{hash(tracePath + baseDenom)}'. -// If the trace is empty, it will return the base denomination. -func (dt DenomTrace) IBCDenom() string { - if dt.Path != "" { - return fmt.Sprintf("ibc/%s", dt.Hash()) - } - return dt.BaseDenom -} -``` - -### `x/ibc-transfer` Changes - -In order to retrieve the trace information from an IBC denomination, a lookup table needs to be -added to the `ibc-transfer` module. These values need to also be persisted between upgrades, meaning -that a new `[]DenomTrace` `GenesisState` field state needs to be added to the module: - -```golang -// GetDenomTrace retrieves the full identifiers trace and base denomination from the store. -func (k Keeper) GetDenomTrace(ctx Context, denomTraceHash []byte) (DenomTrace, bool) { - store := ctx.KVStore(k.storeKey) - bz := store.Get(types.KeyDenomTrace(traceHash)) - if bz == nil { - return &DenomTrace, false - } - - var denomTrace DenomTrace - k.cdc.MustUnmarshalBinaryBare(bz, &denomTrace) - return denomTrace, true -} - -// HasDenomTrace checks if a the key with the given trace hash exists on the store. -func (k Keeper) HasDenomTrace(ctx Context, denomTraceHash []byte) bool { - store := ctx.KVStore(k.storeKey) - return store.Has(types.KeyTrace(denomTraceHash)) -} - -// SetDenomTrace sets a new {trace hash -> trace} pair to the store. -func (k Keeper) SetDenomTrace(ctx Context, denomTrace DenomTrace) { - store := ctx.KVStore(k.storeKey) - bz := k.cdc.MustMarshalBinaryBare(&denomTrace) - store.Set(types.KeyTrace(denomTrace.Hash()), bz) -} -``` - -The `MsgTransfer` will validate that the `Coin` denomination from the `Token` field contains a valid -hash, if the trace info is provided, or that the base denominations matches: - -```golang -func (msg MsgTransfer) ValidateBasic() error { - // ... - return ValidateIBCDenom(msg.Token.Denom) -} -``` - -```golang -// ValidateIBCDenom validates that the given denomination is either: -// -// - A valid base denomination (eg: 'uatom') -// - A valid fungible token representation (i.e 'ibc/{hash}') per ADR 001 https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-001-coin-source-tracing.md -func ValidateIBCDenom(denom string) error { - denomSplit := strings.SplitN(denom, "/", 2) - - switch { - case strings.TrimSpace(denom) == "", - len(denomSplit) == 1 && denomSplit[0] == "ibc", - len(denomSplit) == 2 && (denomSplit[0] != "ibc" || strings.TrimSpace(denomSplit[1]) == ""): - return sdkerrors.Wrapf(ErrInvalidDenomForTransfer, "denomination should be prefixed with the format 'ibc/{hash(trace + \"/\" + %s)}'", denom) - - case denomSplit[0] == denom && strings.TrimSpace(denom) != "": - return sdk.ValidateDenom(denom) - } - - if _, err := ParseHexHash(denomSplit[1]); err != nil { - return Wrapf(err, "invalid denom trace hash %s", denomSplit[1]) - } - - return nil -} -``` - -The denomination trace info only needs to be updated when token is received: - -- Receiver is **source** chain: The receiver created the token and must have the trace lookup already stored (if necessary _ie_ native token case wouldn't need a lookup). -- Receiver is **not source** chain: Store the received info. For example, during step 1, when chain `B` receives `transfer/channelToA/denom`. - -```golang -// SendTransfer -// ... - - fullDenomPath := token.Denom - -// deconstruct the token denomination into the denomination trace info -// to determine if the sender is the source chain -if strings.HasPrefix(token.Denom, "ibc/") { - fullDenomPath, err = k.DenomPathFromHash(ctx, token.Denom) - if err != nil { - return err - } -} - -if types.SenderChainIsSource(sourcePort, sourceChannel, fullDenomPath) { -//... -``` - -```golang -// DenomPathFromHash returns the full denomination path prefix from an ibc denom with a hash -// component. -func (k Keeper) DenomPathFromHash(ctx sdk.Context, denom string) (string, error) { - hexHash := denom[4:] - hash, err := ParseHexHash(hexHash) - if err != nil { - return "", Wrap(ErrInvalidDenomForTransfer, err.Error()) - } - - denomTrace, found := k.GetDenomTrace(ctx, hash) - if !found { - return "", Wrap(ErrTraceNotFound, hexHash) - } - - fullDenomPath := denomTrace.GetFullDenomPath() - return fullDenomPath, nil -} -``` - - -```golang -// OnRecvPacket -// ... - -// This is the prefix that would have been prefixed to the denomination -// on sender chain IF and only if the token originally came from the -// receiving chain. -// -// NOTE: We use SourcePort and SourceChannel here, because the counterparty -// chain would have prefixed with DestPort and DestChannel when originally -// receiving this coin as seen in the "sender chain is the source" condition. -if ReceiverChainIsSource(packet.GetSourcePort(), packet.GetSourceChannel(), data.Denom) { - // sender chain is not the source, unescrow tokens - - // remove prefix added by sender chain - voucherPrefix := types.GetDenomPrefix(packet.GetSourcePort(), packet.GetSourceChannel()) - unprefixedDenom := data.Denom[len(voucherPrefix):] - token := sdk.NewCoin(unprefixedDenom, sdk.NewIntFromUint64(data.Amount)) - - // unescrow tokens - escrowAddress := types.GetEscrowAddress(packet.GetDestPort(), packet.GetDestChannel()) - return k.bankKeeper.SendCoins(ctx, escrowAddress, receiver, sdk.NewCoins(token)) -} - -// sender chain is the source, mint vouchers - -// since SendPacket did not prefix the denomination, we must prefix denomination here -sourcePrefix := types.GetDenomPrefix(packet.GetDestPort(), packet.GetDestChannel()) -// NOTE: sourcePrefix contains the trailing "/" -prefixedDenom := sourcePrefix + data.Denom - -// construct the denomination trace from the full raw denomination -denomTrace := types.ParseDenomTrace(prefixedDenom) - -// set the value to the lookup table if not stored already -traceHash := denomTrace.Hash() -if !k.HasDenomTrace(ctx, traceHash) { - k.SetDenomTrace(ctx, traceHash, denomTrace) -} - -voucherDenom := denomTrace.IBCDenom() -voucher := sdk.NewCoin(voucherDenom, sdk.NewIntFromUint64(data.Amount)) - -// mint new tokens if the source of the transfer is the same chain -if err := k.bankKeeper.MintCoins( - ctx, types.ModuleName, sdk.NewCoins(voucher), -); err != nil { - return err -} - -// send to receiver -return k.bankKeeper.SendCoinsFromModuleToAccount( - ctx, types.ModuleName, receiver, sdk.NewCoins(voucher), -) -``` - -```golang -func NewDenomTraceFromRawDenom(denom string) DenomTrace{ - denomSplit := strings.Split(denom, "/") - trace := "" - if len(denomSplit) > 1 { - trace = strings.Join(denomSplit[:len(denomSplit)-1], "/") - } - return DenomTrace{ - BaseDenom: denomSplit[len(denomSplit)-1], - Trace: trace, - } -} -``` - -One final remark is that the `FungibleTokenPacketData` will remain the same, i.e with the prefixed full denomination, since the receiving chain may not be an SDK-based chain. - -### Coin Changes - -The coin denomination validation will need to be updated to reflect these changes. In particular, the denomination validation -function will now: - -- Accept slash separators (`"/"`) and uppercase characters (due to the `HexBytes` format) -- Bump the maximum character length to 128, as the hex representation used by Tendermint's - `HexBytes` type contains 64 characters. - -Additional validation logic, such as verifying the length of the hash, the may be added to the bank module in the future if the [custom base denomination validation](https://github.com/cosmos/cosmos-sdk/pull/6755) is integrated into the SDK. - -### Positive - -- Clearer separation of the source tracing behaviour of the token (transfer prefix) from the original - `Coin` denomination -- Consistent validation of `Coin` fields (i.e no special characters, fixed max length) -- Cleaner `Coin` and standard denominations for IBC -- No additional fields to SDK `Coin` - -### Negative - -- Store each set of tracing denomination identifiers on the `ibc-transfer` module store -- Clients will have to fetch the base denomination every time they receive a new relayed fungible token over IBC. This can be mitigated using a map/cache for already seen hashes on the client side. Other forms of mitigation, would be opening a websocket connection subscribe to incoming events. - -### Neutral - -- Slight difference with the ICS20 spec -- Additional validation logic for IBC coins on the `ibc-transfer` module -- Additional genesis fields -- Slightly increases the gas usage on cross-chain transfers due to access to the store. This should - be inter-block cached if transfers are frequent. - -## References - -- [ICS 20 - Fungible token transfer](https://github.com/cosmos/ibc/tree/master/spec/app/ics-020-fungible-token-transfer) -- [Custom Coin Denomination validation](https://github.com/cosmos/cosmos-sdk/pull/6755) diff --git a/docs/architecture/adr-015-ibc-packet-receiver.md b/docs/architecture/adr-015-ibc-packet-receiver.md deleted file mode 100644 index 77059fd89..000000000 --- a/docs/architecture/adr-015-ibc-packet-receiver.md +++ /dev/null @@ -1,299 +0,0 @@ -# ADR 015: IBC Packet Receiver - -## Changelog - -- 2019 Oct 22: Initial Draft - -## Context - -[ICS 26 - Routing Module](https://github.com/cosmos/ibc/tree/master/spec/core/ics-026-routing-module) defines a function [`handlePacketRecv`](https://github.com/cosmos/ibc/tree/master/spec/core/ics-026-routing-module#packet-relay). - -In ICS 26, the routing module is defined as a layer above each application module -which verifies and routes messages to the destination modules. It is possible to -implement it as a separate module, however, we already have functionality to route -messages upon the destination identifiers in the baseapp. This ADR suggests -to utilize existing `baseapp.router` to route packets to application modules. - -Generally, routing module callbacks have two separate steps in them, -verification and execution. This corresponds to the `AnteHandler`-`Handler` -model inside the SDK. We can do the verification inside the `AnteHandler` -in order to increase developer ergonomics by reducing boilerplate -verification code. - -For atomic multi-message transaction, we want to keep the IBC related -state modification to be preserved even the application side state change -reverts. One of the example might be IBC token sending message following with -stake delegation which uses the tokens received by the previous packet message. -If the token receiving fails for any reason, we might not want to keep -executing the transaction, but we also don't want to abort the transaction -or the sequence and commitment will be reverted and the channel will be stuck. -This ADR suggests new `CodeType`, `CodeTxBreak`, to fix this problem. - -## Decision - -`PortKeeper` will have the capability key that is able to access only the -channels bound to the port. Entities that hold a `PortKeeper` will be -able to call the methods on it which are corresponding with the methods with -the same names on the `ChannelKeeper`, but only with the -allowed port. `ChannelKeeper.Port(string, ChannelChecker)` will be defined to -easily construct a capability-safe `PortKeeper`. This will be addressed in -another ADR and we will use insecure `ChannelKeeper` for now. - -`baseapp.runMsgs` will break the loop over the messages if one of the handlers -returns `!Result.IsOK()`. However, the outer logic will write the cached -store if `Result.IsOK() || Result.Code.IsBreak()`. `Result.Code.IsBreak()` if -`Result.Code == CodeTxBreak`. - -```go -func (app *BaseApp) runTx(tx Tx) (result Result) { - msgs := tx.GetMsgs() - - // AnteHandler - if app.anteHandler != nil { - anteCtx, msCache := app.cacheTxContext(ctx) - newCtx, err := app.anteHandler(anteCtx, tx) - if !newCtx.IsZero() { - ctx = newCtx.WithMultiStore(ms) - } - - if err != nil { - // error handling logic - return res - } - - msCache.Write() - } - - // Main Handler - runMsgCtx, msCache := app.cacheTxContext(ctx) - result = app.runMsgs(runMsgCtx, msgs) - // BEGIN modification made in this ADR - if result.IsOK() || result.IsBreak() { - // END - msCache.Write() - } - - return result -} -``` - -The Cosmos SDK will define an `AnteDecorator` for IBC packet receiving. The -`AnteDecorator` will iterate over the messages included in the transaction, type -`switch` to check whether the message contains an incoming IBC packet, and if so -verify the Merkle proof. - -```go -type ProofVerificationDecorator struct { - clientKeeper ClientKeeper - channelKeeper ChannelKeeper -} - -func (pvr ProofVerificationDecorator) AnteHandle(ctx Context, tx Tx, simulate bool, next AnteHandler) (Context, error) { - for _, msg := range tx.GetMsgs() { - var err error - switch msg := msg.(type) { - case client.MsgUpdateClient: - err = pvr.clientKeeper.UpdateClient(msg.ClientID, msg.Header) - case channel.MsgPacket: - err = pvr.channelKeeper.RecvPacket(msg.Packet, msg.Proofs, msg.ProofHeight) - case chanel.MsgAcknowledgement: - err = pvr.channelKeeper.AcknowledgementPacket(msg.Acknowledgement, msg.Proof, msg.ProofHeight) - case channel.MsgTimeoutPacket: - err = pvr.channelKeeper.TimeoutPacket(msg.Packet, msg.Proof, msg.ProofHeight, msg.NextSequenceRecv) - case channel.MsgChannelOpenInit; - err = pvr.channelKeeper.CheckOpen(msg.PortID, msg.ChannelID, msg.Channel) - default: - continue - } - - if err != nil { - return ctx, err - } - } - - return next(ctx, tx, simulate) -} -``` - -Where `MsgUpdateClient`, `MsgPacket`, `MsgAcknowledgement`, `MsgTimeoutPacket` -are `sdk.Msg` types correspond to `handleUpdateClient`, `handleRecvPacket`, -`handleAcknowledgementPacket`, `handleTimeoutPacket` of the routing module, -respectively. - -The side effects of `RecvPacket`, `VerifyAcknowledgement`, -`VerifyTimeout` will be extracted out into separated functions, -`WriteAcknowledgement`, `DeleteCommitment`, `DeleteCommitmentTimeout`, respectively, -which will be called by the application handlers after the execution. - -`WriteAcknowledgement` writes the acknowledgement to the state that can be -verified by the counter-party chain and increments the sequence to prevent -double execution. `DeleteCommitment` will delete the commitment stored, -`DeleteCommitmentTimeout` will delete the commitment and close channel in case -of ordered channel. - -```go -func (keeper ChannelKeeper) WriteAcknowledgement(ctx Context, packet Packet, ack []byte) { - keeper.SetPacketAcknowledgement(ctx, packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(), ack) - keeper.SetNextSequenceRecv(ctx, packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) -} - -func (keeper ChannelKeeper) DeleteCommitment(ctx Context, packet Packet) { - keeper.deletePacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) -} - -func (keeper ChannelKeeper) DeleteCommitmentTimeout(ctx Context, packet Packet) { - k.deletePacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - - if channel.Ordering == types.ORDERED [ - channel.State = types.CLOSED - k.SetChannel(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), channel) - } -} -``` - -Each application handler should call respective finalization methods on the `PortKeeper` -in order to increase sequence (in case of packet) or remove the commitment -(in case of acknowledgement and timeout). -Calling those functions implies that the application logic has successfully executed. -However, the handlers can return `Result` with `CodeTxBreak` after calling those methods -which will persist the state changes that has been already done but prevent any further -messages to be executed in case of semantically invalid packet. This will keep the sequence -increased in the previous IBC packets(thus preventing double execution) without -proceeding to the following messages. -In any case the application modules should never return state reverting result, -which will make the channel unable to proceed. - -`ChannelKeeper.CheckOpen` method will be introduced. This will replace `onChanOpen*` defined -under the routing module specification. Instead of define each channel handshake callback -functions, application modules can provide `ChannelChecker` function with the `AppModule` -which will be injected to `ChannelKeeper.Port()` at the top level application. -`CheckOpen` will find the correct `ChennelChecker` using the -`PortID` and call it, which will return an error if it is unacceptable by the application. - -The `ProofVerificationDecorator` will be inserted to the top level application. -It is not safe to make each module responsible to call proof verification -logic, whereas application can misbehave(in terms of IBC protocol) by -mistake. - -The `ProofVerificationDecorator` should come right after the default sybil attack -resistent layer from the current `auth.NewAnteHandler`: - -```go -// add IBC ProofVerificationDecorator to the Chain of -func NewAnteHandler( - ak keeper.AccountKeeper, supplyKeeper types.SupplyKeeper, ibcKeeper ibc.Keeper, - sigGasConsumer SignatureVerificationGasConsumer) sdk.AnteHandler { - return sdk.ChainAnteDecorators( - NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first - ... - NewIncrementSequenceDecorator(ak), - ibcante.ProofVerificationDecorator(ibcKeeper.ClientKeeper, ibcKeeper.ChannelKeeper), // innermost AnteDecorator - ) -} -``` - -The implementation of this ADR will also create a `Data` field of the `Packet` of type `[]byte`, which can be deserialised by the receiving module into its own private type. It is up to the application modules to do this according to their own interpretation, not by the IBC keeper. This is crucial for dynamic IBC. - -Example application-side usage: - -```go -type AppModule struct {} - -// CheckChannel will be provided to the ChannelKeeper as ChannelKeeper.Port(module.CheckChannel) -func (module AppModule) CheckChannel(portID, channelID string, channel Channel) error { - if channel.Ordering != UNORDERED { - return ErrUncompatibleOrdering() - } - if channel.CounterpartyPort != "bank" { - return ErrUncompatiblePort() - } - if channel.Version != "" { - return ErrUncompatibleVersion() - } - return nil -} - -func NewHandler(k Keeper) Handler { - return func(ctx Context, msg Msg) Result { - switch msg := msg.(type) { - case MsgTransfer: - return handleMsgTransfer(ctx, k, msg) - case ibc.MsgPacket: - var data PacketDataTransfer - if err := types.ModuleCodec.UnmarshalBinaryBare(msg.GetData(), &data); err != nil { - return err - } - return handlePacketDataTransfer(ctx, k, msg, data) - case ibc.MsgTimeoutPacket: - var data PacketDataTransfer - if err := types.ModuleCodec.UnmarshalBinaryBare(msg.GetData(), &data); err != nil { - return err - } - return handleTimeoutPacketDataTransfer(ctx, k, packet) - // interface { PortID() string; ChannelID() string; Channel() ibc.Channel } - // MsgChanInit, MsgChanTry implements ibc.MsgChannelOpen - case ibc.MsgChannelOpen: - return handleMsgChannelOpen(ctx, k, msg) - } - } -} - -func handleMsgTransfer(ctx Context, k Keeper, msg MsgTransfer) Result { - err := k.SendTransfer(ctx,msg.PortID, msg.ChannelID, msg.Amount, msg.Sender, msg.Receiver) - if err != nil { - return sdk.ResultFromError(err) - } - - return sdk.Result{} -} - -func handlePacketDataTransfer(ctx Context, k Keeper, packet Packet, data PacketDataTransfer) Result { - err := k.ReceiveTransfer(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetDestinationPort(), packet.GetDestinationChannel(), data) - if err != nil { - // TODO: Source chain sent invalid packet, shutdown channel - } - k.ChannelKeeper.WriteAcknowledgement([]byte{0x00}) // WriteAcknowledgement increases the sequence, preventing double spending - return sdk.Result{} -} - -func handleCustomTimeoutPacket(ctx Context, k Keeper, packet CustomPacket) Result { - err := k.RecoverTransfer(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetDestinationPort(), packet.GetDestinationChannel(), data) - if err != nil { - // This chain sent invalid packet or cannot recover the funds - panic(err) - } - k.ChannelKeeper.DeleteCommitmentTimeout(ctx, packet) - // packet timeout should not fail - return sdk.Result{} -} - -func handleMsgChannelOpen(sdk.Context, k Keeper, msg MsgOpenChannel) Result { - k.AllocateEscrowAddress(ctx, msg.ChannelID()) - return sdk.Result{} -} -``` - -## Status - -Proposed - -## Consequences - -### Positive - -- Intuitive interface for developers - IBC handlers do not need to care about IBC authentication -- State change commitment logic is embedded into `baseapp.runTx` logic - -### Negative - -- Cannot support dynamic ports, routing is tied to the baseapp router - -### Neutral - -- Introduces new `AnteHandler` decorator. -- Dynamic ports can be supported using hierarchical port identifier, see #5290 for detail - -## References - -- Relevant comment: [cosmos/ics#289](https://github.com/cosmos/ics/issues/289#issuecomment-544533583) -- [ICS26 - Routing Module](https://github.com/cosmos/ics/blob/master/spec/ics-026-routing-module) diff --git a/docs/architecture/adr-025-ibc-passive-channels.md b/docs/architecture/adr-025-ibc-passive-channels.md deleted file mode 100644 index 4f12a042a..000000000 --- a/docs/architecture/adr-025-ibc-passive-channels.md +++ /dev/null @@ -1,140 +0,0 @@ -# ADR 025: IBC Passive Channels - -## Changelog - -- 2020-05-23: Provide sample Go code and more details -- 2020-05-18: Initial Draft - -## Status - -Proposed - -## Context - -The current "naive" IBC Relayer strategy currently establishes a single predetermined IBC channel atop a single connection between two clients (each potentially of a different chain). This strategy then detects packets to be relayed by watching for `send_packet` and `recv_packet` events matching that channel, and sends the necessary transactions to relay those packets. - -We wish to expand this "naive" strategy to a "passive" one which detects and relays both channel handshake messages and packets on a given connection, without the need to know each channel in advance of relaying it. - -In order to accomplish this, we propose adding more comprehensive events to expose channel metadata for each transaction sent from the `x/ibc/core/04-channel/keeper/handshake.go` and `x/ibc/core/04-channel/keeper/packet.go` modules. - -Here is an example of what would be in `ChanOpenInit`: - -```go -const ( - EventTypeChannelMeta = "channel_meta" - AttributeKeyAction = "action" - AttributeKeyHops = "hops" - AttributeKeyOrder = "order" - AttributeKeySrcPort = "src_port" - AttributeKeySrcChannel = "src_channel" - AttributeKeySrcVersion = "src_version" - AttributeKeyDstPort = "dst_port" - AttributeKeyDstChannel = "dst_channel" - AttributeKeyDstVersion = "dst_version" -) -// ... - // Emit Event with Channel metadata for the relayer to pick up and - // relay to the other chain - // This appears immediately before the successful return statement. - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - types.EventTypeChannelMeta, - sdk.NewAttribute(types.AttributeKeyAction, "open_init"), - sdk.NewAttribute(types.AttributeKeySrcConnection, connectionHops[0]), - sdk.NewAttribute(types.AttributeKeyHops, strings.Join(connectionHops, ",")), - sdk.NewAttribute(types.AttributeKeyOrder, order.String()), - sdk.NewAttribute(types.AttributeKeySrcPort, portID), - sdk.NewAttribute(types.AttributeKeySrcChannel, chanenlID), - sdk.NewAttribute(types.AttributeKeySrcVersion, version), - sdk.NewAttribute(types.AttributeKeyDstPort, counterparty.GetPortID()), - sdk.NewAttribute(types.AttributeKeyDstChannel, counterparty.GetChannelID()), - // The destination version is not yet known, but a value is necessary to pad - // the event attribute offsets - sdk.NewAttribute(types.AttributeKeyDstVersion, ""), - ), - }) -``` - -These metadata events capture all the "header" information needed to route IBC channel handshake transactions without requiring the client to query any data except that of the connection ID that it is willing to relay. It is intended that `channel_meta.src_connection` is the only event key that needs to be indexed for a passive relayer to function. - -### Handling Channel Open Attempts - -In the case of the passive relayer, when one chain sends a `ChanOpenInit`, the relayer should inform the other chain of this open attempt and allow that chain to decide how (and if) it continues the handshake. Once both chains have actively approved the channel opening, then the rest of the handshake can happen as it does with the current "naive" relayer. - -To implement this behavior, we propose replacing the `cbs.OnChanOpenTry` callback with a new `cbs.OnAttemptChanOpenTry` callback which explicitly handles the `MsgChannelOpenTry`, usually by resulting in a call to `keeper.ChanOpenTry`. The typical implementation, in `x/ibc-transfer/module.go` would be compatible with the current "naive" relayer, as follows: - -```go -func (am AppModule) OnAttemptChanOpenTry( - ctx sdk.Context, - chanKeeper channel.Keeper, - portCap *capability.Capability, - msg channel.MsgChannelOpenTry, -) (*sdk.Result, error) { - // Require portID is the portID transfer module is bound to - boundPort := am.keeper.GetPort(ctx) - if boundPort != msg.PortID { - return nil, sdkerrors.Wrapf(porttypes.ErrInvalidPort, "invalid port: %s, expected %s", msg.PortID, boundPort) - } - - // BEGIN NEW CODE - // Assert our protocol version, overriding the relayer's suggestion. - msg.Version = types.Version - // Continue the ChanOpenTry. - res, chanCap, err := channel.HandleMsgChannelOpenTry(ctx, chanKeeper, portCap, msg) - if err != nil { - return nil, err - } - // END OF NEW CODE - - // ... the rest of the callback is similar to the existing OnChanOpenTry - // but uses msg.* directly. -``` - -Here is how this callback would be used, in the implementation of `x/ibc/handler.go`: - -```go -// ... - case channel.MsgChannelOpenTry: - // Lookup module by port capability - module, portCap, err := k.PortKeeper.LookupModuleByPort(ctx, msg.PortID) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id") - } - // Retrieve callbacks from router - cbs, ok := k.Router.GetRoute(module) - if !ok { - return nil, sdkerrors.Wrapf(port.ErrInvalidRoute, "route not found to module: %s", module) - } - // Delegate to the module's OnAttemptChanOpenTry. - return cbs.OnAttemptChanOpenTry(ctx, k.ChannelKeeper, portCap, msg) -``` - -The reason we do not have a more structured interaction between `x/ibc/handler.go` and the port's module (to explicitly negotiate versions, etc) is that we do not wish to constrain the app module to have to finish handling the `MsgChannelOpenTry` during this transaction or even this block. - -## Decision - -- Expose events to allow "passive" connection relayers. -- Enable application-initiated channels via such passive relayers. -- Allow port modules to control how to handle open-try messages. - -## Consequences - -### Positive - -Makes channels into a complete application-level abstraction. - -Applications have full control over initiating and accepting channels, rather than expecting a relayer to tell them when to do so. - -A passive relayer does not have to know what kind of channel (version string, ordering constraints, firewalling logic) the application supports. These are negotiated directly between applications. - -### Negative - -Increased event size for IBC messages. - -### Neutral - -More IBC events are exposed. - -## References - -- The Agoric VM's IBC handler currently [accomodates `attemptChanOpenTry`](https://github.com/Agoric/agoric-sdk/blob/904b3a0423222a1b32893453e44bbde598473960/packages/cosmic-swingset/lib/ag-solo/vats/ibc.js#L546) diff --git a/docs/architecture/adr-026-ibc-client-recovery-mechanisms.md b/docs/architecture/adr-026-ibc-client-recovery-mechanisms.md deleted file mode 100644 index 2e33bf586..000000000 --- a/docs/architecture/adr-026-ibc-client-recovery-mechanisms.md +++ /dev/null @@ -1,82 +0,0 @@ -# ADR 026: IBC Client Recovery Mechanisms - -## Changelog - -- 2020/06/23: Initial version -- 2020/08/06: Revisions per review & to reference version -- 2021/01/15: Revision to support substitute clients for unfreezing - -## Status - -*Accepted* - -## Context - -### Summary - -At launch, IBC will be a novel protocol, without an experienced user-base. At the protocol layer, it is not possible to distinguish between client expiry or misbehaviour due to genuine faults (Byzantine behavior) and client expiry or misbehaviour due to user mistakes (failing to update a client, or accidentally double-signing). In the base IBC protocol and ICS 20 fungible token transfer implementation, if a client can no longer be updated, funds in that channel will be permanently locked and can no longer be transferred. To the degree that it is safe to do so, it would be preferable to provide users with a recovery mechanism which can be utilised in these exceptional cases. - -### Exceptional cases - -The state of concern is where a client associated with connection(s) and channel(s) can no longer be updated. This can happen for several reasons: - -1. The chain which the client is following has halted and is no longer producing blocks/headers, so no updates can be made to the client -1. The chain which the client is following has continued to operate, but no relayer has submitted a new header within the unbonding period, and the client has expired - 1. This could be due to real misbehaviour (intentional Byzantine behaviour) or merely a mistake by validators, but the client cannot distinguish these two cases -1. The chain which the client is following has experienced a misbehaviour event, and the client has been frozen & thus can no longer be updated - -### Security model - -Two-thirds of the validator set (the quorum for governance, module participation) can already sign arbitrary data, so allowing governance to manually force-update a client with a new header after a delay period does not substantially alter the security model. - -## Decision - -We elect not to deal with chains which have actually halted, which is necessarily Byzantine behaviour and in which case token recovery is not likely possible anyways (in-flight packets cannot be timed-out, but the relative impact of that is minor). - -1. Require Tendermint light clients (ICS 07) to be created with the following additional flags - 1. `allow_governance_override_after_expiry` (boolean, default false) -1. Require Tendermint light clients (ICS 07) to expose the following additional internal query functions - 1. `Expired() boolean`, which returns whether or not the client has passed the trusting period since the last update (in which case no headers can be validated) -1. Require Tendermint light clients (ICS 07) & solo machine clients (ICS 06) to be created with the following additional flags - 1. `allow_governance_override_after_misbehaviour` (boolean, default false) -1. Require Tendermint light clients (ICS 07) to expose the following additional state mutation functions - 1. `Unfreeze()`, which unfreezes a light client after misbehaviour and clears any frozen height previously set -1. Add a new governance proposal type, `ClientUpdateProposal`, in the `x/ibc` module - 1. Extend the base `Proposal` with two client identifiers (`string`) and an initial height ('exported.Height'). - 1. The first client identifier is the proposed client to be updated. This client must be either frozen or expired. - 1. The second client is a substitute client. It carries all the state for the client which may be updated. It must have identitical client and chain parameters to the client which may be updated (except for latest height, frozen height, and chain-id). It should be continually updated during the voting period. - 1. The initial height represents the starting height consensus states which will be copied from the substitute client to the frozen/expired client. - 1. If this governance proposal passes, the client on trial will be updated with all the state of the substitute, if and only if: - 1. `allow_governance_override_after_expiry` is true and the client has expired (`Expired()` returns true) - 1. `allow_governance_override_after_misbehaviour` is true and the client has been frozen (`Frozen()` returns true) - 1. In this case, additionally, the client is unfrozen by calling `Unfreeze()` - - -Note that clients frozen due to misbehaviour must wait for the evidence to expire to avoid becoming refrozen. - -This ADR does not address planned upgrades, which are handled separately as per the [specification](https://github.com/cosmos/ibc/tree/master/spec/client/ics-007-tendermint-client#upgrades). - -## Consequences - -### Positive - -- Establishes a mechanism for client recovery in the case of expiry -- Establishes a mechanism for client recovery in the case of misbehaviour -- Clients can elect to disallow this recovery mechanism if they do not wish to allow for it -- Constructing an ClientUpdate Proposal is as difficult as creating a new client - -### Negative - -- Additional complexity in client creation which must be understood by the user -- Coping state of the substitute adds complexity -- Governance participants must vote on a substitute client - -### Neutral - -No neutral consequences. - -## References - -- [Prior discussion](https://github.com/cosmos/ics/issues/421) -- [Epoch number discussion](https://github.com/cosmos/ics/issues/439) -- [Upgrade plan discussion](https://github.com/cosmos/ics/issues/445) diff --git a/go.mod b/go.mod index e5bb55b77..e25b9d859 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ module github.com/cosmos/cosmos-sdk require ( github.com/99designs/keyring v1.1.6 - github.com/armon/go-metrics v0.3.6 + github.com/armon/go-metrics v0.3.7 github.com/bgentry/speakeasy v0.1.0 github.com/btcsuite/btcd v0.21.0-beta github.com/btcsuite/btcutil v1.0.2 @@ -22,7 +22,7 @@ require ( github.com/golang/snappy v0.0.2 // indirect github.com/gorilla/handlers v1.5.1 github.com/gorilla/mux v1.8.0 - github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 + github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/hashicorp/golang-lru v0.5.4 github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87 diff --git a/go.sum b/go.sum index c1b998fa6..c8f4f7b5a 100644 --- a/go.sum +++ b/go.sum @@ -61,8 +61,8 @@ github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1: github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.3.6 h1:x/tmtOF9cDBoXH7XoAGOz2qqm1DknFD1590XmD/DUJ8= -github.com/armon/go-metrics v0.3.6/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-metrics v0.3.7 h1:c/oCtWzYpboy6+6f6LjXRlyW7NwA2SWf+a9KMlHq/bM= +github.com/armon/go-metrics v0.3.7/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= @@ -314,8 +314,9 @@ github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1 github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.1/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= -github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 h1:FlFbCRLd5Jr4iYXZufAvgWN6Ao0JrI5chLINnUXDDr0= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= diff --git a/types/decimal.go b/types/decimal.go index 706859a85..9ce5cfb97 100644 --- a/types/decimal.go +++ b/types/decimal.go @@ -177,6 +177,9 @@ func NewDecFromStr(str string) (Dec, error) { if !ok { return Dec{}, fmt.Errorf("failed to set decimal string: %s", combinedStr) } + if combined.BitLen() > maxBitLen { + return Dec{}, fmt.Errorf("decimal out of range; bitLen: got %d, max %d", combined.BitLen(), maxBitLen) + } if neg { combined = new(big.Int).Neg(combined) } diff --git a/types/decimal_test.go b/types/decimal_test.go index 050d19f50..efa0ce202 100644 --- a/types/decimal_test.go +++ b/types/decimal_test.go @@ -8,7 +8,7 @@ import ( "testing" "github.com/stretchr/testify/suite" - yaml "gopkg.in/yaml.v2" + "gopkg.in/yaml.v2" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -57,6 +57,7 @@ func (s *decimalTestSuite) TestNewDecFromStr() { {"foobar", true, sdk.Dec{}}, {"0.foobar", true, sdk.Dec{}}, {"0.foobar.", true, sdk.Dec{}}, + {"88888888888888888888888888888888888888888888888888888888888888888888844444440", true, sdk.Dec{}}, } for tcIndex, tc := range tests { diff --git a/x/auth/client/testutil/cli_test.go b/x/auth/client/testutil/cli_test.go new file mode 100644 index 000000000..0a7a5cc25 --- /dev/null +++ b/x/auth/client/testutil/cli_test.go @@ -0,0 +1,17 @@ +// +build norace + +package testutil + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/testutil/network" + + "github.com/stretchr/testify/suite" +) + +func TestIntegrationTestSuite(t *testing.T) { + cfg := network.DefaultConfig() + cfg.NumValidators = 2 + suite.Run(t, NewIntegrationTestSuite(cfg)) +} diff --git a/x/auth/client/cli/cli_test.go b/x/auth/client/testutil/suite.go similarity index 83% rename from x/auth/client/cli/cli_test.go rename to x/auth/client/testutil/suite.go index 15f95d92b..4c75d2b41 100644 --- a/x/auth/client/cli/cli_test.go +++ b/x/auth/client/testutil/suite.go @@ -1,6 +1,4 @@ -// +build norace - -package cli_test +package testutil import ( "context" @@ -31,7 +29,6 @@ import ( "github.com/cosmos/cosmos-sdk/types/tx/signing" authcli "github.com/cosmos/cosmos-sdk/x/auth/client/cli" authrest "github.com/cosmos/cosmos-sdk/x/auth/client/rest" - authtest "github.com/cosmos/cosmos-sdk/x/auth/client/testutil" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" bankcli "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -44,14 +41,14 @@ type IntegrationTestSuite struct { network *network.Network } +func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { + return &IntegrationTestSuite{cfg: cfg} +} + func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") - cfg := network.DefaultConfig() - cfg.NumValidators = 2 - - s.cfg = cfg - s.network = network.New(s.T(), cfg) + s.network = network.New(s.T(), s.cfg) kb := s.network.Validators[0].ClientCtx.Keyring _, _, err := kb.NewMnemonic("newAccount", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) @@ -88,14 +85,15 @@ func (s *IntegrationTestSuite) TestCLIValidateSignatures() { // write unsigned tx to file unsignedTx := testutil.WriteToNewTempFile(s.T(), res.String()) - res, err = authtest.TxSignExec(val.ClientCtx, val.Address, unsignedTx.Name()) + res, err = TxSignExec(val.ClientCtx, val.Address, unsignedTx.Name()) s.Require().NoError(err) signedTx, err := val.ClientCtx.TxConfig.TxJSONDecoder()(res.Bytes()) s.Require().NoError(err) signedTxFile := testutil.WriteToNewTempFile(s.T(), res.String()) txBuilder, err := val.ClientCtx.TxConfig.WrapTxBuilder(signedTx) - res, err = authtest.TxValidateSignaturesExec(val.ClientCtx, signedTxFile.Name()) + s.Require().NoError(err) + _, err = TxValidateSignaturesExec(val.ClientCtx, signedTxFile.Name()) s.Require().NoError(err) txBuilder.SetMemo("MODIFIED TX") @@ -104,7 +102,7 @@ func (s *IntegrationTestSuite) TestCLIValidateSignatures() { modifiedTxFile := testutil.WriteToNewTempFile(s.T(), string(bz)) - res, err = authtest.TxValidateSignaturesExec(val.ClientCtx, modifiedTxFile.Name()) + _, err = TxValidateSignaturesExec(val.ClientCtx, modifiedTxFile.Name()) s.Require().EqualError(err, "signatures validation failed") } @@ -123,30 +121,30 @@ func (s *IntegrationTestSuite) TestCLISignBatch() { val.ClientCtx.HomeDir = strings.Replace(val.ClientCtx.HomeDir, "simd", "simcli", 1) // sign-batch file - offline is set but account-number and sequence are not - res, err := authtest.TxSignBatchExec(val.ClientCtx, val.Address, outputFile.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--offline") + _, err = TxSignBatchExec(val.ClientCtx, val.Address, outputFile.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--offline") s.Require().EqualError(err, "required flag(s) \"account-number\", \"sequence\" not set") // sign-batch file - res, err = authtest.TxSignBatchExec(val.ClientCtx, val.Address, outputFile.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID)) + res, err := TxSignBatchExec(val.ClientCtx, val.Address, outputFile.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID)) s.Require().NoError(err) s.Require().Equal(3, len(strings.Split(strings.Trim(res.String(), "\n"), "\n"))) // sign-batch file - res, err = authtest.TxSignBatchExec(val.ClientCtx, val.Address, outputFile.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--signature-only") + res, err = TxSignBatchExec(val.ClientCtx, val.Address, outputFile.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--signature-only") s.Require().NoError(err) s.Require().Equal(3, len(strings.Split(strings.Trim(res.String(), "\n"), "\n"))) // Sign batch malformed tx file. malformedFile := testutil.WriteToNewTempFile(s.T(), fmt.Sprintf("%smalformed", generatedStd)) - res, err = authtest.TxSignBatchExec(val.ClientCtx, val.Address, malformedFile.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID)) + _, err = TxSignBatchExec(val.ClientCtx, val.Address, malformedFile.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID)) s.Require().Error(err) // Sign batch malformed tx file signature only. - res, err = authtest.TxSignBatchExec(val.ClientCtx, val.Address, malformedFile.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--signature-only") + _, err = TxSignBatchExec(val.ClientCtx, val.Address, malformedFile.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--signature-only") s.Require().Error(err) } -func (s *IntegrationTestSuite) TestCLISign_AminoJSON() { +func (s *IntegrationTestSuite) TestCLISignAminoJSON() { require := s.Require() val1 := s.network.Validators[0] txCfg := val1.ClientCtx.TxConfig @@ -168,13 +166,13 @@ func (s *IntegrationTestSuite) TestCLISign_AminoJSON() { require.NoError(err) // query account info - queryResJSON, err := authtest.QueryAccountExec(val1.ClientCtx, val1.Address) + queryResJSON, err := QueryAccountExec(val1.ClientCtx, val1.Address) require.NoError(err) var account authtypes.AccountI require.NoError(val1.ClientCtx.JSONMarshaler.UnmarshalInterfaceJSON(queryResJSON.Bytes(), &account)) /**** test signature-only ****/ - res, err := authtest.TxSignExec(val1.ClientCtx, val1.Address, fileUnsigned.Name(), chainFlag, + res, err := TxSignExec(val1.ClientCtx, val1.Address, fileUnsigned.Name(), chainFlag, sigOnlyFlag, signModeAminoFlag) require.NoError(err) checkSignatures(require, txCfg, res.Bytes(), valInfo.GetPubKey()) @@ -184,7 +182,7 @@ func (s *IntegrationTestSuite) TestCLISign_AminoJSON() { require.Equal(account.GetSequence(), sigs[0].Sequence) /**** test full output ****/ - res, err = authtest.TxSignExec(val1.ClientCtx, val1.Address, fileUnsigned.Name(), chainFlag, signModeAminoFlag) + res, err = TxSignExec(val1.ClientCtx, val1.Address, fileUnsigned.Name(), chainFlag, signModeAminoFlag) require.NoError(err) // txCfg.UnmarshalSignatureJSON can't unmarshal a fragment of the signature, so we create this structure. @@ -199,14 +197,14 @@ func (s *IntegrationTestSuite) TestCLISign_AminoJSON() { /**** test file output ****/ filenameSigned := filepath.Join(s.T().TempDir(), "test_sign_out.json") fileFlag := fmt.Sprintf("--%s=%s", flags.FlagOutputDocument, filenameSigned) - _, err = authtest.TxSignExec(val1.ClientCtx, val1.Address, fileUnsigned.Name(), chainFlag, fileFlag, signModeAminoFlag) + _, err = TxSignExec(val1.ClientCtx, val1.Address, fileUnsigned.Name(), chainFlag, fileFlag, signModeAminoFlag) require.NoError(err) fContent, err := ioutil.ReadFile(filenameSigned) require.NoError(err) require.Equal(res.String(), string(fContent)) /**** try to append to the previously signed transaction ****/ - res, err = authtest.TxSignExec(val1.ClientCtx, val1.Address, filenameSigned, chainFlag, + res, err = TxSignExec(val1.ClientCtx, val1.Address, filenameSigned, chainFlag, sigOnlyFlag, signModeAminoFlag) require.NoError(err) checkSignatures(require, txCfg, res.Bytes(), valInfo.GetPubKey(), valInfo.GetPubKey()) @@ -217,12 +215,13 @@ func (s *IntegrationTestSuite) TestCLISign_AminoJSON() { // account. Changing the file is too much hacking, because TxDecoder returns sdk.Tx, which doesn't // provide functionality to check / manage `auth_info`. // Cases with different keys are are covered in unit tests of `tx.Sign`. - res, err = authtest.TxSignExec(val1.ClientCtx, val1.Address, filenameSigned, chainFlag, + res, err = TxSignExec(val1.ClientCtx, val1.Address, filenameSigned, chainFlag, sigOnlyFlag, "--overwrite", signModeAminoFlag) + require.NoError(err) checkSignatures(require, txCfg, res.Bytes(), valInfo.GetPubKey()) /**** test flagAmino ****/ - res, err = authtest.TxSignExec(val1.ClientCtx, val1.Address, filenameSigned, chainFlag, + res, err = TxSignExec(val1.ClientCtx, val1.Address, filenameSigned, chainFlag, "--amino=true", signModeAminoFlag) require.NoError(err) @@ -393,23 +392,23 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() { unsignedTxFile := testutil.WriteToNewTempFile(s.T(), finalGeneratedTx.String()) // Test validate-signatures - res, err := authtest.TxValidateSignaturesExec(val1.ClientCtx, unsignedTxFile.Name()) + res, err := TxValidateSignaturesExec(val1.ClientCtx, unsignedTxFile.Name()) s.Require().EqualError(err, "signatures validation failed") s.Require().True(strings.Contains(res.String(), fmt.Sprintf("Signers:\n 0: %v\n\nSignatures:\n\n", val1.Address.String()))) // Test sign // Does not work in offline mode - res, err = authtest.TxSignExec(val1.ClientCtx, val1.Address, unsignedTxFile.Name(), "--offline") + _, err = TxSignExec(val1.ClientCtx, val1.Address, unsignedTxFile.Name(), "--offline") s.Require().EqualError(err, "required flag(s) \"account-number\", \"sequence\" not set") // But works offline if we set account number and sequence val1.ClientCtx.HomeDir = strings.Replace(val1.ClientCtx.HomeDir, "simd", "simcli", 1) - res, err = authtest.TxSignExec(val1.ClientCtx, val1.Address, unsignedTxFile.Name(), "--offline", "--account-number", "1", "--sequence", "1") + _, err = TxSignExec(val1.ClientCtx, val1.Address, unsignedTxFile.Name(), "--offline", "--account-number", "1", "--sequence", "1") s.Require().NoError(err) // Sign transaction - signedTx, err := authtest.TxSignExec(val1.ClientCtx, val1.Address, unsignedTxFile.Name()) + signedTx, err := TxSignExec(val1.ClientCtx, val1.Address, unsignedTxFile.Name()) s.Require().NoError(err) signedFinalTx, err := txCfg.TxJSONDecoder()(signedTx.Bytes()) s.Require().NoError(err) @@ -425,7 +424,7 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() { signedTxFile := testutil.WriteToNewTempFile(s.T(), signedTx.String()) // validate Signature - res, err = authtest.TxValidateSignaturesExec(val1.ClientCtx, signedTxFile.Name()) + res, err = TxValidateSignaturesExec(val1.ClientCtx, signedTxFile.Name()) s.Require().NoError(err) s.Require().True(strings.Contains(res.String(), "[OK]")) @@ -440,14 +439,14 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() { // Test broadcast // Does not work in offline mode - res, err = authtest.TxBroadcastExec(val1.ClientCtx, signedTxFile.Name(), "--offline") + _, err = TxBroadcastExec(val1.ClientCtx, signedTxFile.Name(), "--offline") s.Require().EqualError(err, "cannot broadcast tx during offline mode") s.Require().NoError(s.network.WaitForNextBlock()) // Broadcast correct transaction. val1.ClientCtx.BroadcastMode = flags.BroadcastBlock - res, err = authtest.TxBroadcastExec(val1.ClientCtx, signedTxFile.Name()) + _, err = TxBroadcastExec(val1.ClientCtx, signedTxFile.Name()) s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) @@ -510,18 +509,18 @@ func (s *IntegrationTestSuite) TestCLIMultisignInsufficientCosigners() { // Multisign, sign with one signature val1.ClientCtx.HomeDir = strings.Replace(val1.ClientCtx.HomeDir, "simd", "simcli", 1) - account1Signature, err := authtest.TxSignExec(val1.ClientCtx, account1.GetAddress(), multiGeneratedTxFile.Name(), "--multisig", multisigInfo.GetAddress().String()) + account1Signature, err := TxSignExec(val1.ClientCtx, account1.GetAddress(), multiGeneratedTxFile.Name(), "--multisig", multisigInfo.GetAddress().String()) s.Require().NoError(err) sign1File := testutil.WriteToNewTempFile(s.T(), account1Signature.String()) - multiSigWith1Signature, err := authtest.TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), sign1File.Name()) + multiSigWith1Signature, err := TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), sign1File.Name()) s.Require().NoError(err) // Save tx to file multiSigWith1SignatureFile := testutil.WriteToNewTempFile(s.T(), multiSigWith1Signature.String()) - _, err = authtest.TxValidateSignaturesExec(val1.ClientCtx, multiSigWith1SignatureFile.Name()) + _, err = TxValidateSignaturesExec(val1.ClientCtx, multiSigWith1SignatureFile.Name()) s.Require().Error(err) } @@ -540,12 +539,12 @@ func (s *IntegrationTestSuite) TestCLIEncode() { savedTxFile := testutil.WriteToNewTempFile(s.T(), normalGeneratedTx.String()) // Encode - encodeExec, err := authtest.TxEncodeExec(val1.ClientCtx, savedTxFile.Name()) + encodeExec, err := TxEncodeExec(val1.ClientCtx, savedTxFile.Name()) s.Require().NoError(err) trimmedBase64 := strings.Trim(encodeExec.String(), "\"\n") // Check that the transaction decodes as expected - decodedTx, err := authtest.TxDecodeExec(val1.ClientCtx, trimmedBase64) + decodedTx, err := TxDecodeExec(val1.ClientCtx, trimmedBase64) s.Require().NoError(err) txCfg := val1.ClientCtx.TxConfig @@ -616,28 +615,28 @@ func (s *IntegrationTestSuite) TestCLIMultisignSortSignatures() { // Sign with account1 val1.ClientCtx.HomeDir = strings.Replace(val1.ClientCtx.HomeDir, "simd", "simcli", 1) - account1Signature, err := authtest.TxSignExec(val1.ClientCtx, account1.GetAddress(), multiGeneratedTxFile.Name(), "--multisig", multisigInfo.GetAddress().String()) + account1Signature, err := TxSignExec(val1.ClientCtx, account1.GetAddress(), multiGeneratedTxFile.Name(), "--multisig", multisigInfo.GetAddress().String()) s.Require().NoError(err) sign1File := testutil.WriteToNewTempFile(s.T(), account1Signature.String()) // Sign with account1 - account2Signature, err := authtest.TxSignExec(val1.ClientCtx, account2.GetAddress(), multiGeneratedTxFile.Name(), "--multisig", multisigInfo.GetAddress().String()) + account2Signature, err := TxSignExec(val1.ClientCtx, account2.GetAddress(), multiGeneratedTxFile.Name(), "--multisig", multisigInfo.GetAddress().String()) s.Require().NoError(err) sign2File := testutil.WriteToNewTempFile(s.T(), account2Signature.String()) - multiSigWith2Signatures, err := authtest.TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), sign1File.Name(), sign2File.Name()) + multiSigWith2Signatures, err := TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), sign1File.Name(), sign2File.Name()) s.Require().NoError(err) // Write the output to disk signedTxFile := testutil.WriteToNewTempFile(s.T(), multiSigWith2Signatures.String()) - _, err = authtest.TxValidateSignaturesExec(val1.ClientCtx, signedTxFile.Name()) + _, err = TxValidateSignaturesExec(val1.ClientCtx, signedTxFile.Name()) s.Require().NoError(err) val1.ClientCtx.BroadcastMode = flags.BroadcastBlock - _, err = authtest.TxBroadcastExec(val1.ClientCtx, signedTxFile.Name()) + _, err = TxBroadcastExec(val1.ClientCtx, signedTxFile.Name()) s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) @@ -662,7 +661,7 @@ func (s *IntegrationTestSuite) TestCLIMultisign() { val1, multisigInfo.GetAddress(), sdk.NewCoins(sendTokens), ) - + s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) resp, err := bankcli.QueryBalancesExec(val1.ClientCtx, multisigInfo.GetAddress()) @@ -693,33 +692,33 @@ func (s *IntegrationTestSuite) TestCLIMultisign() { // Sign with account1 val1.ClientCtx.HomeDir = strings.Replace(val1.ClientCtx.HomeDir, "simd", "simcli", 1) - account1Signature, err := authtest.TxSignExec(val1.ClientCtx, account1.GetAddress(), multiGeneratedTxFile.Name(), "--multisig", multisigInfo.GetAddress().String()) + account1Signature, err := TxSignExec(val1.ClientCtx, account1.GetAddress(), multiGeneratedTxFile.Name(), "--multisig", multisigInfo.GetAddress().String()) s.Require().NoError(err) sign1File := testutil.WriteToNewTempFile(s.T(), account1Signature.String()) // Sign with account1 - account2Signature, err := authtest.TxSignExec(val1.ClientCtx, account2.GetAddress(), multiGeneratedTxFile.Name(), "--multisig", multisigInfo.GetAddress().String()) + account2Signature, err := TxSignExec(val1.ClientCtx, account2.GetAddress(), multiGeneratedTxFile.Name(), "--multisig", multisigInfo.GetAddress().String()) s.Require().NoError(err) sign2File := testutil.WriteToNewTempFile(s.T(), account2Signature.String()) // Does not work in offline mode. - _, err = authtest.TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), "--offline", sign1File.Name(), sign2File.Name()) + _, err = TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), "--offline", sign1File.Name(), sign2File.Name()) s.Require().EqualError(err, fmt.Sprintf("couldn't verify signature for address %s", account1.GetAddress())) val1.ClientCtx.Offline = false - multiSigWith2Signatures, err := authtest.TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), sign1File.Name(), sign2File.Name()) + multiSigWith2Signatures, err := TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), sign1File.Name(), sign2File.Name()) s.Require().NoError(err) // Write the output to disk signedTxFile := testutil.WriteToNewTempFile(s.T(), multiSigWith2Signatures.String()) - _, err = authtest.TxValidateSignaturesExec(val1.ClientCtx, signedTxFile.Name()) + _, err = TxValidateSignaturesExec(val1.ClientCtx, signedTxFile.Name()) s.Require().NoError(err) val1.ClientCtx.BroadcastMode = flags.BroadcastBlock - _, err = authtest.TxBroadcastExec(val1.ClientCtx, signedTxFile.Name()) + _, err = TxBroadcastExec(val1.ClientCtx, signedTxFile.Name()) s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) @@ -734,6 +733,7 @@ func (s *IntegrationTestSuite) TestSignBatchMultisig() { account2, err := val.ClientCtx.Keyring.Key("newAccount2") s.Require().NoError(err) multisigInfo, err := val.ClientCtx.Keyring.Key("multi") + s.Require().NoError(err) // Send coins from validator to multisig. sendTokens := sdk.NewInt64Coin(s.cfg.BondDenom, 10) @@ -764,20 +764,20 @@ func (s *IntegrationTestSuite) TestSignBatchMultisig() { val.ClientCtx.HomeDir = strings.Replace(val.ClientCtx.HomeDir, "simd", "simcli", 1) // sign-batch file - res, err := authtest.TxSignBatchExec(val.ClientCtx, account1.GetAddress(), filename.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--multisig", multisigInfo.GetAddress().String()) + res, err := TxSignBatchExec(val.ClientCtx, account1.GetAddress(), filename.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--multisig", multisigInfo.GetAddress().String()) s.Require().NoError(err) s.Require().Equal(1, len(strings.Split(strings.Trim(res.String(), "\n"), "\n"))) // write sigs to file file1 := testutil.WriteToNewTempFile(s.T(), res.String()) // sign-batch file with account2 - res, err = authtest.TxSignBatchExec(val.ClientCtx, account2.GetAddress(), filename.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--multisig", multisigInfo.GetAddress().String()) + res, err = TxSignBatchExec(val.ClientCtx, account2.GetAddress(), filename.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--multisig", multisigInfo.GetAddress().String()) s.Require().NoError(err) s.Require().Equal(1, len(strings.Split(strings.Trim(res.String(), "\n"), "\n"))) // write sigs to file2 file2 := testutil.WriteToNewTempFile(s.T(), res.String()) - res, err = authtest.TxMultiSignExec(val.ClientCtx, multisigInfo.GetName(), filename.Name(), file1.Name(), file2.Name()) + _, err = TxMultiSignExec(val.ClientCtx, multisigInfo.GetName(), filename.Name(), file1.Name(), file2.Name()) s.Require().NoError(err) } @@ -790,6 +790,7 @@ func (s *IntegrationTestSuite) TestMultisignBatch() { account2, err := val.ClientCtx.Keyring.Key("newAccount2") s.Require().NoError(err) multisigInfo, err := val.ClientCtx.Keyring.Key("multi") + s.Require().NoError(err) // Send coins from validator to multisig. sendTokens := sdk.NewInt64Coin(s.cfg.BondDenom, 1000) @@ -819,26 +820,26 @@ func (s *IntegrationTestSuite) TestMultisignBatch() { filename := testutil.WriteToNewTempFile(s.T(), strings.Repeat(generatedStd.String(), 3)) val.ClientCtx.HomeDir = strings.Replace(val.ClientCtx.HomeDir, "simd", "simcli", 1) - queryResJSON, err := authtest.QueryAccountExec(val.ClientCtx, multisigInfo.GetAddress()) + queryResJSON, err := QueryAccountExec(val.ClientCtx, multisigInfo.GetAddress()) s.Require().NoError(err) var account authtypes.AccountI s.Require().NoError(val.ClientCtx.JSONMarshaler.UnmarshalInterfaceJSON(queryResJSON.Bytes(), &account)) // sign-batch file - res, err := authtest.TxSignBatchExec(val.ClientCtx, account1.GetAddress(), filename.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--multisig", multisigInfo.GetAddress().String(), fmt.Sprintf("--%s", flags.FlagOffline), fmt.Sprintf("--%s=%s", flags.FlagAccountNumber, fmt.Sprint(account.GetAccountNumber())), fmt.Sprintf("--%s=%s", flags.FlagSequence, fmt.Sprint(account.GetSequence()))) + res, err := TxSignBatchExec(val.ClientCtx, account1.GetAddress(), filename.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--multisig", multisigInfo.GetAddress().String(), fmt.Sprintf("--%s", flags.FlagOffline), fmt.Sprintf("--%s=%s", flags.FlagAccountNumber, fmt.Sprint(account.GetAccountNumber())), fmt.Sprintf("--%s=%s", flags.FlagSequence, fmt.Sprint(account.GetSequence()))) s.Require().NoError(err) s.Require().Equal(3, len(strings.Split(strings.Trim(res.String(), "\n"), "\n"))) // write sigs to file file1 := testutil.WriteToNewTempFile(s.T(), res.String()) // sign-batch file with account2 - res, err = authtest.TxSignBatchExec(val.ClientCtx, account2.GetAddress(), filename.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--multisig", multisigInfo.GetAddress().String(), fmt.Sprintf("--%s", flags.FlagOffline), fmt.Sprintf("--%s=%s", flags.FlagAccountNumber, fmt.Sprint(account.GetAccountNumber())), fmt.Sprintf("--%s=%s", flags.FlagSequence, fmt.Sprint(account.GetSequence()))) + res, err = TxSignBatchExec(val.ClientCtx, account2.GetAddress(), filename.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--multisig", multisigInfo.GetAddress().String(), fmt.Sprintf("--%s", flags.FlagOffline), fmt.Sprintf("--%s=%s", flags.FlagAccountNumber, fmt.Sprint(account.GetAccountNumber())), fmt.Sprintf("--%s=%s", flags.FlagSequence, fmt.Sprint(account.GetSequence()))) s.Require().NoError(err) s.Require().Equal(3, len(strings.Split(strings.Trim(res.String(), "\n"), "\n"))) // multisign the file file2 := testutil.WriteToNewTempFile(s.T(), res.String()) - res, err = authtest.TxMultiSignBatchExec(val.ClientCtx, filename.Name(), multisigInfo.GetName(), file1.Name(), file2.Name()) + res, err = TxMultiSignBatchExec(val.ClientCtx, filename.Name(), multisigInfo.GetName(), file1.Name(), file2.Name()) s.Require().NoError(err) signedTxs := strings.Split(strings.Trim(res.String(), "\n"), "\n") @@ -846,7 +847,7 @@ func (s *IntegrationTestSuite) TestMultisignBatch() { for _, signedTx := range signedTxs { signedTxFile := testutil.WriteToNewTempFile(s.T(), signedTx) val.ClientCtx.BroadcastMode = flags.BroadcastBlock - res, err = authtest.TxBroadcastExec(val.ClientCtx, signedTxFile.Name()) + _, err = TxBroadcastExec(val.ClientCtx, signedTxFile.Name()) s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) } @@ -878,7 +879,7 @@ func (s *IntegrationTestSuite) TestGetAccountCmd() { s.Run(tc.name, func() { clientCtx := val.ClientCtx - out, err := authtest.QueryAccountExec(clientCtx, tc.address) + out, err := QueryAccountExec(clientCtx, tc.address) if tc.expectErr { s.Require().Error(err) s.Require().NotEqual("internal", err.Error()) @@ -905,7 +906,7 @@ func (s *IntegrationTestSuite) TestGetAccountsCmd() { s.Require().NotEmpty(res.Accounts) } -func TestGetBroadcastCommand_OfflineFlag(t *testing.T) { +func TestGetBroadcastCommandOfflineFlag(t *testing.T) { clientCtx := client.Context{}.WithOffline(true) clientCtx = clientCtx.WithTxConfig(simapp.MakeTestEncodingConfig().TxConfig) @@ -916,7 +917,7 @@ func TestGetBroadcastCommand_OfflineFlag(t *testing.T) { require.EqualError(t, cmd.Execute(), "cannot broadcast tx during offline mode") } -func TestGetBroadcastCommand_WithoutOfflineFlag(t *testing.T) { +func TestGetBroadcastCommandWithoutOfflineFlag(t *testing.T) { clientCtx := client.Context{} txCfg := simapp.MakeTestEncodingConfig().TxConfig clientCtx = clientCtx.WithTxConfig(txCfg) @@ -1019,7 +1020,7 @@ func (s *IntegrationTestSuite) TestTxWithoutPublicKey() { unsignedTxFile := testutil.WriteToNewTempFile(s.T(), string(txJSON)) // Sign the file with the unsignedTx. - signedTx, err := authtest.TxSignExec(val1.ClientCtx, val1.Address, unsignedTxFile.Name()) + signedTx, err := TxSignExec(val1.ClientCtx, val1.Address, unsignedTxFile.Name()) s.Require().NoError(err) // Remove the signerInfo's `public_key` field manually from the signedTx. @@ -1037,14 +1038,14 @@ func (s *IntegrationTestSuite) TestTxWithoutPublicKey() { // Broadcast tx, test that it shouldn't panic. val1.ClientCtx.BroadcastMode = flags.BroadcastSync - out, err := authtest.TxBroadcastExec(val1.ClientCtx, signedTxFile.Name()) + out, err := TxBroadcastExec(val1.ClientCtx, signedTxFile.Name()) s.Require().NoError(err) var res sdk.TxResponse s.Require().NoError(val1.ClientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &res)) s.Require().NotEqual(0, res.Code) } -func (s *IntegrationTestSuite) TestSignWithMultiSigners_AminoJSON() { +func (s *IntegrationTestSuite) TestSignWithMultiSignersAminoJSON() { // test case: // Create a transaction with 2 messages which has to be signed with 2 different keys // Sign and append the signatures using the CLI with Amino signing mode. @@ -1075,14 +1076,14 @@ func (s *IntegrationTestSuite) TestSignWithMultiSigners_AminoJSON() { unsignedTxFile := testutil.WriteToNewTempFile(s.T(), string(txJSON)) // Let val0 sign first the file with the unsignedTx. - signedByVal0, err := authtest.TxSignExec(val0.ClientCtx, val0.Address, unsignedTxFile.Name(), "--overwrite", "--sign-mode=amino-json") + signedByVal0, err := TxSignExec(val0.ClientCtx, val0.Address, unsignedTxFile.Name(), "--overwrite", "--sign-mode=amino-json") require.NoError(err) signedByVal0File := testutil.WriteToNewTempFile(s.T(), signedByVal0.String()) // Then let val1 sign the file with signedByVal0. val1AccNum, val1Seq, err := val0.ClientCtx.AccountRetriever.GetAccountNumberSequence(val0.ClientCtx, val1.Address) require.NoError(err) - signedTx, err := authtest.TxSignExec( + signedTx, err := TxSignExec( val1.ClientCtx, val1.Address, signedByVal0File.Name(), "--offline", fmt.Sprintf("--account-number=%d", val1AccNum), fmt.Sprintf("--sequence=%d", val1Seq), "--sign-mode=amino-json", ) @@ -1090,7 +1091,7 @@ func (s *IntegrationTestSuite) TestSignWithMultiSigners_AminoJSON() { signedTxFile := testutil.WriteToNewTempFile(s.T(), signedTx.String()) // Now let's try to send this tx. - res, err := authtest.TxBroadcastExec( + res, err := TxBroadcastExec( val0.ClientCtx, signedTxFile.Name(), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), @@ -1120,7 +1121,3 @@ func (s *IntegrationTestSuite) createBankMsg(val *network.Validator, toAddr sdk. flags = append(flags, extraFlags...) return bankcli.MsgSendExec(val.ClientCtx, val.Address, toAddr, amount, flags...) } - -func TestIntegrationTestSuite(t *testing.T) { - suite.Run(t, new(IntegrationTestSuite)) -} diff --git a/x/auth/vesting/client/testutil/cli_test.go b/x/auth/vesting/client/testutil/cli_test.go new file mode 100644 index 000000000..dd36a6af2 --- /dev/null +++ b/x/auth/vesting/client/testutil/cli_test.go @@ -0,0 +1,17 @@ +// +build norace + +package testutil + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/testutil/network" + + "github.com/stretchr/testify/suite" +) + +func TestIntegrationTestSuite(t *testing.T) { + cfg := network.DefaultConfig() + cfg.NumValidators = 1 + suite.Run(t, NewIntegrationTestSuite(cfg)) +} diff --git a/x/auth/vesting/client/cli/cli_test.go b/x/auth/vesting/client/testutil/suite.go similarity index 93% rename from x/auth/vesting/client/cli/cli_test.go rename to x/auth/vesting/client/testutil/suite.go index ebd417a62..e538f73a6 100644 --- a/x/auth/vesting/client/cli/cli_test.go +++ b/x/auth/vesting/client/testutil/suite.go @@ -1,10 +1,7 @@ -// +build norace - -package cli_test +package testutil import ( "fmt" - "testing" "github.com/gogo/protobuf/proto" "github.com/stretchr/testify/suite" @@ -23,14 +20,14 @@ type IntegrationTestSuite struct { network *network.Network } +func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { + return &IntegrationTestSuite{cfg: cfg} +} + func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") - cfg := network.DefaultConfig() - cfg.NumValidators = 1 - - s.cfg = cfg - s.network = network.New(s.T(), cfg) + s.network = network.New(s.T(), s.cfg) _, err := s.network.WaitForHeight(1) s.Require().NoError(err) @@ -47,8 +44,8 @@ func (s *IntegrationTestSuite) TestNewMsgCreateVestingAccountCmd() { testCases := map[string]struct { args []string expectErr bool - respType proto.Message expectedCode uint32 + respType proto.Message }{ "create a continuous vesting account": { args: []string{ @@ -61,8 +58,8 @@ func (s *IntegrationTestSuite) TestNewMsgCreateVestingAccountCmd() { fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, expectErr: false, - respType: &sdk.TxResponse{}, expectedCode: 0, + respType: &sdk.TxResponse{}, }, "create a delayed vesting account": { args: []string{ @@ -76,8 +73,8 @@ func (s *IntegrationTestSuite) TestNewMsgCreateVestingAccountCmd() { fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, expectErr: false, - respType: &sdk.TxResponse{}, expectedCode: 0, + respType: &sdk.TxResponse{}, }, "invalid address": { args: []string{ @@ -87,8 +84,8 @@ func (s *IntegrationTestSuite) TestNewMsgCreateVestingAccountCmd() { fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address), }, expectErr: true, - respType: &sdk.TxResponse{}, expectedCode: 0, + respType: &sdk.TxResponse{}, }, "invalid coins": { args: []string{ @@ -98,8 +95,8 @@ func (s *IntegrationTestSuite) TestNewMsgCreateVestingAccountCmd() { fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address), }, expectErr: true, - respType: &sdk.TxResponse{}, expectedCode: 0, + respType: &sdk.TxResponse{}, }, "invalid end time": { args: []string{ @@ -109,8 +106,8 @@ func (s *IntegrationTestSuite) TestNewMsgCreateVestingAccountCmd() { fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address), }, expectErr: true, - respType: &sdk.TxResponse{}, expectedCode: 0, + respType: &sdk.TxResponse{}, }, } @@ -133,7 +130,3 @@ func (s *IntegrationTestSuite) TestNewMsgCreateVestingAccountCmd() { }) } } - -func TestIntegrationTestSuite(t *testing.T) { - suite.Run(t, new(IntegrationTestSuite)) -} diff --git a/x/authz/client/testutil/cli_test.go b/x/authz/client/testutil/cli_test.go new file mode 100644 index 000000000..dd36a6af2 --- /dev/null +++ b/x/authz/client/testutil/cli_test.go @@ -0,0 +1,17 @@ +// +build norace + +package testutil + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/testutil/network" + + "github.com/stretchr/testify/suite" +) + +func TestIntegrationTestSuite(t *testing.T) { + cfg := network.DefaultConfig() + cfg.NumValidators = 1 + suite.Run(t, NewIntegrationTestSuite(cfg)) +} diff --git a/x/authz/client/cli/query_test.go b/x/authz/client/testutil/query.go similarity index 95% rename from x/authz/client/cli/query_test.go rename to x/authz/client/testutil/query.go index e011d990d..6079bcacb 100644 --- a/x/authz/client/cli/query_test.go +++ b/x/authz/client/testutil/query.go @@ -1,6 +1,4 @@ -// +build norace - -package cli_test +package testutil import ( "fmt" @@ -14,7 +12,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/authz/client/cli" - authztestutil "github.com/cosmos/cosmos-sdk/x/authz/client/testutil" "github.com/cosmos/cosmos-sdk/x/authz/types" ) @@ -24,7 +21,7 @@ func (s *IntegrationTestSuite) TestQueryAuthorizations() { grantee := s.grantee twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() - _, err := authztestutil.ExecGrantAuthorization( + _, err := ExecGrantAuthorization( val, []string{ grantee.String(), @@ -102,7 +99,7 @@ func (s *IntegrationTestSuite) TestQueryAuthorization() { grantee := s.grantee twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() - _, err := authztestutil.ExecGrantAuthorization( + _, err := ExecGrantAuthorization( val, []string{ grantee.String(), diff --git a/x/authz/client/cli/tx_test.go b/x/authz/client/testutil/tx.go similarity index 93% rename from x/authz/client/cli/tx_test.go rename to x/authz/client/testutil/tx.go index b7dad15e6..08c3d706e 100644 --- a/x/authz/client/cli/tx_test.go +++ b/x/authz/client/testutil/tx.go @@ -1,10 +1,7 @@ -// +build norace - -package cli_test +package testutil import ( "fmt" - "testing" "time" "github.com/gogo/protobuf/proto" @@ -25,8 +22,6 @@ import ( govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" stakingcli "github.com/cosmos/cosmos-sdk/x/staking/client/cli" - authztestutil "github.com/cosmos/cosmos-sdk/x/authz/client/testutil" - bankcli "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" bank "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -39,14 +34,14 @@ type IntegrationTestSuite struct { grantee sdk.AccAddress } +func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { + return &IntegrationTestSuite{cfg: cfg} +} + func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") - cfg := network.DefaultConfig() - cfg.NumValidators = 1 - - s.cfg = cfg - s.network = network.New(s.T(), cfg) + s.network = network.New(s.T(), s.cfg) val := s.network.Validators[0] @@ -88,8 +83,6 @@ func (s *IntegrationTestSuite) TearDownSuite() { var typeMsgSend = bank.SendAuthorization{}.MethodName() var typeMsgVote = "/cosmos.gov.v1beta1.Msg/Vote" -var commonFlags = []string{} - func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() { val := s.network.Validators[0] grantee := s.grantee @@ -169,8 +162,8 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() { fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), - fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, fmt.Sprintf("%s", val.ValAddress.String())), - fmt.Sprintf("--%s=%s", cli.FlagDenyValidators, fmt.Sprintf("%s", val.ValAddress.String())), + fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, val.ValAddress.String()), + fmt.Sprintf("--%s=%s", cli.FlagDenyValidators, val.ValAddress.String()), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, nil, 0, @@ -186,7 +179,7 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() { fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), - fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, fmt.Sprintf("%s", val.ValAddress.String())), + fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, val.ValAddress.String()), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, &sdk.TxResponse{}, 0, @@ -202,7 +195,7 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() { fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), - fmt.Sprintf("--%s=%s", cli.FlagDenyValidators, fmt.Sprintf("%s", val.ValAddress.String())), + fmt.Sprintf("--%s=%s", cli.FlagDenyValidators, val.ValAddress.String()), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, &sdk.TxResponse{}, 0, @@ -218,7 +211,7 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() { fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), - fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, fmt.Sprintf("%s", val.ValAddress.String())), + fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, val.ValAddress.String()), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, &sdk.TxResponse{}, 0, @@ -234,7 +227,7 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() { fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), - fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, fmt.Sprintf("%s", val.ValAddress.String())), + fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, val.ValAddress.String()), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, &sdk.TxResponse{}, 0, @@ -276,7 +269,7 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() { tc := tc s.Run(tc.name, func() { clientCtx := val.ClientCtx - out, err := authztestutil.ExecGrantAuthorization( + out, err := ExecGrantAuthorization( val, tc.args, ) @@ -305,7 +298,7 @@ func (s *IntegrationTestSuite) TestCmdRevokeAuthorizations() { twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() // send-authorization - _, err := authztestutil.ExecGrantAuthorization( + _, err := ExecGrantAuthorization( val, []string{ grantee.String(), @@ -321,7 +314,7 @@ func (s *IntegrationTestSuite) TestCmdRevokeAuthorizations() { s.Require().NoError(err) // generic-authorization - _, err = authztestutil.ExecGrantAuthorization( + _, err = ExecGrantAuthorization( val, []string{ grantee.String(), @@ -346,7 +339,7 @@ func (s *IntegrationTestSuite) TestCmdRevokeAuthorizations() { { "invalid grantee address", []string{ - "invlid grantee", + "invalid grantee", typeMsgSend, fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), @@ -419,7 +412,7 @@ func (s *IntegrationTestSuite) TestExecAuthorizationWithExpiration() { grantee := s.grantee tenSeconds := time.Now().Add(time.Second * time.Duration(10)).Unix() - _, err := authztestutil.ExecGrantAuthorization( + _, err := ExecGrantAuthorization( val, []string{ grantee.String(), @@ -459,7 +452,7 @@ func (s *IntegrationTestSuite) TestNewExecGenericAuthorized() { grantee := s.grantee twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() - _, err := authztestutil.ExecGrantAuthorization( + _, err := ExecGrantAuthorization( val, []string{ grantee.String(), @@ -548,7 +541,7 @@ func (s *IntegrationTestSuite) TestNewExecGrantAuthorized() { grantee := s.grantee twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() - _, err := authztestutil.ExecGrantAuthorization( + _, err := ExecGrantAuthorization( val, []string{ grantee.String(), @@ -565,7 +558,7 @@ func (s *IntegrationTestSuite) TestNewExecGrantAuthorized() { tokens := sdk.NewCoins( sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), sdk.NewInt(12)), ) - normalGeneratedTx, err := bankcli.MsgSendExec( + normalGeneratedTx, err := banktestutil.MsgSendExec( val.ClientCtx, val.Address, grantee, @@ -633,7 +626,7 @@ func (s *IntegrationTestSuite) TestExecDelegateAuthorization() { grantee := s.grantee twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() - _, err := authztestutil.ExecGrantAuthorization( + _, err := ExecGrantAuthorization( val, []string{ grantee.String(), @@ -643,7 +636,7 @@ func (s *IntegrationTestSuite) TestExecDelegateAuthorization() { fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), - fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, fmt.Sprintf("%s", val.ValAddress.String())), + fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, val.ValAddress.String()), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, ) @@ -724,8 +717,8 @@ func (s *IntegrationTestSuite) TestExecDelegateAuthorization() { }) } - //test delegate no spend-limit - _, err = authztestutil.ExecGrantAuthorization( + // test delegate no spend-limit + _, err = ExecGrantAuthorization( val, []string{ grantee.String(), @@ -734,7 +727,7 @@ func (s *IntegrationTestSuite) TestExecDelegateAuthorization() { fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), - fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, fmt.Sprintf("%s", val.ValAddress.String())), + fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, val.ValAddress.String()), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, ) @@ -802,7 +795,7 @@ func (s *IntegrationTestSuite) TestExecDelegateAuthorization() { } // test delegating to denied validator - _, err = authztestutil.ExecGrantAuthorization( + _, err = ExecGrantAuthorization( val, []string{ grantee.String(), @@ -812,7 +805,7 @@ func (s *IntegrationTestSuite) TestExecDelegateAuthorization() { fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), - fmt.Sprintf("--%s=%s", cli.FlagDenyValidators, fmt.Sprintf("%s", val.ValAddress.String())), + fmt.Sprintf("--%s=%s", cli.FlagDenyValidators, val.ValAddress.String()), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, ) @@ -838,7 +831,7 @@ func (s *IntegrationTestSuite) TestExecUndelegateAuthorization() { twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() // granting undelegate msg authorization - _, err := authztestutil.ExecGrantAuthorization( + _, err := ExecGrantAuthorization( val, []string{ grantee.String(), @@ -848,7 +841,7 @@ func (s *IntegrationTestSuite) TestExecUndelegateAuthorization() { fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), - fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, fmt.Sprintf("%s", val.ValAddress.String())), + fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, val.ValAddress.String()), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, ) @@ -944,7 +937,7 @@ func (s *IntegrationTestSuite) TestExecUndelegateAuthorization() { } // grant undelegate authorization without limit - _, err = authztestutil.ExecGrantAuthorization( + _, err = ExecGrantAuthorization( val, []string{ grantee.String(), @@ -953,7 +946,7 @@ func (s *IntegrationTestSuite) TestExecUndelegateAuthorization() { fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), - fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, fmt.Sprintf("%s", val.ValAddress.String())), + fmt.Sprintf("--%s=%s", cli.FlagAllowedValidators, val.ValAddress.String()), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, ) @@ -1020,7 +1013,3 @@ func (s *IntegrationTestSuite) TestExecUndelegateAuthorization() { }) } } - -func TestIntegrationTestSuite(t *testing.T) { - suite.Run(t, new(IntegrationTestSuite)) -} diff --git a/x/bank/client/testutil/cli_test.go b/x/bank/client/testutil/cli_test.go new file mode 100644 index 000000000..dd36a6af2 --- /dev/null +++ b/x/bank/client/testutil/cli_test.go @@ -0,0 +1,17 @@ +// +build norace + +package testutil + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/testutil/network" + + "github.com/stretchr/testify/suite" +) + +func TestIntegrationTestSuite(t *testing.T) { + cfg := network.DefaultConfig() + cfg.NumValidators = 1 + suite.Run(t, NewIntegrationTestSuite(cfg)) +} diff --git a/x/bank/client/cli/cli_test.go b/x/bank/client/testutil/suite.go similarity index 83% rename from x/bank/client/cli/cli_test.go rename to x/bank/client/testutil/suite.go index 60b8c504b..d56835f9b 100644 --- a/x/bank/client/cli/cli_test.go +++ b/x/bank/client/testutil/suite.go @@ -1,15 +1,12 @@ -package cli_test +package testutil import ( - "context" "fmt" - "testing" "github.com/gogo/protobuf/proto" "github.com/stretchr/testify/suite" tmcli "github.com/tendermint/tendermint/libs/cli" - "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" "github.com/cosmos/cosmos-sdk/testutil/network" @@ -17,7 +14,6 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/query" "github.com/cosmos/cosmos-sdk/x/bank/client/cli" - banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -28,15 +24,16 @@ type IntegrationTestSuite struct { network *network.Network } +func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { + return &IntegrationTestSuite{cfg: cfg} +} + func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") - cfg := network.DefaultConfig() - genesisState := cfg.GenesisState - cfg.NumValidators = 1 - + genesisState := s.cfg.GenesisState var bankGenesis types.GenesisState - s.Require().NoError(cfg.Codec.UnmarshalJSON(genesisState[types.ModuleName], &bankGenesis)) + s.Require().NoError(s.cfg.Codec.UnmarshalJSON(genesisState[types.ModuleName], &bankGenesis)) bankGenesis.DenomMetadata = []types.Metadata{ { @@ -78,13 +75,12 @@ func (s *IntegrationTestSuite) SetupSuite() { }, } - bankGenesisBz, err := cfg.Codec.MarshalJSON(&bankGenesis) + bankGenesisBz, err := s.cfg.Codec.MarshalJSON(&bankGenesis) s.Require().NoError(err) genesisState[types.ModuleName] = bankGenesisBz - cfg.GenesisState = genesisState + s.cfg.GenesisState = genesisState - s.cfg = cfg - s.network = network.New(s.T(), cfg) + s.network = network.New(s.T(), s.cfg) _, err = s.network.WaitForHeight(1) s.Require().NoError(err) @@ -199,7 +195,10 @@ func (s *IntegrationTestSuite) TestGetCmdQueryTotalSupply() { fmt.Sprintf("--%s=json", tmcli.OutputFlag), }, respType: &sdk.Coin{}, - expected: &sdk.Coin{s.cfg.BondDenom, s.cfg.StakingTokens.Add(sdk.NewInt(10))}, + expected: &sdk.Coin{ + Denom: s.cfg.BondDenom, + Amount: s.cfg.StakingTokens.Add(sdk.NewInt(10)), + }, }, { name: "total supply of a bogus denom", @@ -209,7 +208,10 @@ func (s *IntegrationTestSuite) TestGetCmdQueryTotalSupply() { fmt.Sprintf("--%s=json", tmcli.OutputFlag), }, respType: &sdk.Coin{}, - expected: &sdk.Coin{"foobar", sdk.ZeroInt()}, + expected: &sdk.Coin{ + Denom: "foobar", + Amount: sdk.ZeroInt(), + }, }, } @@ -364,9 +366,6 @@ func (s *IntegrationTestSuite) TestNewSendTxCmdGenOnly() { clientCtx := val.ClientCtx - ctx := context.Background() - ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx) - from := val.Address to := val.Address amount := sdk.NewCoins( @@ -380,7 +379,7 @@ func (s *IntegrationTestSuite) TestNewSendTxCmdGenOnly() { fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), } - bz, err := banktestutil.MsgSendExec(clientCtx, from, to, amount, args...) + bz, err := MsgSendExec(clientCtx, from, to, amount, args...) s.Require().NoError(err) tx, err := s.cfg.TxConfig.TxJSONDecoder()(bz.Bytes()) s.Require().NoError(err) @@ -399,8 +398,8 @@ func (s *IntegrationTestSuite) TestNewSendTxCmd() { amount sdk.Coins args []string expectErr bool - respType proto.Message expectedCode uint32 + respType proto.Message }{ { "valid transaction", @@ -415,9 +414,7 @@ func (s *IntegrationTestSuite) TestNewSendTxCmd() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - false, - &sdk.TxResponse{}, - 0, + false, 0, &sdk.TxResponse{}, }, { "not enough fees", @@ -433,8 +430,8 @@ func (s *IntegrationTestSuite) TestNewSendTxCmd() { fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(1))).String()), }, false, - &sdk.TxResponse{}, sdkerrors.ErrInsufficientFee.ABCICode(), + &sdk.TxResponse{}, }, { "not enough gas", @@ -451,8 +448,8 @@ func (s *IntegrationTestSuite) TestNewSendTxCmd() { "--gas=10", }, false, - &sdk.TxResponse{}, sdkerrors.ErrOutOfGas.ABCICode(), + &sdk.TxResponse{}, }, } @@ -462,7 +459,7 @@ func (s *IntegrationTestSuite) TestNewSendTxCmd() { s.Run(tc.name, func() { clientCtx := val.ClientCtx - bz, err := banktestutil.MsgSendExec(clientCtx, tc.from, tc.to, tc.amount, tc.args...) + bz, err := MsgSendExec(clientCtx, tc.from, tc.to, tc.amount, tc.args...) if tc.expectErr { s.Require().Error(err) } else { @@ -476,8 +473,60 @@ func (s *IntegrationTestSuite) TestNewSendTxCmd() { } } -func TestIntegrationTestSuite(t *testing.T) { - suite.Run(t, new(IntegrationTestSuite)) +// TestBankMsgService does a basic test of whether or not service Msg's as defined +// in ADR 031 work in the most basic end-to-end case. +func (s *IntegrationTestSuite) TestBankMsgService() { + val := s.network.Validators[0] + + testCases := []struct { + name string + from, to sdk.AccAddress + amount sdk.Coins + args []string + expectErr bool + expectedCode uint32 + respType proto.Message + rawLogContains string + }{ + { + "valid transaction", + val.Address, + val.Address, + sdk.NewCoins( + sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), sdk.NewInt(10)), + sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)), + ), + []string{ + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + false, + 0, + &sdk.TxResponse{}, + "/cosmos.bank.v1beta1.Msg/Send", // indicates we are using ServiceMsg and not a regular Msg + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + clientCtx := val.ClientCtx + + bz, err := MsgSendExec(clientCtx, tc.from, tc.to, tc.amount, tc.args...) + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(bz.Bytes(), tc.respType), bz.String()) + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code) + s.Require().Contains(txResp.RawLog, tc.rawLogContains) + } + }) + } } func NewCoin(denom string, amount sdk.Int) *sdk.Coin { diff --git a/x/crisis/client/testsuite/cli_test.go b/x/crisis/client/testsuite/cli_test.go new file mode 100644 index 000000000..3c083e694 --- /dev/null +++ b/x/crisis/client/testsuite/cli_test.go @@ -0,0 +1,17 @@ +// +build norace + +package testutil + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/cosmos-sdk/testutil/network" +) + +func TestIntegrationTestSuite(t *testing.T) { + cfg := network.DefaultConfig() + cfg.NumValidators = 1 + suite.Run(t, NewIntegrationTestSuite(cfg)) +} diff --git a/x/crisis/client/cli/cli_test.go b/x/crisis/client/testsuite/suite.go similarity index 89% rename from x/crisis/client/cli/cli_test.go rename to x/crisis/client/testsuite/suite.go index 92b439614..1b6907e83 100644 --- a/x/crisis/client/cli/cli_test.go +++ b/x/crisis/client/testsuite/suite.go @@ -1,10 +1,7 @@ -// +build norace - -package cli_test +package testutil import ( "fmt" - "testing" "github.com/gogo/protobuf/proto" "github.com/stretchr/testify/suite" @@ -23,15 +20,14 @@ type IntegrationTestSuite struct { network *network.Network } +func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { + return &IntegrationTestSuite{cfg: cfg} +} + func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") - cfg := network.DefaultConfig() - cfg.NumValidators = 1 - - s.cfg = cfg - s.network = network.New(s.T(), cfg) - + s.network = network.New(s.T(), s.cfg) _, err := s.network.WaitForHeight(1) s.Require().NoError(err) } @@ -48,8 +44,8 @@ func (s *IntegrationTestSuite) TestNewMsgVerifyInvariantTxCmd() { name string args []string expectErr bool - respType proto.Message expectedCode uint32 + respType proto.Message }{ { "missing module", @@ -60,7 +56,7 @@ func (s *IntegrationTestSuite) TestNewMsgVerifyInvariantTxCmd() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - true, nil, 0, + true, 0, nil, }, { "missing invariant route", @@ -71,7 +67,7 @@ func (s *IntegrationTestSuite) TestNewMsgVerifyInvariantTxCmd() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - true, nil, 0, + true, 0, nil, }, { "valid transaction", @@ -82,7 +78,7 @@ func (s *IntegrationTestSuite) TestNewMsgVerifyInvariantTxCmd() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, } @@ -106,7 +102,3 @@ func (s *IntegrationTestSuite) TestNewMsgVerifyInvariantTxCmd() { }) } } - -func TestIntegrationTestSuite(t *testing.T) { - suite.Run(t, new(IntegrationTestSuite)) -} diff --git a/x/distribution/client/testutil/cli_test.go b/x/distribution/client/testutil/cli_test.go new file mode 100644 index 000000000..dd36a6af2 --- /dev/null +++ b/x/distribution/client/testutil/cli_test.go @@ -0,0 +1,17 @@ +// +build norace + +package testutil + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/testutil/network" + + "github.com/stretchr/testify/suite" +) + +func TestIntegrationTestSuite(t *testing.T) { + cfg := network.DefaultConfig() + cfg.NumValidators = 1 + suite.Run(t, NewIntegrationTestSuite(cfg)) +} diff --git a/x/distribution/client/cli/cli_test.go b/x/distribution/client/testutil/suite.go similarity index 92% rename from x/distribution/client/cli/cli_test.go rename to x/distribution/client/testutil/suite.go index 40331db7b..603b8b6a2 100644 --- a/x/distribution/client/cli/cli_test.go +++ b/x/distribution/client/testutil/suite.go @@ -1,34 +1,32 @@ -// +build norace - -package cli_test +package testutil import ( - "context" "fmt" "strings" - "testing" "time" "github.com/gogo/protobuf/proto" "github.com/stretchr/testify/suite" tmcli "github.com/tendermint/tendermint/libs/cli" - "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/testutil" clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" - testnet "github.com/cosmos/cosmos-sdk/testutil/network" + "github.com/cosmos/cosmos-sdk/testutil/network" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/distribution/client/cli" - distrtestutil "github.com/cosmos/cosmos-sdk/x/distribution/client/testutil" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" ) type IntegrationTestSuite struct { suite.Suite - cfg testnet.Config - network *testnet.Network + cfg network.Config + network *network.Network +} + +func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { + return &IntegrationTestSuite{cfg: cfg} } // SetupTest creates a new network for _each_ integration test. We create a new @@ -38,25 +36,21 @@ type IntegrationTestSuite struct { func (s *IntegrationTestSuite) SetupTest() { s.T().Log("setting up integration test suite") - cfg := testnet.DefaultConfig() - genesisState := cfg.GenesisState - cfg.NumValidators = 1 - + genesisState := s.cfg.GenesisState var mintData minttypes.GenesisState - s.Require().NoError(cfg.Codec.UnmarshalJSON(genesisState[minttypes.ModuleName], &mintData)) + s.Require().NoError(s.cfg.Codec.UnmarshalJSON(genesisState[minttypes.ModuleName], &mintData)) inflation := sdk.MustNewDecFromStr("1.0") mintData.Minter.Inflation = inflation mintData.Params.InflationMin = inflation mintData.Params.InflationMax = inflation - mintDataBz, err := cfg.Codec.MarshalJSON(&mintData) + mintDataBz, err := s.cfg.Codec.MarshalJSON(&mintData) s.Require().NoError(err) genesisState[minttypes.ModuleName] = mintDataBz - cfg.GenesisState = genesisState + s.cfg.GenesisState = genesisState - s.cfg = cfg - s.network = testnet.New(s.T(), cfg) + s.network = network.New(s.T(), s.cfg) _, err = s.network.WaitForHeight(1) s.Require().NoError(err) @@ -134,7 +128,7 @@ func (s *IntegrationTestSuite) TestGetCmdQueryValidatorOutstandingRewards() { fmt.Sprintf("--%s=json", tmcli.OutputFlag), }, false, - `{"rewards":[{"denom":"stake","amount":"232.260000000000000000"}]}`, + `{"rewards":[{"denom":"stake","amount":"1164.240000000000000000"}]}`, }, { "text output", @@ -145,7 +139,7 @@ func (s *IntegrationTestSuite) TestGetCmdQueryValidatorOutstandingRewards() { }, false, `rewards: -- amount: "232.260000000000000000" +- amount: "1164.240000000000000000" denom: stake`, }, } @@ -197,7 +191,7 @@ func (s *IntegrationTestSuite) TestGetCmdQueryValidatorCommission() { fmt.Sprintf("--%s=json", tmcli.OutputFlag), }, false, - `{"commission":[{"denom":"stake","amount":"116.130000000000000000"}]}`, + `{"commission":[{"denom":"stake","amount":"464.520000000000000000"}]}`, }, { "text output", @@ -208,7 +202,7 @@ func (s *IntegrationTestSuite) TestGetCmdQueryValidatorCommission() { }, false, `commission: -- amount: "116.130000000000000000" +- amount: "464.520000000000000000" denom: stake`, }, } @@ -345,7 +339,7 @@ func (s *IntegrationTestSuite) TestGetCmdQueryDelegatorRewards() { { "json output", []string{ - fmt.Sprintf("--%s=10", flags.FlagHeight), + fmt.Sprintf("--%s=5", flags.FlagHeight), addr.String(), fmt.Sprintf("--%s=json", tmcli.OutputFlag), }, @@ -355,7 +349,7 @@ func (s *IntegrationTestSuite) TestGetCmdQueryDelegatorRewards() { { "json output (specific validator)", []string{ - fmt.Sprintf("--%s=10", flags.FlagHeight), + fmt.Sprintf("--%s=5", flags.FlagHeight), addr.String(), valAddr.String(), fmt.Sprintf("--%s=json", tmcli.OutputFlag), }, @@ -366,7 +360,7 @@ func (s *IntegrationTestSuite) TestGetCmdQueryDelegatorRewards() { "text output", []string{ fmt.Sprintf("--%s=text", tmcli.OutputFlag), - fmt.Sprintf("--%s=10", flags.FlagHeight), + fmt.Sprintf("--%s=5", flags.FlagHeight), addr.String(), }, false, @@ -383,7 +377,7 @@ total: "text output (specific validator)", []string{ fmt.Sprintf("--%s=text", tmcli.OutputFlag), - fmt.Sprintf("--%s=10", flags.FlagHeight), + fmt.Sprintf("--%s=5", flags.FlagHeight), addr.String(), valAddr.String(), }, false, @@ -458,8 +452,8 @@ func (s *IntegrationTestSuite) TestNewWithdrawRewardsCmd() { valAddr fmt.Stringer args []string expectErr bool - respType proto.Message expectedCode uint32 + respType proto.Message }{ { "invalid validator address", @@ -470,7 +464,7 @@ func (s *IntegrationTestSuite) TestNewWithdrawRewardsCmd() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - true, nil, 0, + true, 0, nil, }, { "valid transaction", @@ -481,7 +475,7 @@ func (s *IntegrationTestSuite) TestNewWithdrawRewardsCmd() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, { "valid transaction (with commission)", @@ -493,7 +487,7 @@ func (s *IntegrationTestSuite) TestNewWithdrawRewardsCmd() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, } @@ -503,10 +497,7 @@ func (s *IntegrationTestSuite) TestNewWithdrawRewardsCmd() { s.Run(tc.name, func() { clientCtx := val.ClientCtx - ctx := context.Background() - ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx) - - bz, err := distrtestutil.MsgWithdrawDelegatorRewardExec(clientCtx, tc.valAddr, tc.args...) + bz, err := MsgWithdrawDelegatorRewardExec(clientCtx, tc.valAddr, tc.args...) if tc.expectErr { s.Require().Error(err) } else { @@ -527,8 +518,8 @@ func (s *IntegrationTestSuite) TestNewWithdrawAllRewardsCmd() { name string args []string expectErr bool - respType proto.Message expectedCode uint32 + respType proto.Message }{ { "valid transaction (offline)", @@ -538,7 +529,7 @@ func (s *IntegrationTestSuite) TestNewWithdrawAllRewardsCmd() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - true, nil, 0, + true, 0, nil, }, { "valid transaction", @@ -548,7 +539,7 @@ func (s *IntegrationTestSuite) TestNewWithdrawAllRewardsCmd() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, } @@ -580,8 +571,8 @@ func (s *IntegrationTestSuite) TestNewSetWithdrawAddrCmd() { name string args []string expectErr bool - respType proto.Message expectedCode uint32 + respType proto.Message }{ { "invalid withdraw address", @@ -592,7 +583,7 @@ func (s *IntegrationTestSuite) TestNewSetWithdrawAddrCmd() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - true, nil, 0, + true, 0, nil, }, { "valid transaction", @@ -603,7 +594,7 @@ func (s *IntegrationTestSuite) TestNewSetWithdrawAddrCmd() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, } @@ -635,8 +626,8 @@ func (s *IntegrationTestSuite) TestNewFundCommunityPoolCmd() { name string args []string expectErr bool - respType proto.Message expectedCode uint32 + respType proto.Message }{ { "invalid funding amount", @@ -647,7 +638,7 @@ func (s *IntegrationTestSuite) TestNewFundCommunityPoolCmd() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - true, nil, 0, + true, 0, nil, }, { "valid transaction", @@ -658,7 +649,7 @@ func (s *IntegrationTestSuite) TestNewFundCommunityPoolCmd() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, } @@ -692,7 +683,9 @@ func (s *IntegrationTestSuite) TestGetCmdSubmitProposal() { "amount": "-343foocoin", "deposit": -324foocoin }` + invalidPropFile := testutil.WriteToNewTempFile(s.T(), invalidProp) + validProp := fmt.Sprintf(`{ "title": "Community Pool Spend", "description": "Pay me some Atoms!", @@ -700,13 +693,14 @@ func (s *IntegrationTestSuite) TestGetCmdSubmitProposal() { "amount": "%s", "deposit": "%s" }`, val.Address.String(), sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(5431)), sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(5431))) + validPropFile := testutil.WriteToNewTempFile(s.T(), validProp) testCases := []struct { name string args []string expectErr bool - respType proto.Message expectedCode uint32 + respType proto.Message }{ { "invalid proposal", @@ -717,7 +711,7 @@ func (s *IntegrationTestSuite) TestGetCmdSubmitProposal() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - true, nil, 0, + true, 0, nil, }, { "valid transaction", @@ -728,7 +722,7 @@ func (s *IntegrationTestSuite) TestGetCmdSubmitProposal() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), // sync mode as there are no funds yet fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, } @@ -753,7 +747,3 @@ func (s *IntegrationTestSuite) TestGetCmdSubmitProposal() { }) } } - -func TestIntegrationTestSuite(t *testing.T) { - suite.Run(t, new(IntegrationTestSuite)) -} diff --git a/x/evidence/client/testutil/cli_test.go b/x/evidence/client/testutil/cli_test.go new file mode 100644 index 000000000..dd36a6af2 --- /dev/null +++ b/x/evidence/client/testutil/cli_test.go @@ -0,0 +1,17 @@ +// +build norace + +package testutil + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/testutil/network" + + "github.com/stretchr/testify/suite" +) + +func TestIntegrationTestSuite(t *testing.T) { + cfg := network.DefaultConfig() + cfg.NumValidators = 1 + suite.Run(t, NewIntegrationTestSuite(cfg)) +} diff --git a/x/evidence/client/cli/cli_test.go b/x/evidence/client/testutil/suite.go similarity index 81% rename from x/evidence/client/cli/cli_test.go rename to x/evidence/client/testutil/suite.go index 84b3697b4..d12083b64 100644 --- a/x/evidence/client/cli/cli_test.go +++ b/x/evidence/client/testutil/suite.go @@ -1,31 +1,30 @@ -package cli_test +package testutil import ( "strings" - "testing" "github.com/stretchr/testify/suite" clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" - testnet "github.com/cosmos/cosmos-sdk/testutil/network" + "github.com/cosmos/cosmos-sdk/testutil/network" "github.com/cosmos/cosmos-sdk/x/evidence/client/cli" ) type IntegrationTestSuite struct { suite.Suite - cfg testnet.Config - network *testnet.Network + cfg network.Config + network *network.Network +} + +func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { + return &IntegrationTestSuite{cfg: cfg} } func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") - cfg := testnet.DefaultConfig() - cfg.NumValidators = 1 - - s.cfg = cfg - s.network = testnet.New(s.T(), cfg) + s.network = network.New(s.T(), s.cfg) _, err := s.network.WaitForHeight(1) s.Require().NoError(err) @@ -36,10 +35,6 @@ func (s *IntegrationTestSuite) TearDownSuite() { s.network.Cleanup() } -func TestIntegrationTestSuite(t *testing.T) { - suite.Run(t, new(IntegrationTestSuite)) -} - func (s *IntegrationTestSuite) TestGetQueryCmd() { val := s.network.Validators[0] diff --git a/x/feegrant/client/testutil/cli_test.go b/x/feegrant/client/testutil/cli_test.go new file mode 100644 index 000000000..bdbfb78d0 --- /dev/null +++ b/x/feegrant/client/testutil/cli_test.go @@ -0,0 +1,17 @@ +// +build norace + +package testutil + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/testutil/network" + + "github.com/stretchr/testify/suite" +) + +func TestIntegrationTestSuite(t *testing.T) { + cfg := network.DefaultConfig() + cfg.NumValidators = 3 + suite.Run(t, NewIntegrationTestSuite(cfg)) +} diff --git a/x/feegrant/client/cli/cli_test.go b/x/feegrant/client/testutil/suite.go similarity index 96% rename from x/feegrant/client/cli/cli_test.go rename to x/feegrant/client/testutil/suite.go index 787a342d1..a247ac7e8 100644 --- a/x/feegrant/client/cli/cli_test.go +++ b/x/feegrant/client/testutil/suite.go @@ -1,6 +1,4 @@ -// +build norace - -package cli_test +package testutil import ( "fmt" @@ -33,6 +31,10 @@ type IntegrationTestSuite struct { addedGrant types.FeeAllowanceGrant } +func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { + return &IntegrationTestSuite{cfg: cfg} +} + func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") @@ -40,11 +42,7 @@ func (s *IntegrationTestSuite) SetupSuite() { s.T().Skip("skipping test in unit-tests mode.") } - cfg := network.DefaultConfig() - cfg.NumValidators = 3 - - s.cfg = cfg - s.network = network.New(s.T(), cfg) + s.network = network.New(s.T(), s.cfg) _, err := s.network.WaitForHeight(1) s.Require().NoError(err) @@ -255,8 +253,8 @@ func (s *IntegrationTestSuite) TestNewCmdFeeGrant() { name string args []string expectErr bool - respType proto.Message expectedCode uint32 + respType proto.Message }{ { "wrong granter address", @@ -269,7 +267,7 @@ func (s *IntegrationTestSuite) TestNewCmdFeeGrant() { }, commonFlags..., ), - true, nil, 0, + true, 0, nil, }, { "wrong grantee address", @@ -282,7 +280,7 @@ func (s *IntegrationTestSuite) TestNewCmdFeeGrant() { }, commonFlags..., ), - true, nil, 0, + true, 0, nil, }, { "valid basic fee grant", @@ -295,7 +293,7 @@ func (s *IntegrationTestSuite) TestNewCmdFeeGrant() { }, commonFlags..., ), - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, { "valid basic fee grant without spend limit", @@ -307,7 +305,7 @@ func (s *IntegrationTestSuite) TestNewCmdFeeGrant() { }, commonFlags..., ), - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, { "valid basic fee grant without expiration", @@ -320,7 +318,7 @@ func (s *IntegrationTestSuite) TestNewCmdFeeGrant() { }, commonFlags..., ), - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, { "valid basic fee grant without spend-limit and expiration", @@ -332,7 +330,7 @@ func (s *IntegrationTestSuite) TestNewCmdFeeGrant() { }, commonFlags..., ), - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, { "try to add existed grant", @@ -345,7 +343,7 @@ func (s *IntegrationTestSuite) TestNewCmdFeeGrant() { }, commonFlags..., ), - false, &sdk.TxResponse{}, 18, + false, 18, &sdk.TxResponse{}, }, { "invalid number of args(periodic fee grant)", @@ -360,7 +358,7 @@ func (s *IntegrationTestSuite) TestNewCmdFeeGrant() { }, commonFlags..., ), - true, nil, 0, + true, 0, nil, }, { "period mentioned and period limit omitted, invalid periodic grant", @@ -375,7 +373,7 @@ func (s *IntegrationTestSuite) TestNewCmdFeeGrant() { }, commonFlags..., ), - true, nil, 0, + true, 0, nil, }, { "period cannot be greater than the actual expiration(periodic fee grant)", @@ -391,7 +389,7 @@ func (s *IntegrationTestSuite) TestNewCmdFeeGrant() { }, commonFlags..., ), - true, nil, 0, + true, 0, nil, }, { "valid periodic fee grant", @@ -407,7 +405,7 @@ func (s *IntegrationTestSuite) TestNewCmdFeeGrant() { }, commonFlags..., ), - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, { "valid periodic fee grant without spend-limit", @@ -422,7 +420,7 @@ func (s *IntegrationTestSuite) TestNewCmdFeeGrant() { }, commonFlags..., ), - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, { "valid periodic fee grant without expiration", @@ -437,7 +435,7 @@ func (s *IntegrationTestSuite) TestNewCmdFeeGrant() { }, commonFlags..., ), - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, { "valid periodic fee grant without spend-limit and expiration", @@ -451,7 +449,7 @@ func (s *IntegrationTestSuite) TestNewCmdFeeGrant() { }, commonFlags..., ), - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, } @@ -491,8 +489,8 @@ func (s *IntegrationTestSuite) TestNewCmdRevokeFeegrant() { name string args []string expectErr bool - respType proto.Message expectedCode uint32 + respType proto.Message }{ { "invalid grantee", @@ -504,9 +502,7 @@ func (s *IntegrationTestSuite) TestNewCmdRevokeFeegrant() { }, commonFlags..., ), - true, - nil, - 0, + true, 0, nil, }, { "invalid grantee", @@ -518,9 +514,7 @@ func (s *IntegrationTestSuite) TestNewCmdRevokeFeegrant() { }, commonFlags..., ), - true, - nil, - 0, + true, 0, nil, }, { "Non existed grant", @@ -532,9 +526,7 @@ func (s *IntegrationTestSuite) TestNewCmdRevokeFeegrant() { }, commonFlags..., ), - false, - &sdk.TxResponse{}, - 4, + false, 4, &sdk.TxResponse{}, }, { "Valid revoke", @@ -546,9 +538,7 @@ func (s *IntegrationTestSuite) TestNewCmdRevokeFeegrant() { }, commonFlags..., ), - false, - &sdk.TxResponse{}, - 0, + false, 0, &sdk.TxResponse{}, }, } @@ -796,7 +786,3 @@ func (s *IntegrationTestSuite) TestFilteredFeeAllowance() { }) } } - -func TestIntegrationTestSuite(t *testing.T) { - suite.Run(t, new(IntegrationTestSuite)) -} diff --git a/x/genutil/client/testutil/cli_test.go b/x/genutil/client/testutil/cli_test.go new file mode 100644 index 000000000..dd36a6af2 --- /dev/null +++ b/x/genutil/client/testutil/cli_test.go @@ -0,0 +1,17 @@ +// +build norace + +package testutil + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/testutil/network" + + "github.com/stretchr/testify/suite" +) + +func TestIntegrationTestSuite(t *testing.T) { + cfg := network.DefaultConfig() + cfg.NumValidators = 1 + suite.Run(t, NewIntegrationTestSuite(cfg)) +} diff --git a/x/genutil/client/cli/migrate_test.go b/x/genutil/client/testutil/migrate.go similarity index 98% rename from x/genutil/client/cli/migrate_test.go rename to x/genutil/client/testutil/migrate.go index 7e2f0e17a..4645f832b 100644 --- a/x/genutil/client/cli/migrate_test.go +++ b/x/genutil/client/testutil/migrate.go @@ -1,4 +1,4 @@ -package cli_test +package testutil import ( "testing" @@ -52,6 +52,7 @@ func (s *IntegrationTestSuite) TestMigrateGenesis() { } for _, tc := range testCases { + tc := tc s.Run(tc.name, func() { genesisFile := testutil.WriteToNewTempFile(s.T(), tc.genesis) jsonOutput, err := clitestutil.ExecTestCLICmd(val0.ClientCtx, cli.MigrateGenesisCmd(), []string{tc.target, genesisFile.Name()}) diff --git a/x/genutil/client/cli/gentx_test.go b/x/genutil/client/testutil/suite.go similarity index 90% rename from x/genutil/client/cli/gentx_test.go rename to x/genutil/client/testutil/suite.go index b57336759..a0bc047b4 100644 --- a/x/genutil/client/cli/gentx_test.go +++ b/x/genutil/client/testutil/suite.go @@ -1,4 +1,4 @@ -package cli_test +package testutil import ( "context" @@ -6,7 +6,6 @@ import ( "io/ioutil" "os" "path/filepath" - "testing" "github.com/stretchr/testify/suite" @@ -28,14 +27,14 @@ type IntegrationTestSuite struct { network *network.Network } +func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { + return &IntegrationTestSuite{cfg: cfg} +} + func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") - cfg := network.DefaultConfig() - cfg.NumValidators = 1 - - s.cfg = cfg - s.network = network.New(s.T(), cfg) + s.network = network.New(s.T(), s.cfg) _, err := s.network.WaitForHeight(1) s.Require().NoError(err) @@ -91,7 +90,3 @@ func (s *IntegrationTestSuite) TestGenTxCmd() { err = tx.ValidateBasic() s.Require().NoError(err) } - -func TestIntegrationTestSuite(t *testing.T) { - suite.Run(t, new(IntegrationTestSuite)) -} diff --git a/x/genutil/client/cli/validate_genesis_test.go b/x/genutil/client/testutil/validate_genesis.go similarity index 98% rename from x/genutil/client/cli/validate_genesis_test.go rename to x/genutil/client/testutil/validate_genesis.go index ea3d49c47..fe34e04bb 100644 --- a/x/genutil/client/cli/validate_genesis_test.go +++ b/x/genutil/client/testutil/validate_genesis.go @@ -1,4 +1,4 @@ -package cli_test +package testutil import ( "github.com/cosmos/cosmos-sdk/testutil" @@ -87,6 +87,7 @@ func (s *IntegrationTestSuite) TestValidateGenesis() { } for _, tc := range testCases { + tc := tc s.Run(tc.name, func() { genesisFile := testutil.WriteToNewTempFile(s.T(), tc.genesis) _, err := clitestutil.ExecTestCLICmd(val0.ClientCtx, cli.ValidateGenesisCmd(nil), []string{genesisFile.Name()}) diff --git a/x/gov/client/testutil/cli_test.go b/x/gov/client/testutil/cli_test.go new file mode 100644 index 000000000..dd36a6af2 --- /dev/null +++ b/x/gov/client/testutil/cli_test.go @@ -0,0 +1,17 @@ +// +build norace + +package testutil + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/testutil/network" + + "github.com/stretchr/testify/suite" +) + +func TestIntegrationTestSuite(t *testing.T) { + cfg := network.DefaultConfig() + cfg.NumValidators = 1 + suite.Run(t, NewIntegrationTestSuite(cfg)) +} diff --git a/x/gov/client/cli/cli_test.go b/x/gov/client/testutil/suite.go similarity index 94% rename from x/gov/client/cli/cli_test.go rename to x/gov/client/testutil/suite.go index 8b56aff9d..2bc14f0f4 100644 --- a/x/gov/client/cli/cli_test.go +++ b/x/gov/client/testutil/suite.go @@ -1,11 +1,8 @@ -// +build norace - -package cli_test +package testutil import ( "fmt" "strings" - "testing" "github.com/cosmos/cosmos-sdk/testutil" @@ -19,7 +16,6 @@ import ( "github.com/cosmos/cosmos-sdk/testutil/network" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/gov/client/cli" - govtestutil "github.com/cosmos/cosmos-sdk/x/gov/client/testutil" "github.com/cosmos/cosmos-sdk/x/gov/types" ) @@ -30,12 +26,13 @@ type IntegrationTestSuite struct { network *network.Network } +func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { + return &IntegrationTestSuite{cfg: cfg} +} + func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") - s.cfg = network.DefaultConfig() - s.cfg.NumValidators = 1 - s.network = network.New(s.T(), s.cfg) _, err := s.network.WaitForHeight(1) @@ -44,7 +41,7 @@ func (s *IntegrationTestSuite) SetupSuite() { val := s.network.Validators[0] // create a proposal with deposit - _, err = govtestutil.MsgSubmitProposal(val.ClientCtx, val.Address.String(), + _, err = MsgSubmitProposal(val.ClientCtx, val.Address.String(), "Text Proposal 1", "Where is the title!?", types.ProposalTypeText, fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, types.DefaultMinDepositTokens).String())) s.Require().NoError(err) @@ -52,18 +49,18 @@ func (s *IntegrationTestSuite) SetupSuite() { s.Require().NoError(err) // vote for proposal - _, err = govtestutil.MsgVote(val.ClientCtx, val.Address.String(), "1", "yes") + _, err = MsgVote(val.ClientCtx, val.Address.String(), "1", "yes") s.Require().NoError(err) // create a proposal without deposit - _, err = govtestutil.MsgSubmitProposal(val.ClientCtx, val.Address.String(), + _, err = MsgSubmitProposal(val.ClientCtx, val.Address.String(), "Text Proposal 2", "Where is the title!?", types.ProposalTypeText) s.Require().NoError(err) _, err = s.network.WaitForHeight(1) s.Require().NoError(err) // create a proposal3 with deposit - _, err = govtestutil.MsgSubmitProposal(val.ClientCtx, val.Address.String(), + _, err = MsgSubmitProposal(val.ClientCtx, val.Address.String(), "Text Proposal 3", "Where is the title!?", types.ProposalTypeText, fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, types.DefaultMinDepositTokens).String())) s.Require().NoError(err) @@ -71,7 +68,7 @@ func (s *IntegrationTestSuite) SetupSuite() { s.Require().NoError(err) // vote for proposal3 as val - _, err = govtestutil.MsgVote(val.ClientCtx, val.Address.String(), "3", "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05") + _, err = MsgVote(val.ClientCtx, val.Address.String(), "3", "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05") s.Require().NoError(err) } @@ -296,8 +293,8 @@ func (s *IntegrationTestSuite) TestNewCmdSubmitProposal() { name string args []string expectErr bool - respType proto.Message expectedCode uint32 + respType proto.Message }{ { "invalid proposal (file)", @@ -307,7 +304,7 @@ func (s *IntegrationTestSuite) TestNewCmdSubmitProposal() { fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - true, nil, 0, + true, 0, nil, }, { "invalid proposal", @@ -319,7 +316,7 @@ func (s *IntegrationTestSuite) TestNewCmdSubmitProposal() { fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - true, nil, 0, + true, 0, nil, }, { "valid transaction (file)", @@ -330,7 +327,7 @@ func (s *IntegrationTestSuite) TestNewCmdSubmitProposal() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, { "valid transaction", @@ -344,7 +341,7 @@ func (s *IntegrationTestSuite) TestNewCmdSubmitProposal() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, } @@ -576,7 +573,7 @@ func (s *IntegrationTestSuite) TestNewCmdDeposit() { { "without proposal id", []string{ - sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)).String(), //10stake + sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)).String(), // 10stake fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), @@ -599,7 +596,7 @@ func (s *IntegrationTestSuite) TestNewCmdDeposit() { "deposit on non existing proposal", []string{ "10", - sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)).String(), //10stake + sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)).String(), // 10stake fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), @@ -611,7 +608,7 @@ func (s *IntegrationTestSuite) TestNewCmdDeposit() { "deposit on non existing proposal", []string{ "1", - sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)).String(), //10stake + sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)).String(), // 10stake fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), @@ -790,7 +787,7 @@ func (s *IntegrationTestSuite) TestNewCmdVote() { "vote for invalid proposal", []string{ "10", - fmt.Sprintf("%s", "yes"), + "yes", fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), @@ -802,7 +799,7 @@ func (s *IntegrationTestSuite) TestNewCmdVote() { "valid vote", []string{ "1", - fmt.Sprintf("%s", "yes"), + "yes", fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), @@ -850,7 +847,7 @@ func (s *IntegrationTestSuite) TestNewCmdWeightedVote() { "vote for invalid proposal", []string{ "10", - fmt.Sprintf("%s", "yes"), + "yes", fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), @@ -862,7 +859,7 @@ func (s *IntegrationTestSuite) TestNewCmdWeightedVote() { "valid vote", []string{ "1", - fmt.Sprintf("%s", "yes"), + "yes", fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), @@ -874,7 +871,7 @@ func (s *IntegrationTestSuite) TestNewCmdWeightedVote() { "invalid valid split vote string", []string{ "1", - fmt.Sprintf("%s", "yes/0.6,no/0.3,abstain/0.05,no_with_veto/0.05"), + "yes/0.6,no/0.3,abstain/0.05,no_with_veto/0.05", fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), @@ -886,7 +883,7 @@ func (s *IntegrationTestSuite) TestNewCmdWeightedVote() { "valid split vote", []string{ "1", - fmt.Sprintf("%s", "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05"), + "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05", fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), @@ -915,7 +912,3 @@ func (s *IntegrationTestSuite) TestNewCmdWeightedVote() { }) } } - -func TestIntegrationTestSuite(t *testing.T) { - suite.Run(t, new(IntegrationTestSuite)) -} diff --git a/x/mint/client/testutil/cli_test.go b/x/mint/client/testutil/cli_test.go new file mode 100644 index 000000000..dd36a6af2 --- /dev/null +++ b/x/mint/client/testutil/cli_test.go @@ -0,0 +1,17 @@ +// +build norace + +package testutil + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/testutil/network" + + "github.com/stretchr/testify/suite" +) + +func TestIntegrationTestSuite(t *testing.T) { + cfg := network.DefaultConfig() + cfg.NumValidators = 1 + suite.Run(t, NewIntegrationTestSuite(cfg)) +} diff --git a/x/mint/client/cli/cli_test.go b/x/mint/client/testutil/suite.go similarity index 87% rename from x/mint/client/cli/cli_test.go rename to x/mint/client/testutil/suite.go index 6425f369a..24e742676 100644 --- a/x/mint/client/cli/cli_test.go +++ b/x/mint/client/testutil/suite.go @@ -1,18 +1,15 @@ -// +build norace - -package cli_test +package testutil import ( "fmt" "strings" - "testing" "github.com/stretchr/testify/suite" tmcli "github.com/tendermint/tendermint/libs/cli" "github.com/cosmos/cosmos-sdk/client/flags" clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" - testnet "github.com/cosmos/cosmos-sdk/testutil/network" + "github.com/cosmos/cosmos-sdk/testutil/network" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/mint/client/cli" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" @@ -21,32 +18,33 @@ import ( type IntegrationTestSuite struct { suite.Suite - cfg testnet.Config - network *testnet.Network + cfg network.Config + network *network.Network +} + +func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { + return &IntegrationTestSuite{cfg: cfg} } func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") - cfg := testnet.DefaultConfig() - genesisState := cfg.GenesisState - cfg.NumValidators = 1 + genesisState := s.cfg.GenesisState var mintData minttypes.GenesisState - s.Require().NoError(cfg.Codec.UnmarshalJSON(genesisState[minttypes.ModuleName], &mintData)) + s.Require().NoError(s.cfg.Codec.UnmarshalJSON(genesisState[minttypes.ModuleName], &mintData)) inflation := sdk.MustNewDecFromStr("1.0") mintData.Minter.Inflation = inflation mintData.Params.InflationMin = inflation mintData.Params.InflationMax = inflation - mintDataBz, err := cfg.Codec.MarshalJSON(&mintData) + mintDataBz, err := s.cfg.Codec.MarshalJSON(&mintData) s.Require().NoError(err) genesisState[minttypes.ModuleName] = mintDataBz - cfg.GenesisState = genesisState + s.cfg.GenesisState = genesisState - s.cfg = cfg - s.network = testnet.New(s.T(), cfg) + s.network = network.New(s.T(), s.cfg) _, err = s.network.WaitForHeight(1) s.Require().NoError(err) @@ -163,7 +161,3 @@ func (s *IntegrationTestSuite) TestGetCmdQueryAnnualProvisions() { }) } } - -func TestIntegrationTestSuite(t *testing.T) { - suite.Run(t, new(IntegrationTestSuite)) -} diff --git a/x/params/client/testutil/cli_test.go b/x/params/client/testutil/cli_test.go new file mode 100644 index 000000000..dd36a6af2 --- /dev/null +++ b/x/params/client/testutil/cli_test.go @@ -0,0 +1,17 @@ +// +build norace + +package testutil + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/testutil/network" + + "github.com/stretchr/testify/suite" +) + +func TestIntegrationTestSuite(t *testing.T) { + cfg := network.DefaultConfig() + cfg.NumValidators = 1 + suite.Run(t, NewIntegrationTestSuite(cfg)) +} diff --git a/x/params/client/cli/cli_test.go b/x/params/client/testutil/suite.go similarity index 86% rename from x/params/client/cli/cli_test.go rename to x/params/client/testutil/suite.go index 6254a45ea..e539b8791 100644 --- a/x/params/client/cli/cli_test.go +++ b/x/params/client/testutil/suite.go @@ -1,11 +1,8 @@ -// +build norace - -package cli_test +package testutil import ( "fmt" "strings" - "testing" "github.com/stretchr/testify/suite" tmcli "github.com/tendermint/tendermint/libs/cli" @@ -22,14 +19,14 @@ type IntegrationTestSuite struct { network *network.Network } +func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { + return &IntegrationTestSuite{cfg: cfg} +} + func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") - cfg := network.DefaultConfig() - cfg.NumValidators = 1 - - s.cfg = cfg - s.network = network.New(s.T(), cfg) + s.network = network.New(s.T(), s.cfg) _, err := s.network.WaitForHeight(1) s.Require().NoError(err) @@ -81,7 +78,3 @@ value: "100"`, }) } } - -func TestIntegrationTestSuite(t *testing.T) { - suite.Run(t, new(IntegrationTestSuite)) -} diff --git a/x/slashing/client/testutil/cli_test.go b/x/slashing/client/testutil/cli_test.go new file mode 100644 index 000000000..dd36a6af2 --- /dev/null +++ b/x/slashing/client/testutil/cli_test.go @@ -0,0 +1,17 @@ +// +build norace + +package testutil + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/testutil/network" + + "github.com/stretchr/testify/suite" +) + +func TestIntegrationTestSuite(t *testing.T) { + cfg := network.DefaultConfig() + cfg.NumValidators = 1 + suite.Run(t, NewIntegrationTestSuite(cfg)) +} diff --git a/x/slashing/client/cli/cli_test.go b/x/slashing/client/testutil/suite.go similarity index 94% rename from x/slashing/client/cli/cli_test.go rename to x/slashing/client/testutil/suite.go index 84be17b76..2ab4a965e 100644 --- a/x/slashing/client/cli/cli_test.go +++ b/x/slashing/client/testutil/suite.go @@ -1,11 +1,8 @@ -// +build norace - -package cli_test +package testutil import ( "fmt" "strings" - "testing" "github.com/gogo/protobuf/proto" "github.com/stretchr/testify/suite" @@ -25,16 +22,16 @@ type IntegrationTestSuite struct { network *network.Network } +func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { + return &IntegrationTestSuite{cfg: cfg} +} + // SetupSuite executes bootstrapping logic before all the tests, i.e. once before // the entire suite, start executing. func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") - cfg := network.DefaultConfig() - cfg.NumValidators = 1 - - s.cfg = cfg - s.network = network.New(s.T(), cfg) + s.network = network.New(s.T(), s.cfg) _, err := s.network.WaitForHeight(1) s.Require().NoError(err) @@ -149,8 +146,8 @@ func (s *IntegrationTestSuite) TestNewUnjailTxCmd() { name string args []string expectErr bool - respType proto.Message expectedCode uint32 + respType proto.Message }{ { "valid transaction", @@ -160,7 +157,7 @@ func (s *IntegrationTestSuite) TestNewUnjailTxCmd() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), // sync mode as there are no funds yet fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, } @@ -184,7 +181,3 @@ func (s *IntegrationTestSuite) TestNewUnjailTxCmd() { }) } } - -func TestIntegrationTestSuite(t *testing.T) { - suite.Run(t, new(IntegrationTestSuite)) -} diff --git a/x/staking/client/rest/grpc_query_test.go b/x/staking/client/rest/grpc_query_test.go index 6e98844c4..f0cc39996 100644 --- a/x/staking/client/rest/grpc_query_test.go +++ b/x/staking/client/rest/grpc_query_test.go @@ -756,15 +756,15 @@ func (s *IntegrationTestSuite) TestQueryHistoricalInfoGRPC() { resp, err := rest.GetRequest(tc.url) s.Require().NoError(err) - var historical_info types.QueryHistoricalInfoResponse + var historicalInfo types.QueryHistoricalInfoResponse - err = val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, &historical_info) + err = val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, &historicalInfo) if tc.error { s.Require().Error(err) } else { s.Require().NoError(err) - s.Require().NotNil(historical_info) + s.Require().NotNil(historicalInfo) } }) } diff --git a/x/staking/client/testutil/cli_test.go b/x/staking/client/testutil/cli_test.go new file mode 100644 index 000000000..0a7a5cc25 --- /dev/null +++ b/x/staking/client/testutil/cli_test.go @@ -0,0 +1,17 @@ +// +build norace + +package testutil + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/testutil/network" + + "github.com/stretchr/testify/suite" +) + +func TestIntegrationTestSuite(t *testing.T) { + cfg := network.DefaultConfig() + cfg.NumValidators = 2 + suite.Run(t, NewIntegrationTestSuite(cfg)) +} diff --git a/x/staking/client/cli/cli_test.go b/x/staking/client/testutil/suite.go similarity index 97% rename from x/staking/client/cli/cli_test.go rename to x/staking/client/testutil/suite.go index 156afb4b3..d05f45b4c 100644 --- a/x/staking/client/cli/cli_test.go +++ b/x/staking/client/testutil/suite.go @@ -1,6 +1,4 @@ -// +build norace - -package cli_test +package testutil import ( "context" @@ -24,7 +22,6 @@ import ( "github.com/cosmos/cosmos-sdk/types/query" banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" "github.com/cosmos/cosmos-sdk/x/staking/client/cli" - stakingtestutil "github.com/cosmos/cosmos-sdk/x/staking/client/testutil" "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -35,6 +32,10 @@ type IntegrationTestSuite struct { network *network.Network } +func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { + return &IntegrationTestSuite{cfg: cfg} +} + func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") @@ -42,8 +43,6 @@ func (s *IntegrationTestSuite) SetupSuite() { s.T().Skip("skipping test in unit-tests mode.") } - s.cfg = network.DefaultConfig() - s.cfg.NumValidators = 2 s.network = network.New(s.T(), s.cfg) _, err := s.network.WaitForHeight(1) @@ -56,7 +55,7 @@ func (s *IntegrationTestSuite) SetupSuite() { val2 := s.network.Validators[1] // redelegate - _, err = stakingtestutil.MsgRedelegateExec( + _, err = MsgRedelegateExec( val.ClientCtx, val.Address, val.ValAddress, @@ -68,7 +67,7 @@ func (s *IntegrationTestSuite) SetupSuite() { _, err = s.network.WaitForHeight(1) s.Require().NoError(err) // unbonding - _, err = stakingtestutil.MsgUnbondExec(val.ClientCtx, val.Address, val.ValAddress, unbond) + _, err = MsgUnbondExec(val.ClientCtx, val.Address, val.ValAddress, unbond) s.Require().NoError(err) _, err = s.network.WaitForHeight(1) s.Require().NoError(err) @@ -106,8 +105,8 @@ func (s *IntegrationTestSuite) TestNewCreateValidatorCmd() { name string args []string expectErr bool - respType proto.Message expectedCode uint32 + respType proto.Message }{ { "invalid transaction (missing amount)", @@ -125,7 +124,7 @@ func (s *IntegrationTestSuite) TestNewCreateValidatorCmd() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - true, nil, 0, + true, 0, nil, }, { "invalid transaction (missing pubkey)", @@ -144,7 +143,7 @@ func (s *IntegrationTestSuite) TestNewCreateValidatorCmd() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - true, nil, 0, + true, 0, nil, }, { "invalid transaction (missing moniker)", @@ -164,7 +163,7 @@ func (s *IntegrationTestSuite) TestNewCreateValidatorCmd() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - true, nil, 0, + true, 0, nil, }, { "valid transaction", @@ -185,7 +184,7 @@ func (s *IntegrationTestSuite) TestNewCreateValidatorCmd() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, } @@ -844,11 +843,11 @@ func (s *IntegrationTestSuite) TestGetCmdQueryHistoricalInfo() { if tc.error { s.Require().Error(err) } else { - var historical_info types.HistoricalInfo + var historicalInfo types.HistoricalInfo - err = val.ClientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &historical_info) + err = val.ClientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &historicalInfo) s.Require().NoError(err) - s.Require().NotNil(historical_info) + s.Require().NotNil(historicalInfo) } }) } @@ -938,8 +937,8 @@ func (s *IntegrationTestSuite) TestNewCmdEditValidator() { name string args []string expectErr bool - respType proto.Message expectedCode uint32 + respType proto.Message }{ { "with no edit flag (since all are optional)", @@ -949,7 +948,7 @@ func (s *IntegrationTestSuite) TestNewCmdEditValidator() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - true, nil, 0, + true, 0, nil, }, { "with no edit flag (since all are optional)", @@ -959,7 +958,7 @@ func (s *IntegrationTestSuite) TestNewCmdEditValidator() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, { "edit validator details", @@ -970,7 +969,7 @@ func (s *IntegrationTestSuite) TestNewCmdEditValidator() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, { "edit validator identity", @@ -981,7 +980,7 @@ func (s *IntegrationTestSuite) TestNewCmdEditValidator() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, { "edit validator security-contact", @@ -992,7 +991,7 @@ func (s *IntegrationTestSuite) TestNewCmdEditValidator() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, { "edit validator website", @@ -1003,7 +1002,7 @@ func (s *IntegrationTestSuite) TestNewCmdEditValidator() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, { "with all edit flags", @@ -1017,7 +1016,7 @@ func (s *IntegrationTestSuite) TestNewCmdEditValidator() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, } @@ -1064,8 +1063,8 @@ func (s *IntegrationTestSuite) TestNewCmdDelegate() { name string args []string expectErr bool - respType proto.Message expectedCode uint32 + respType proto.Message }{ { "without delegate amount", @@ -1076,7 +1075,7 @@ func (s *IntegrationTestSuite) TestNewCmdDelegate() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - true, nil, 0, + true, 0, nil, }, { "without validator address", @@ -1087,7 +1086,7 @@ func (s *IntegrationTestSuite) TestNewCmdDelegate() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - true, nil, 0, + true, 0, nil, }, { "valid transaction of delegate", @@ -1099,7 +1098,7 @@ func (s *IntegrationTestSuite) TestNewCmdDelegate() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, } @@ -1132,8 +1131,8 @@ func (s *IntegrationTestSuite) TestNewCmdRedelegate() { name string args []string expectErr bool - respType proto.Message expectedCode uint32 + respType proto.Message }{ { "without amount", @@ -1145,7 +1144,7 @@ func (s *IntegrationTestSuite) TestNewCmdRedelegate() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - true, nil, 0, + true, 0, nil, }, { "with wrong source validator address", @@ -1158,7 +1157,7 @@ func (s *IntegrationTestSuite) TestNewCmdRedelegate() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - false, &sdk.TxResponse{}, 4, + false, 4, &sdk.TxResponse{}, }, { "with wrong destination validator address", @@ -1171,7 +1170,7 @@ func (s *IntegrationTestSuite) TestNewCmdRedelegate() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - false, &sdk.TxResponse{}, 39, + false, 39, &sdk.TxResponse{}, }, { "valid transaction of delegate", @@ -1185,7 +1184,7 @@ func (s *IntegrationTestSuite) TestNewCmdRedelegate() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, } @@ -1217,8 +1216,8 @@ func (s *IntegrationTestSuite) TestNewCmdUnbond() { name string args []string expectErr bool - respType proto.Message expectedCode uint32 + respType proto.Message }{ { "Without unbond amount", @@ -1229,7 +1228,7 @@ func (s *IntegrationTestSuite) TestNewCmdUnbond() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - true, nil, 0, + true, 0, nil, }, { "Without validator address", @@ -1240,7 +1239,7 @@ func (s *IntegrationTestSuite) TestNewCmdUnbond() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - true, nil, 0, + true, 0, nil, }, { "valid transaction of unbond", @@ -1252,7 +1251,7 @@ func (s *IntegrationTestSuite) TestNewCmdUnbond() { fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), }, - false, &sdk.TxResponse{}, 0, + false, 0, &sdk.TxResponse{}, }, } @@ -1316,6 +1315,7 @@ func (s *IntegrationTestSuite) TestBlockResults() { // Create a HTTP rpc client. rpcClient, err := http.New(val.RPCAddress, "/websocket") + require.NoError(err) // Loop until we find a block result with the correct validator updates. // By experience, it happens around 2 blocks after `delHeight`. @@ -1345,7 +1345,3 @@ func (s *IntegrationTestSuite) TestBlockResults() { s.network.WaitForNextBlock() } } - -func TestIntegrationTestSuite(t *testing.T) { - suite.Run(t, new(IntegrationTestSuite)) -}