Skip to content

Commit

Permalink
feat(sudo): CLI fns + tests. Also, switches testutil to use secp256k1 (
Browse files Browse the repository at this point in the history
…#1317)

* golang structs for the contract binding types

* feat(wasm): implement custom queries: Reserves, AllMarkets

* refactor: make request type names more obvious

* Wire in the WasmKeeper to the app with []wasm.Option set for the bindings

* add FundAccount fn to x/common/testutil

* rm fund.go. These functions were defined in the recent x/inflation PR

* refactor: test genesis setup to testutil/genesis so other modules can import th functions

* fix: add json serialization info to cw_query.go

* test(wasmbin): add perp bindings contract and add correctness tests

* test(wasm/binding): successful integration test using the real contract

* update CHANGELOG and include marshal.go

* fix: linter

* (wasm): impl and test base price query

* add utils

* impl and test BasePrice, Metrics, and PremiumFraction queries

* add remaining integration tests for the PR

* test,fix(wasm): all integration tests working on a real contract

* test,fix(wasm): all integration tests working on a real contract

* comment

* refactor(wasm): small rename to query_responses.json

* refactor,docs: PR comments

* test(cw_struct): test compatibility with rust binding types for execute msgs

* feat(wasm): add execute msg bindings for open pos, add & remove margin, close pos

* (wasm.go): wire the execute msg as a wasm.Option

* test(wasm): unit + integration tests for perp transactions

* changelog

* changelog

* test(wasm): check for position in state after it's open

* golangci-lint

* (wasm): new bindings contract

* feat(wasm): peg shift bindings + unit test + integration test

* changelog

* build: new contract with String types for sdk.Dec values that can be negative

* impl Position query with unit test

* test: integration test for Position query

* impl and test multiple position query

* test(wasm): verify correctness of fields in positions query

* checkpoint #wip sudo core business logic

* checkpoint #wip: implement all business logic with full test coverage

* test: add integration tests of the sudo contracts in x/wasm

* changelog

* changelog

* more docs

* refactor(sudo): run msg.ValidateBasic before the main handler

* refactor: small cleanup

* doc comment

* feat(sudo): cli commands + tests for tx and query

* feat(sample.go): secp256k1 usage for #1316

* chore: changelog + linter

* test(sudo): slice order can change when written into state

* test(sudo): fix boolean checks

* chore: linter

* chore: linter

* changelog

* remove ed25519Algo support in sample.go

---------

Co-authored-by: Matthias <[email protected]>
  • Loading branch information
Unique-Divine and matthiasmatt authored May 9, 2023
1 parent 9661bf1 commit 8b0ebbd
Show file tree
Hide file tree
Showing 9 changed files with 482 additions and 10 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Breaking

* [#1317](https://github.com/NibiruChain/nibiru/pull/1317) - feat(sudo): Implement and test CLI commands for tx and queries.
* [#1307](https://github.com/NibiruChain/nibiru/pull/1307) - feat(sudo): Create the x/sudo module + integration tests
* [#1299](https://github.com/NibiruChain/nibiru/pull/1299) - feat(wasm): Add peg shift bindings
* [#1292](https://github.com/NibiruChain/nibiru/pull/1292) - feat(wasm): Add module bindings for execute calls in x/perp: OpenPosition, ClosePosition, AddMargin, RemoveMargin.
Expand Down Expand Up @@ -69,8 +70,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Improvements

* [#1321](https://github.com/NibiruChain/nibiru/pull/1321) - build(deps): bump github.com/prometheus/client_golang from 1.15.0 to 1.15.1
* [#1317](https://github.com/NibiruChain/nibiru/pull/1317) - feat(testutil): Use secp256k1 algo for private key generation in common/testutil.
* [#1322](https://gitub.com/NibiruChain/nibiru/pull/1322) - build(deps): Bumps github.com/armon/go-metrics from 0.4.0 to 0.4.1.
* [#1321](https://github.com/NibiruChain/nibiru/pull/1321) - build(deps): bump github.com/prometheus/client_golang from 1.15.0 to 1.15.1
* [#1295](https://github.com/NibiruChain/nibiru/pull/1295) - refactor(app): Organize keepers, store keys, and module manager initialization in app.go
* [#1248](https://github.com/NibiruChain/nibiru/pull/1248) - refactor(common): Combine x/testutil and x/common/testutil.
* [#1245](https://github.com/NibiruChain/nibiru/pull/1245) - fix(localnet.sh): force localnet.sh to work even if Coingecko is down
Expand Down
15 changes: 15 additions & 0 deletions x/common/testutil/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import (
perpammtypes "github.com/NibiruChain/nibiru/x/perp/amm/types"
perpcli "github.com/NibiruChain/nibiru/x/perp/client/cli"
perptypes "github.com/NibiruChain/nibiru/x/perp/types"
sudocli "github.com/NibiruChain/nibiru/x/sudo/cli"
sudotypes "github.com/NibiruChain/nibiru/x/sudo/pb"
)

// ExecQueryOption defines a type which customizes a CLI query operation.
Expand Down Expand Up @@ -114,3 +116,16 @@ func QueryCumulativePremiumFraction(clientCtx client.Context, pair asset.Pair) (
}
return &queryResp, nil
}

func QuerySudoers(clientCtx client.Context) (*sudotypes.QuerySudoersResponse, error) {
var queryResp sudotypes.QuerySudoersResponse
if err := ExecQuery(
clientCtx,
sudocli.CmdQuerySudoers(),
[]string{},
&queryResp,
); err != nil {
return nil, err
}
return &queryResp, nil
}
2 changes: 2 additions & 0 deletions x/common/testutil/genesis/perp_genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/NibiruChain/nibiru/app"

"github.com/NibiruChain/nibiru/x/common"
"github.com/NibiruChain/nibiru/x/common/asset"
"github.com/NibiruChain/nibiru/x/common/denoms"

oracletypes "github.com/NibiruChain/nibiru/x/oracle/types"
perpammtypes "github.com/NibiruChain/nibiru/x/perp/amm/types"
perptypes "github.com/NibiruChain/nibiru/x/perp/types"
Expand Down
41 changes: 41 additions & 0 deletions x/common/testutil/genesis/sudo_genesis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package genesis

import (
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/NibiruChain/nibiru/app"

"github.com/NibiruChain/nibiru/x/sudo"
sudotypes "github.com/NibiruChain/nibiru/x/sudo/pb"

cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"

"github.com/NibiruChain/nibiru/x/common/testutil"
)

func AddSudoGenesis(gen app.GenesisState) (
genState app.GenesisState,
rootPrivKey cryptotypes.PrivKey,
rootAddr sdk.AccAddress,
) {
sudoGenesis, rootPrivKey, rootAddr := SudoGenesis()
gen[sudotypes.ModuleName] = TEST_ENCODING_CONFIG.Marshaler.
MustMarshalJSON(sudoGenesis)
return gen, rootPrivKey, rootAddr
}

func SudoGenesis() (
genState *sudotypes.GenesisState,
rootPrivKey cryptotypes.PrivKey,
rootAddr sdk.AccAddress,
) {
sudoGenesis := sudo.DefaultGenesis()

// Set the root user
privKeys, addrs := testutil.PrivKeyAddressPairs(1)
rootPrivKey = privKeys[0]
rootAddr = addrs[0]
sudoGenesis.Sudoers.Root = rootAddr.String()

return sudoGenesis, rootPrivKey, rootAddr
}
23 changes: 16 additions & 7 deletions x/common/testutil/sample.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ package testutil
import (
"math/rand"

"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"

cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/store"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand All @@ -13,15 +14,23 @@ import (
tmdb "github.com/tendermint/tm-db"
)

// AccAddress Returns a sample account address (sdk.AccAddress)
// AccAddress returns a sample address (sdk.AccAddress) created using secp256k1.
// Note that AccAddress().String() can be used to get a string representation.
func AccAddress() sdk.AccAddress {
pk := ed25519.GenPrivKey().PubKey()
addr := pk.Address()
return sdk.AccAddress(addr)
_, accAddr := PrivKey()
return accAddr
}

// PrivKey returns a private key and corresponding on-chain address.
func PrivKey() (*secp256k1.PrivKey, sdk.AccAddress) {
privKey := secp256k1.GenPrivKey()
pubKey := privKey.PubKey()
addr := pubKey.Address()
return privKey, sdk.AccAddress(addr)
}

// PrivKeyAddressPairs generates (deterministically) a total of n private keys and addresses.
// PrivKeyAddressPairs generates (deterministically) a total of n private keys
// and addresses.
func PrivKeyAddressPairs(n int) (keys []cryptotypes.PrivKey, addrs []sdk.AccAddress) {
r := rand.New(rand.NewSource(12345)) // make the generation deterministic
keys = make([]cryptotypes.PrivKey, n)
Expand All @@ -32,7 +41,7 @@ func PrivKeyAddressPairs(n int) (keys []cryptotypes.PrivKey, addrs []sdk.AccAddr
if err != nil {
panic("Could not read randomness")
}
keys[i] = ed25519.GenPrivKeyFromSecret(secret)
keys[i] = secp256k1.GenPrivKeyFromSecret(secret)
addrs[i] = sdk.AccAddress(keys[i].PubKey().Address())
}
return
Expand Down
143 changes: 143 additions & 0 deletions x/sudo/cli/cli.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package cli

import (
"fmt"
"os"
"strings"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/cosmos/cosmos-sdk/version"

"github.com/spf13/cobra"

"github.com/NibiruChain/nibiru/x/sudo/pb"
)

// GetTxCmd returns a cli command for this module's transactions
func GetTxCmd() *cobra.Command {
txCmd := &cobra.Command{
Use: pb.ModuleName,
Short: fmt.Sprintf("x/%s transaction subcommands", pb.ModuleName),
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}

// Add subcommands
txCmd.AddCommand(
CmdEditSudoers(),
)

return txCmd
}

// GetQueryCmd returns a cli command for this module's queries
func GetQueryCmd() *cobra.Command {
moduleQueryCmd := &cobra.Command{
Use: pb.ModuleName,
Short: fmt.Sprintf(
"Query commands for the x/%s module", pb.ModuleName),
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}

// Add subcommands
cmds := []*cobra.Command{
CmdQuerySudoers(),
}
for _, cmd := range cmds {
moduleQueryCmd.AddCommand(cmd)
}

return moduleQueryCmd
}

// CmdEditSudoers is a terminal command corresponding to the EditSudoers
// function of the sdk.Msg handler for x/sudo.
func CmdEditSudoers() *cobra.Command {
cmd := &cobra.Command{
Use: "edit [edit-json]",
Args: cobra.ExactArgs(1),
Short: "Edit the x/sudo state (sudoers) by adding or removing contracts",
Example: strings.TrimSpace(fmt.Sprintf(`
Example:
$ %s tx sudo edit <path/to/edit.json> --from=<key_or_address>
`, version.AppName)),
Long: strings.TrimSpace(
`Adds or removes contracts from the x/sudo state, giving the
contracts permissioned access to certain bindings in x/wasm.
The edit.json for 'EditSudoers' is of the form:
{
"action": "add_contracts",
"contracts": "..."
}
- Valid action types: "add_contracts", "remove_contracts"
`),
RunE: func(cmd *cobra.Command, args []string) (err error) {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

msg := new(pb.MsgEditSudoers)

// marshals contents into the proto.Message to which 'msg' points.
contents, err := os.ReadFile(args[0])
if err != nil {
return err
}
if err = clientCtx.Codec.UnmarshalJSON(contents, msg); err != nil {
return err
}

// Parse the message sender
from := clientCtx.GetFromAddress()
msg.Sender = from.String()

if err = msg.ValidateBasic(); err != nil {
return err
}

return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}

flags.AddTxFlagsToCmd(cmd)

return cmd
}

func CmdQuerySudoers() *cobra.Command {
cmd := &cobra.Command{
Use: "state",
Short: "displays the internal state (sudoers) of the x/sudo module",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}

queryClient := pb.NewQueryClient(clientCtx)

req := new(pb.QuerySudoersRequest)
resp, err := queryClient.QuerySudoers(
cmd.Context(), req,
)
if err != nil {
return err
}

return clientCtx.PrintProto(resp)
},
}

flags.AddQueryFlagsToCmd(cmd)

return cmd
}
Loading

0 comments on commit 8b0ebbd

Please sign in to comment.