From ec0e091a87e17dd93b9d1554fb0d5138ef98d37d Mon Sep 17 00:00:00 2001 From: qua is Date: Sun, 5 May 2024 18:59:01 -0400 Subject: [PATCH] add integration tests, enable tx compute store, add gRPC calls to query compute --- go.mod | 2 +- go.sum | 4 +- integration-tests/basic-tests.sh | 124 ++++ .../test-contracts/contract.wasm.gz | Bin 0 -> 51974 bytes scripts/start-node.sh | 2 +- x/compute/client/cli/query.go | 604 ++++++++++++++++++ x/compute/internal/keeper/querier.go | 9 +- x/compute/module.go | 10 + 8 files changed, 746 insertions(+), 9 deletions(-) create mode 100755 integration-tests/basic-tests.sh create mode 100644 integration-tests/test-contracts/contract.wasm.gz create mode 100644 x/compute/client/cli/query.go diff --git a/go.mod b/go.mod index 9aee2d1f4..2e1f77aec 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ replace ( cosmossdk.io/store => github.com/scrtlabs/cosmos-sdk-store v1.0.3 github.com/cometbft/cometbft => github.com/scrtlabs/tendermint v0.38.2 github.com/cosmos/cosmos-sdk => github.com/scrtlabs/cosmos-sdk v0.46.0-beta2.0.20240430231059-06a080edfca9 - github.com/cosmos/iavl => github.com/cosmos/iavl v1.0.3 + github.com/cosmos/iavl => github.com/scrtlabs/iavl v1.0.1 ) require ( diff --git a/go.sum b/go.sum index 9384862ed..be8503c99 100644 --- a/go.sum +++ b/go.sum @@ -356,8 +356,6 @@ github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= github.com/cosmos/gogoproto v1.4.11 h1:LZcMHrx4FjUgrqQSWeaGC1v/TeuVFqSLa43CC6aWR2g= github.com/cosmos/gogoproto v1.4.11/go.mod h1:/g39Mh8m17X8Q/GDEs5zYTSNaNnInBSohtaxzQnYq1Y= -github.com/cosmos/iavl v1.0.3 h1:yNJ5oS6gZ4ZKg6NGE78F8xeF2jFU0TZqFiczUdtU9JA= -github.com/cosmos/iavl v1.0.3/go.mod h1:8xIUkgVvwvVrBu81scdPty+/Dx9GqwHnAvXz4cwF7RY= github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v8 v8.0.1 h1:BHn+JWZILxkUT9IrlP1ctUfo9ENGi+EmiZ9om1XSHIw= github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v8 v8.0.1/go.mod h1:82hPO/tRawbuFad2gPwChvpZ0JEIoNi91LwVneAYCeM= github.com/cosmos/ibc-go/modules/capability v1.0.0 h1:r/l++byFtn7jHYa09zlAdSeevo8ci1mVZNO9+V0xsLE= @@ -957,6 +955,8 @@ github.com/scrtlabs/cosmos-sdk v0.46.0-beta2.0.20240430231059-06a080edfca9 h1:a+ github.com/scrtlabs/cosmos-sdk v0.46.0-beta2.0.20240430231059-06a080edfca9/go.mod h1:ehEJ6NYUAKWxVGMczCoQJ9XXbEURe1T8KG7mL5PAMok= github.com/scrtlabs/cosmos-sdk-store v1.0.3 h1:CBzurqDLXOGGLFPnMvGUKqL4lvnnBPVY28ZhVEpPID0= github.com/scrtlabs/cosmos-sdk-store v1.0.3/go.mod h1:EFtENTqVTuWwitGW1VwaBct+yDagk7oG/axBMPH+FXs= +github.com/scrtlabs/iavl v1.0.1 h1:WL9YhEvOp+guahFQD25m67NvVyrX3jC90sVpebODDVc= +github.com/scrtlabs/iavl v1.0.1/go.mod h1:8xIUkgVvwvVrBu81scdPty+/Dx9GqwHnAvXz4cwF7RY= github.com/scrtlabs/tendermint v0.38.2 h1:a2L2v70guPMvQNbr38Cl5jwuLRBJim1iznBV+4x7fyU= github.com/scrtlabs/tendermint v0.38.2/go.mod h1:FbzZXk9nkr7atxsGcBn6tlM6Q+BD4GA6wlgY5Qk3FzQ= github.com/scrtlabs/tm-secret-enclave v1.11.3 h1:3WVDS4x11tidRvCK/FbemtuVDMgujvSzMSt9sKLaMwY= diff --git a/integration-tests/basic-tests.sh b/integration-tests/basic-tests.sh new file mode 100755 index 000000000..2b5bfe171 --- /dev/null +++ b/integration-tests/basic-tests.sh @@ -0,0 +1,124 @@ +#!/bin/bash + +SECRETCLI=${1:-./secretcli} +SECRETD_HOME=${2:-$HOME/.secretd_local} +CHAINID=${3:-secretdev-1} +SECRETD=${4:-"http://localhost:26657"} + +if ! [ -f $SECRETD_HOME/config/genesis.json ]; then + echo "Cannot find $SECRETD_HOME/config/genesis.json." + exit 1 +fi + +set -x +set -o errexit + +$SECRETCLI config set client chain-id "$CHAINID" +$SECRETCLI config set client output json +$SECRETCLI config set client keyring-backend test +$SECRETCLI config set client node $SECRETD + +$SECRETCLI status --output=json | js + +$SECRETCLI keys list --keyring-backend="test" --home=$SECRETD_HOME --output=json | jq + +address_v=$($SECRETCLI keys show -a validator --keyring-backend="test" --home=$SECRETD_HOME) + +address_a=$($SECRETCLI keys show -a a --keyring-backend="test" --home=$SECRETD_HOME) +address_b=$($SECRETCLI keys show -a b --keyring-backend="test" --home=$SECRETD_HOME) +address_c=$($SECRETCLI keys show -a c --keyring-backend="test" --home=$SECRETD_HOME) +address_d=$($SECRETCLI keys show -a d --keyring-backend="test" --home=$SECRETD_HOME) + +key_a=$($SECRETCLI keys show -p a --keyring-backend="test" --home=$SECRETD_HOME) +key_b=$($SECRETCLI keys show -p b --keyring-backend="test" --home=$SECRETD_HOME) +key_c=$($SECRETCLI keys show -p c --keyring-backend="test" --home=$SECRETD_HOME) +key_d=$($SECRETCLI keys show -p d --keyring-backend="test" --home=$SECRETD_HOME) + +$SECRETCLI q bank balances $address_a --home=$SECRETD_HOME --output=json | jq +$SECRETCLI q bank balances $address_b --home=$SECRETD_HOME --output=json | jq +$SECRETCLI q bank balances $address_c --home=$SECRETD_HOME --output=json | jq +$SECRETCLI q bank balances $address_d --home=$SECRETD_HOME --output=json | jq + +# $SECRETCLI tx bank send $address_a $address_b 10uscrt --gas=auto --gas-adjustment=1.0 --chain-id=$CHAINID --home=$SECRETD_HOME --keyring-backend="test" --output=json | jq + +txhash=$($SECRETCLI tx bank send $address_a $address_b 10uscrt --gas-prices=0.25uscrt -y --chain-id=$CHAINID --home=$SECRETD_HOME --keyring-backend="test" --output=json | jq ".txhash" | sed 's/"//g') +echo "FIX: $SECRETCLI q tx --type="hash" "$txhash" --home=$SECRETD_HOME" +$SECRETCLI q bank balances $address_a --home=$SECRETD_HOME --output=json | jq +$SECRETCLI q bank balances $address_b --home=$SECRETD_HOME --output=json | jq + +txhash=$($SECRETCLI tx bank send $address_b $address_c 10uscrt --gas-prices=0.25uscrt -y --chain-id=$CHAINID --home=$SECRETD_HOME --keyring-backend="test" --output=json | jq ".txhash" | sed 's/"//g') +echo "FIX: $SECRETCLI q tx --type="hash" "$txhash" --home=$SECRETD_HOME" +$SECRETCLI q bank balances $address_b --home=$SECRETD_HOME --output=json | jq +$SECRETCLI q bank balances $address_c --home=$SECRETD_HOME --output=json | jq + +txhash=$($SECRETCLI tx bank send $address_c $address_d 10uscrt --gas-prices=0.25uscrt -y --chain-id=$CHAINID --home=$SECRETD_HOME --keyring-backend="test" --output=json | jq ".txhash" | sed 's/"//g') +echo "FIX: $SECRETCLI q tx --type="hash" "$txhash" --home=$SECRETD_HOME" +$SECRETCLI q bank balances $address_c --home=$SECRETD_HOME --output=json | jq +$SECRETCLI q bank balances $address_d --home=$SECRETD_HOME --output=json | jq + +txhash=$($SECRETCLI tx bank send $address_d $address_a 10uscrt --gas-prices=0.25uscrt -y --chain-id=$CHAINID --home=$SECRETD_HOME --keyring-backend="test" --output=json | jq ".txhash" | sed 's/"//g') +echo "FIX: $SECRETCLI q tx --type="hash" "$txhash" --home=$SECRETD_HOME" +$SECRETCLI q bank balances $address_d --home=$SECRETD_HOME --output=json | jq +$SECRETCLI q bank balances $address_a --home=$SECRETD_HOME --output=json | jq + + +$SECRETCLI q distribution params --output=json | jq + +$SECRETCLI q distribution community-pool --output=json | jq + +address_valop=$(jq '.app_state.genutil.gen_txs[0].body.messages[0].validator_address' $SECRETD_HOME/config/genesis.json) + +if [[ -z $address_valop ]];then + echo "No GENESIS tx in genesis.json" + exit 1 +fi + +address_valop=$(echo $address_valop | sed 's/"//g') +$SECRETCLI q distribution validator-outstanding-rewards $address_valop --output=json | jq + +$SECRETCLI q distribution commission $address_valop --output=json | jq + +echo "FIXME: get realistic height" +$SECRETCLI q distribution slashes $address_valop "1" "10" --output=json | jq + +DIR=$(pwd) +WORK_DIR=$(mktemp -d -p ${DIR}) +if [ ! -d $WORK_DIR ]; then + echo "Could not create $WORK_DIR" + exit 1 +fi + +function cleanup { + echo "Clean up $WORK_DIR" + #rm -rf "$WORK_DIR" +} + +trap cleanup EXIT + + +cd $WORK_DIR + +cargo generate --git https://github.com/scrtlabs/secret-template.git --name secret-test-contract + +cd secret-test-contract +make build + +if [[ ! contract.wasm.gz ]];then + echo "failed to build a test contract" + cd - + return 1 +fi + +cd $DIR +echo "FIXME: add deploy contract" + +$SECRETCLI keys add scrt_smart_contract -y --keyring-backend="test" --home=$SECRETD_HOME --output=json | jq +address_scrt=$($SECRETCLI keys show -a scrt_smart_contract --keyring-backend="test" --home=$SECRETD_HOME) +$SECRETCLI q bank balances $address_scrt --home=$SECRETD_HOME --output=json | jq +#curl http://localhost:5000/faucet?address=$address_scrt +txhash=$($SECRETCLI tx bank send $address_a $address_scrt 100000uscrt --gas-prices=0.25uscrt -y --chain-id=$CHAINID --home=$SECRETD_HOME --keyring-backend="test" --output=json | jq ".txhash" | sed 's/"//g') +$SECRETCLI q bank balances $address_scrt --home=$SECRETD_HOME --output=json | jq + +$SECRETCLI tx compute store $WORK_DIR/secret-test-contract/contract.wasm -y --gas 50000 --from $address_scrt --chain-id=$CHAINID --keyring-backend="test" --home=$SECRETD_HOME --output=json | jq + +$SECRETCLI q compute list-code --home=$SECRETD_HOME \ No newline at end of file diff --git a/integration-tests/test-contracts/contract.wasm.gz b/integration-tests/test-contracts/contract.wasm.gz new file mode 100644 index 0000000000000000000000000000000000000000..220520c57385112732901b8cebb03192009bde1e GIT binary patch literal 51974 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

+3i4uJzpwG(JxE_dp{( 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 z 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%0Ap%8;{?5mwAN{yxzcvZJ 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 literal 0 HcmV?d00001 diff --git a/scripts/start-node.sh b/scripts/start-node.sh index 6ff8cf816..908bc4ff1 100755 --- a/scripts/start-node.sh +++ b/scripts/start-node.sh @@ -79,4 +79,4 @@ fi # Start the secretd -LOG_LEVEL=trace $SECRETD start --pruning=nothing --bootstrap --home=$SECRETD_HOME --log_level=info +LOG_LEVEL=trace $SECRETD start --pruning=nothing --bootstrap --home=$SECRETD_HOME --log_level=debug diff --git a/x/compute/client/cli/query.go b/x/compute/client/cli/query.go new file mode 100644 index 000000000..33773ec0f --- /dev/null +++ b/x/compute/client/cli/query.go @@ -0,0 +1,604 @@ +package cli + +import ( + "context" + "fmt" + + // wasmvm "github.com/CosmWasm/wasmvm/v2" + "github.com/spf13/cobra" + "google.golang.org/protobuf/types/known/emptypb" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + + "github.com/scrtlabs/SecretNetwork/x/compute/internal/types" +) + +func GetQueryCmd() *cobra.Command { + queryCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Querying commands for the wasm module", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + SilenceUsage: true, + } + queryCmd.AddCommand( + GetCmdListCode(), + // GetCmdListContractByCode(), + // GetCmdQueryCode(), + // GetCmdQueryCodeInfo(), + // GetCmdGetContractInfo(), + // GetCmdGetContractHistory(), + // GetCmdGetContractState(), + // GetCmdListPinnedCode(), + // GetCmdQueryParams(), + // GetCmdListContractsByCreator(), + ) + return queryCmd +} + +// GetCmdListCode -> gRPC into x/compute/internal/keeper/querier.go: Codes(c context.Context, _ *empty.Empty) +func GetCmdListCode() *cobra.Command { + cmd := &cobra.Command{ + Use: "list-code", + Short: "List all wasm bytecode on the chain", + Long: "List all wasm bytecode on the chain", + Aliases: []string{"list-codes", "codes", "lco"}, + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + res, err := queryClient.Codes( + context.Background(), + &emptypb.Empty{}, + ) + if err != nil { + return err + } + return clientCtx.PrintProto(res) + }, + SilenceUsage: true, + } + flags.AddQueryFlagsToCmd(cmd) + addPaginationFlags(cmd, "list codes") + return cmd +} + +// // GetCmdListContractByCode lists all wasm code uploaded for given code id +// func GetCmdListContractByCode() *cobra.Command { +// cmd := &cobra.Command{ +// Use: "list-contract-by-code [code_id]", +// Short: "List wasm all bytecode on the chain for given code id", +// Long: "List wasm all bytecode on the chain for given code id", +// Aliases: []string{"list-contracts-by-code", "list-contracts", "contracts", "lca"}, +// Args: cobra.ExactArgs(1), +// RunE: func(cmd *cobra.Command, args []string) error { +// clientCtx, err := client.GetClientQueryContext(cmd) +// if err != nil { +// return err +// } + +// codeID, err := strconv.ParseUint(args[0], 10, 64) +// if err != nil { +// return err +// } +// if codeID == 0 { +// return errors.New("empty code id") +// } + +// pageReq, err := client.ReadPageRequest(withPageKeyDecoded(cmd.Flags())) +// if err != nil { +// return err +// } +// queryClient := types.NewQueryClient(clientCtx) +// res, err := queryClient.ContractsByCode( +// context.Background(), +// &types.QueryContractsByCodeRequest{ +// CodeId: codeID, +// Pagination: pageReq, +// }, +// ) +// if err != nil { +// return err +// } +// return clientCtx.PrintProto(res) +// }, +// SilenceUsage: true, +// } +// flags.AddQueryFlagsToCmd(cmd) +// addPaginationFlags(cmd, "list contracts by code") +// return cmd +// } + +// // GetCmdQueryCode returns the bytecode for a given contract +// func GetCmdQueryCode() *cobra.Command { +// cmd := &cobra.Command{ +// Use: "code [code_id] [output filename]", +// Short: "Downloads wasm bytecode for given code id", +// Long: "Downloads wasm bytecode for given code id", +// Aliases: []string{"source-code", "source"}, +// Args: cobra.ExactArgs(2), +// RunE: func(cmd *cobra.Command, args []string) error { +// clientCtx, err := client.GetClientQueryContext(cmd) +// if err != nil { +// return err +// } + +// codeID, err := strconv.ParseUint(args[0], 10, 64) +// if err != nil { +// return err +// } + +// queryClient := types.NewQueryClient(clientCtx) +// res, err := queryClient.Code( +// context.Background(), +// &types.QueryCodeRequest{ +// CodeId: codeID, +// }, +// ) +// if err != nil { +// return err +// } +// if len(res.Data) == 0 { +// return fmt.Errorf("contract not found") +// } + +// fmt.Printf("Downloading wasm code to %s\n", args[1]) +// return os.WriteFile(args[1], res.Data, 0o600) +// }, +// SilenceUsage: true, +// } +// flags.AddQueryFlagsToCmd(cmd) +// return cmd +// } + +// // GetCmdQueryCodeInfo returns the code info for a given code id +// func GetCmdQueryCodeInfo() *cobra.Command { +// cmd := &cobra.Command{ +// Use: "code-info [code_id]", +// Short: "Prints out metadata of a code id", +// Long: "Prints out metadata of a code id", +// Args: cobra.ExactArgs(1), +// RunE: func(cmd *cobra.Command, args []string) error { +// clientCtx, err := client.GetClientQueryContext(cmd) +// if err != nil { +// return err +// } + +// codeID, err := strconv.ParseUint(args[0], 10, 64) +// if err != nil { +// return err +// } + +// queryClient := types.NewQueryClient(clientCtx) +// res, err := queryClient.Code( +// context.Background(), +// &types.QueryCodeRequest{ +// CodeId: codeID, +// }, +// ) +// if err != nil { +// return err +// } +// if res.CodeInfoResponse == nil { +// return fmt.Errorf("contract not found") +// } + +// return clientCtx.PrintProto(res.CodeInfoResponse) +// }, +// SilenceUsage: true, +// } +// flags.AddQueryFlagsToCmd(cmd) +// return cmd +// } + +// // GetCmdGetContractInfo gets details about a given contract +// func GetCmdGetContractInfo() *cobra.Command { +// cmd := &cobra.Command{ +// Use: "contract [bech32_address]", +// Short: "Prints out metadata of a contract given its address", +// Long: "Prints out metadata of a contract given its address", +// Aliases: []string{"meta", "c"}, +// Args: cobra.ExactArgs(1), +// RunE: func(cmd *cobra.Command, args []string) error { +// clientCtx, err := client.GetClientQueryContext(cmd) +// if err != nil { +// return err +// } + +// _, err = sdk.AccAddressFromBech32(args[0]) +// if err != nil { +// return err +// } +// queryClient := types.NewQueryClient(clientCtx) +// res, err := queryClient.ContractInfo( +// context.Background(), +// &types.QueryContractInfoRequest{ +// Address: args[0], +// }, +// ) +// if err != nil { +// return err +// } +// return clientCtx.PrintProto(res) +// }, +// SilenceUsage: true, +// } +// flags.AddQueryFlagsToCmd(cmd) +// return cmd +// } + +// // GetCmdGetContractState dumps full internal state of a given contract +// func GetCmdGetContractState() *cobra.Command { +// cmd := &cobra.Command{ +// Use: "contract-state", +// Short: "Querying commands for the wasm module", +// Aliases: []string{"state", "cs", "s"}, +// DisableFlagParsing: true, +// SuggestionsMinimumDistance: 2, +// RunE: client.ValidateCmd, +// SilenceUsage: true, +// } +// cmd.AddCommand( +// GetCmdGetContractStateAll(), +// GetCmdGetContractStateRaw(), +// GetCmdGetContractStateSmart(), +// ) +// return cmd +// } + +// func GetCmdGetContractStateAll() *cobra.Command { +// cmd := &cobra.Command{ +// Use: "all [bech32_address]", +// Short: "Prints out all internal state of a contract given its address", +// Long: "Prints out all internal state of a contract given its address", +// Args: cobra.ExactArgs(1), +// RunE: func(cmd *cobra.Command, args []string) error { +// clientCtx, err := client.GetClientQueryContext(cmd) +// if err != nil { +// return err +// } + +// _, err = sdk.AccAddressFromBech32(args[0]) +// if err != nil { +// return err +// } + +// pageReq, err := client.ReadPageRequest(withPageKeyDecoded(cmd.Flags())) +// if err != nil { +// return err +// } +// queryClient := types.NewQueryClient(clientCtx) +// res, err := queryClient.AllContractState( +// context.Background(), +// &types.QueryAllContractStateRequest{ +// Address: args[0], +// Pagination: pageReq, +// }, +// ) +// if err != nil { +// return err +// } +// return clientCtx.PrintProto(res) +// }, +// SilenceUsage: true, +// } +// flags.AddQueryFlagsToCmd(cmd) +// addPaginationFlags(cmd, "contract state") +// return cmd +// } + +// func GetCmdGetContractStateRaw() *cobra.Command { +// decoder := newArgDecoder(hex.DecodeString) +// cmd := &cobra.Command{ +// Use: "raw [bech32_address] [key]", +// Short: "Prints out internal state for key of a contract given its address", +// Long: "Prints out internal state for of a contract given its address", +// Args: cobra.ExactArgs(2), +// RunE: func(cmd *cobra.Command, args []string) error { +// clientCtx, err := client.GetClientQueryContext(cmd) +// if err != nil { +// return err +// } + +// _, err = sdk.AccAddressFromBech32(args[0]) +// if err != nil { +// return err +// } +// queryData, err := decoder.DecodeString(args[1]) +// if err != nil { +// return err +// } + +// queryClient := types.NewQueryClient(clientCtx) +// res, err := queryClient.RawContractState( +// context.Background(), +// &types.QueryRawContractStateRequest{ +// Address: args[0], +// QueryData: queryData, +// }, +// ) +// if err != nil { +// return err +// } +// return clientCtx.PrintProto(res) +// }, +// SilenceUsage: true, +// } +// decoder.RegisterFlags(cmd.PersistentFlags(), "key argument") +// flags.AddQueryFlagsToCmd(cmd) +// return cmd +// } + +// func GetCmdGetContractStateSmart() *cobra.Command { +// decoder := newArgDecoder(asciiDecodeString) +// cmd := &cobra.Command{ +// Use: "smart [bech32_address] [query]", +// Short: "Calls contract with given address with query data and prints the returned result", +// Long: "Calls contract with given address with query data and prints the returned result", +// Args: cobra.ExactArgs(2), +// RunE: func(cmd *cobra.Command, args []string) error { +// clientCtx, err := client.GetClientQueryContext(cmd) +// if err != nil { +// return err +// } + +// _, err = sdk.AccAddressFromBech32(args[0]) +// if err != nil { +// return err +// } +// if args[1] == "" { +// return errors.New("query data must not be empty") +// } + +// queryData, err := decoder.DecodeString(args[1]) +// if err != nil { +// return fmt.Errorf("decode query: %s", err) +// } +// if !json.Valid(queryData) { +// return errors.New("query data must be json") +// } + +// queryClient := types.NewQueryClient(clientCtx) +// res, err := queryClient.SmartContractState( +// context.Background(), +// &types.QuerySmartContractStateRequest{ +// Address: args[0], +// QueryData: queryData, +// }, +// ) +// if err != nil { +// return err +// } +// return clientCtx.PrintProto(res) +// }, +// SilenceUsage: true, +// } +// decoder.RegisterFlags(cmd.PersistentFlags(), "query argument") +// flags.AddQueryFlagsToCmd(cmd) +// return cmd +// } + +// // GetCmdGetContractHistory prints the code history for a given contract +// func GetCmdGetContractHistory() *cobra.Command { +// cmd := &cobra.Command{ +// Use: "contract-history [bech32_address]", +// Short: "Prints out the code history for a contract given its address", +// Long: "Prints out the code history for a contract given its address", +// Aliases: []string{"history", "hist", "ch"}, +// Args: cobra.ExactArgs(1), +// RunE: func(cmd *cobra.Command, args []string) error { +// clientCtx, err := client.GetClientQueryContext(cmd) +// if err != nil { +// return err +// } + +// _, err = sdk.AccAddressFromBech32(args[0]) +// if err != nil { +// return err +// } + +// pageReq, err := client.ReadPageRequest(withPageKeyDecoded(cmd.Flags())) +// if err != nil { +// return err +// } +// queryClient := types.NewQueryClient(clientCtx) +// res, err := queryClient.ContractHistory( +// context.Background(), +// &types.QueryContractHistoryRequest{ +// Address: args[0], +// Pagination: pageReq, +// }, +// ) +// if err != nil { +// return err +// } + +// return clientCtx.PrintProto(res) +// }, +// SilenceUsage: true, +// } + +// flags.AddQueryFlagsToCmd(cmd) +// addPaginationFlags(cmd, "contract history") +// return cmd +// } + +// // GetCmdListPinnedCode lists all wasm code ids that are pinned +// func GetCmdListPinnedCode() *cobra.Command { +// cmd := &cobra.Command{ +// Use: "pinned", +// Short: "List all pinned code ids", +// Long: "List all pinned code ids", +// Args: cobra.ExactArgs(0), +// RunE: func(cmd *cobra.Command, args []string) error { +// clientCtx, err := client.GetClientQueryContext(cmd) +// if err != nil { +// return err +// } + +// pageReq, err := client.ReadPageRequest(withPageKeyDecoded(cmd.Flags())) +// if err != nil { +// return err +// } +// queryClient := types.NewQueryClient(clientCtx) +// res, err := queryClient.PinnedCodes( +// context.Background(), +// &types.QueryPinnedCodesRequest{ +// Pagination: pageReq, +// }, +// ) +// if err != nil { +// return err +// } +// return clientCtx.PrintProto(res) +// }, +// SilenceUsage: true, +// } +// flags.AddQueryFlagsToCmd(cmd) +// addPaginationFlags(cmd, "list codes") +// return cmd +// } + +// // GetCmdListContractsByCreator lists all contracts by creator +// func GetCmdListContractsByCreator() *cobra.Command { +// cmd := &cobra.Command{ +// Use: "list-contracts-by-creator [creator]", +// Short: "List all contracts by creator", +// Long: "List all contracts by creator", +// Args: cobra.ExactArgs(1), +// RunE: func(cmd *cobra.Command, args []string) error { +// clientCtx, err := client.GetClientQueryContext(cmd) +// if err != nil { +// return err +// } +// _, err = sdk.AccAddressFromBech32(args[0]) +// if err != nil { +// return err +// } +// pageReq, err := client.ReadPageRequest(withPageKeyDecoded(cmd.Flags())) +// if err != nil { +// return err +// } + +// queryClient := types.NewQueryClient(clientCtx) +// res, err := queryClient.ContractsByCreator( +// context.Background(), +// &types.QueryContractsByCreatorRequest{ +// CreatorAddress: args[0], +// Pagination: pageReq, +// }, +// ) +// if err != nil { +// return err +// } +// return clientCtx.PrintProto(res) +// }, +// SilenceUsage: true, +// } +// flags.AddQueryFlagsToCmd(cmd) +// addPaginationFlags(cmd, "list contracts by creator") +// return cmd +// } + +// type argumentDecoder struct { +// // dec is the default decoder +// dec func(string) ([]byte, error) +// asciiF, hexF, b64F bool +// } + +// func newArgDecoder(def func(string) ([]byte, error)) *argumentDecoder { +// return &argumentDecoder{dec: def} +// } + +// func (a *argumentDecoder) RegisterFlags(f *flag.FlagSet, argName string) { +// f.BoolVar(&a.asciiF, "ascii", false, "ascii encoded "+argName) +// f.BoolVar(&a.hexF, "hex", false, "hex encoded "+argName) +// f.BoolVar(&a.b64F, "b64", false, "base64 encoded "+argName) +// } + +// func (a *argumentDecoder) DecodeString(s string) ([]byte, error) { +// found := -1 +// for i, v := range []*bool{&a.asciiF, &a.hexF, &a.b64F} { +// if !*v { +// continue +// } +// if found != -1 { +// return nil, errors.New("multiple decoding flags used") +// } +// found = i +// } +// switch found { +// case 0: +// return asciiDecodeString(s) +// case 1: +// return hex.DecodeString(s) +// case 2: +// return base64.StdEncoding.DecodeString(s) +// default: +// return a.dec(s) +// } +// } + +// func asciiDecodeString(s string) ([]byte, error) { +// return []byte(s), nil +// } + +// // sdk ReadPageRequest expects binary but we encoded to base64 in our marshaller +// func withPageKeyDecoded(flagSet *flag.FlagSet) *flag.FlagSet { +// encoded, err := flagSet.GetString(flags.FlagPageKey) +// if err != nil { +// panic(err.Error()) +// } +// raw, err := base64.StdEncoding.DecodeString(encoded) +// if err != nil { +// panic(err.Error()) +// } +// err = flagSet.Set(flags.FlagPageKey, string(raw)) +// if err != nil { +// panic(err.Error()) +// } +// return flagSet +// } + +// // GetCmdQueryParams implements a command to return the current wasm +// // parameters. +// func GetCmdQueryParams() *cobra.Command { +// cmd := &cobra.Command{ +// Use: "params", +// Short: "Query the current wasm parameters", +// Args: cobra.NoArgs, +// RunE: func(cmd *cobra.Command, args []string) error { +// clientCtx, err := client.GetClientQueryContext(cmd) +// if err != nil { +// return err +// } +// queryClient := types.NewQueryClient(clientCtx) + +// params := &types.QueryParamsRequest{} +// res, err := queryClient.Params(cmd.Context(), params) +// if err != nil { +// return err +// } + +// return clientCtx.PrintProto(&res.Params) +// }, +// SilenceUsage: true, +// } + +// flags.AddQueryFlagsToCmd(cmd) + +// return cmd +// } + +// supports a subset of the SDK pagination params for better resource utilization +func addPaginationFlags(cmd *cobra.Command, query string) { + cmd.Flags().String(flags.FlagPageKey, "", fmt.Sprintf("pagination page-key of %s to query for", query)) + cmd.Flags().Uint64(flags.FlagLimit, 100, fmt.Sprintf("pagination limit of %s to query for", query)) + cmd.Flags().Bool(flags.FlagReverse, false, "results are sorted in descending order") +} diff --git a/x/compute/internal/keeper/querier.go b/x/compute/internal/keeper/querier.go index c71ea9f1f..193757483 100644 --- a/x/compute/internal/keeper/querier.go +++ b/x/compute/internal/keeper/querier.go @@ -113,13 +113,12 @@ func (q GrpcQuerier) Code(c context.Context, req *types.QueryByCodeIdRequest) (* func (q GrpcQuerier) Codes(c context.Context, _ *empty.Empty) (*types.QueryCodesResponse, error) { response, err := queryCodeList(sdk.UnwrapSDKContext(c), q.keeper) - switch { - case err != nil: + if err != nil { return nil, err - case response == nil: - return nil, types.ErrNotFound } - + if response == nil { + response = make([]types.CodeInfoResponse, 0) + } return &types.QueryCodesResponse{CodeInfos: response}, nil } diff --git a/x/compute/module.go b/x/compute/module.go index c0891154f..56c5e42b8 100644 --- a/x/compute/module.go +++ b/x/compute/module.go @@ -5,6 +5,7 @@ import ( "encoding/json" "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" @@ -12,6 +13,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" + "github.com/scrtlabs/SecretNetwork/x/compute/client/cli" "github.com/scrtlabs/SecretNetwork/x/compute/internal/keeper" "github.com/scrtlabs/SecretNetwork/x/compute/internal/types" ) @@ -59,6 +61,14 @@ func (AppModuleBasic) ValidateGenesis(marshaler codec.JSONCodec, _ client.TxEnco return ValidateGenesis(data) } +func (b AppModuleBasic) GetTxCmd() *cobra.Command { + return cli.GetTxCmd() +} + +func (b AppModuleBasic) GetQueryCmd() *cobra.Command { + return cli.GetQueryCmd() +} + // RegisterInterfaceTypes implements InterfaceModule func (b AppModuleBasic) RegisterInterfaces(registry cdctypes.InterfaceRegistry) { types.RegisterInterfaces(registry)