Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: native core SDK command support #892

Merged
merged 47 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
1526481
add authz native support
Reecepbcups Dec 1, 2023
421b08c
`x/bank` support
Reecepbcups Dec 1, 2023
5342317
cleanup bank queries
Reecepbcups Dec 1, 2023
069779d
fix authz to SDK v50
Reecepbcups Dec 1, 2023
c57a3c5
fix e2e
Reecepbcups Dec 1, 2023
46c1c39
WIP of todos
Reecepbcups Dec 2, 2023
f20e1e8
full bank suite testing
Reecepbcups Dec 3, 2023
c1d1d0d
fix test
Reecepbcups Dec 4, 2023
32e08ba
build TokenFactory off ChainNode
Reecepbcups Dec 4, 2023
e6ea937
crisis, distr, slashing, and staking txs+queries
Reecepbcups Dec 4, 2023
2fb0a4f
updated todo
Reecepbcups Dec 5, 2023
720d1cd
move gRPC conn on node startup
Reecepbcups Dec 6, 2023
d36acc8
rename all to modules_
Reecepbcups Dec 6, 2023
7d0bfe9
add circuit & feegrant txs + queries
Reecepbcups Dec 6, 2023
809d695
x/upgrade
Reecepbcups Dec 6, 2023
c2a4a6c
WIP: x/gov
Reecepbcups Dec 6, 2023
4317009
distribution test
Reecepbcups Dec 9, 2023
59bf214
fix distribution
Reecepbcups Dec 9, 2023
d5bee5e
Merge branch 'main' into reece/complete-core
Reecepbcups Dec 9, 2023
f1c330e
backup
Reecepbcups Dec 9, 2023
264939e
comment out bad feegrant for now
Reecepbcups Dec 10, 2023
fe405d2
govv1 & govv1beta1 query types
Reecepbcups Dec 10, 2023
03e390c
add SDK v50 gov test
Reecepbcups Dec 10, 2023
c6cdd0c
wip: circuit
Reecepbcups Dec 11, 2023
8648f3c
move cosmwasm to its own module section
Reecepbcups Dec 30, 2023
059a87e
Add `x/auth` queries
Reecepbcups Dec 30, 2023
b21efd0
add `vesting` txs + test
Reecepbcups Dec 30, 2023
4341133
Merge branch 'main' into reece/complete-core
Reecepbcups Dec 30, 2023
609856d
cleanup / move functions to better suited files
Reecepbcups Dec 30, 2023
8d920bd
use `c.GetNode()` as Cosmos getFullNode
Reecepbcups Dec 30, 2023
60c69d0
fully test `auth`
Reecepbcups Dec 30, 2023
2dd180b
Use <Module>Query<Path> format (i.e. `AuthQueryAccount`)
Reecepbcups Dec 30, 2023
8c603c0
remove todo log
Reecepbcups Dec 30, 2023
8c6cb9a
rm circuit module
Reecepbcups Dec 30, 2023
79d8959
testStaking
Reecepbcups Dec 30, 2023
7e076dc
test slashing
Reecepbcups Dec 30, 2023
2b43cb4
deprecate `TokenFactoryGetAdmin`
Reecepbcups Dec 30, 2023
e127b6f
cleanup `testFeeGrant`
Reecepbcups Dec 30, 2023
eecbc6d
final self review touchups
Reecepbcups Dec 30, 2023
7cef1a9
cleanup `AuthPrintAccountInfo`
Reecepbcups Jan 9, 2024
7953959
use path.Join
Reecepbcups Jan 9, 2024
c9a62ef
`PrefixMsgTypeIfRequired`
Reecepbcups Jan 9, 2024
7c9f8fd
Merge branch 'main' into reece/complete-core
Reecepbcups Jan 9, 2024
2544c5f
Merge branch 'main' into reece/complete-core
Reecepbcups Jan 9, 2024
3af2926
del[0]
Reecepbcups Jan 9, 2024
99c1ff2
query users delegations, iter all for `found`
Reecepbcups Jan 9, 2024
42d7856
supplyOf.IsGTE supply
Reecepbcups Jan 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
383 changes: 35 additions & 348 deletions chain/cosmos/chain_node.go

Large diffs are not rendered by default.

123 changes: 15 additions & 108 deletions chain/cosmos/cosmos_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"context"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"math"
Expand All @@ -22,10 +21,8 @@ import (
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
bankTypes "github.com/cosmos/cosmos-sdk/x/bank/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
paramsutils "github.com/cosmos/cosmos-sdk/x/params/client/utils"
cosmosproto "github.com/cosmos/gogoproto/proto"
chanTypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types"
dockertypes "github.com/docker/docker/api/types"
volumetypes "github.com/docker/docker/api/types/volume"
Expand All @@ -38,8 +35,6 @@ import (
"github.com/strangelove-ventures/interchaintest/v8/testutil"
"go.uber.org/zap"
"golang.org/x/sync/errgroup"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)

// CosmosChain is a local docker testnet for a Cosmos SDK chain.
Expand All @@ -55,6 +50,7 @@ type CosmosChain struct {
// Additional processes that need to be run on a per-chain basis.
Sidecars SidecarProcesses

cdc *codec.ProtoCodec
log *zap.Logger
keyring keyring.Keyring
findTxMu sync.Mutex
Expand Down Expand Up @@ -104,10 +100,16 @@ func NewCosmosChain(testName string, chainConfig ibc.ChainConfig, numValidators
numValidators: numValidators,
numFullNodes: numFullNodes,
log: log,
cdc: cdc,
keyring: kr,
}
}

// GetCodec returns the codec for the chain.
func (c *CosmosChain) GetCodec() *codec.ProtoCodec {
return c.cdc
}
Comment on lines +108 to +111
Copy link
Member Author

@Reecepbcups Reecepbcups Dec 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Required for module_auth.go (converting the any types -> accounts)


// Nodes returns all nodes, including validators and fullnodes.
func (c *CosmosChain) Nodes() ChainNodes {
return append(c.Validators, c.FullNodes...)
Expand Down Expand Up @@ -184,14 +186,7 @@ func (c *CosmosChain) Initialize(ctx context.Context, testName string, cli *clie
}

func (c *CosmosChain) getFullNode() *ChainNode {
c.findTxMu.Lock()
defer c.findTxMu.Unlock()
if len(c.FullNodes) > 0 {
// use first full node
return c.FullNodes[0]
}
// use first validator
return c.Validators[0]
return c.GetNode()
}
Comment on lines 188 to 190
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When a test adds or removes a full node, this then switches which node the user was original acting on. This results in a NPE and causes a lot of confusion (including for myself). This uses GetNode() (validator[0]) now so commands always happen on the same machine as a user expects

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great catch!!


func (c *CosmosChain) GetNode() *ChainNode {
Expand Down Expand Up @@ -319,7 +314,7 @@ func (c *CosmosChain) BuildRelayerWallet(ctx context.Context, keyName string) (i

// Implements Chain interface
func (c *CosmosChain) SendFunds(ctx context.Context, keyName string, amount ibc.WalletAmount) error {
return c.getFullNode().SendFunds(ctx, keyName, amount)
return c.getFullNode().BankSend(ctx, keyName, amount)
}

// Implements Chain interface
Expand Down Expand Up @@ -381,26 +376,6 @@ func (c *CosmosChain) SendIBCTransfer(
return tx, nil
}

// GetGovernanceAddress performs a query to get the address of the chain's x/gov module
func (c *CosmosChain) GetGovernanceAddress(ctx context.Context) (string, error) {
return c.GetModuleAddress(ctx, govtypes.ModuleName)
}

// GetModuleAddress performs a query to get the address of the specified chain module
func (c *CosmosChain) GetModuleAddress(ctx context.Context, moduleName string) (string, error) {
return c.getFullNode().GetModuleAddress(ctx, moduleName)
}

// QueryProposal returns the state and details of a governance proposal.
func (c *CosmosChain) QueryProposal(ctx context.Context, proposalID string) (*ProposalResponse, error) {
return c.getFullNode().QueryProposal(ctx, proposalID)
}

// QueryProposal returns the state and details of an IBC-Go v8 / SDK v50 governance proposal.
func (c *CosmosChain) QueryProposalV8(ctx context.Context, proposalID string) (*ProposalResponseV8, error) {
return c.getFullNode().QueryProposalV8(ctx, proposalID)
}

// PushNewWasmClientProposal submits a new wasm client governance proposal to the chain
func (c *CosmosChain) PushNewWasmClientProposal(ctx context.Context, keyName string, fileName string, prop TxProposalv1) (TxProposal, string, error) {
tx := TxProposal{}
Expand Down Expand Up @@ -449,38 +424,6 @@ func (c *CosmosChain) SubmitProposal(ctx context.Context, keyName string, prop T
return c.txProposal(txHash)
}

// Build a gov v1 proposal type.
//
// The proposer field should only be set for IBC-Go v8 / SDK v50 chains.
func (c *CosmosChain) BuildProposal(messages []cosmosproto.Message, title, summary, metadata, depositStr, proposer string, expedited bool) (TxProposalv1, error) {
var propType TxProposalv1
rawMsgs := make([]json.RawMessage, len(messages))

for i, msg := range messages {
msg, err := c.Config().EncodingConfig.Codec.MarshalInterfaceJSON(msg)
if err != nil {
return propType, err
}
rawMsgs[i] = msg
}

propType = TxProposalv1{
Messages: rawMsgs,
Metadata: metadata,
Deposit: depositStr,
Title: title,
Summary: summary,
}

// SDK v50 only
if proposer != "" {
propType.Proposer = proposer
propType.Expedited = expedited
}

return propType, nil
}

// TextProposal submits a text governance proposal to the chain.
func (c *CosmosChain) TextProposal(ctx context.Context, keyName string, prop TextProposal) (tx TxProposal, _ error) {
txHash, err := c.getFullNode().TextProposal(ctx, keyName, prop)
Expand Down Expand Up @@ -571,47 +514,6 @@ func (c *CosmosChain) ExportState(ctx context.Context, height int64) (string, er
return c.getFullNode().ExportState(ctx, height)
}

// GetBalance fetches the current balance for a specific account address and denom.
// Implements Chain interface
func (c *CosmosChain) GetBalance(ctx context.Context, address string, denom string) (sdkmath.Int, error) {
params := &bankTypes.QueryBalanceRequest{Address: address, Denom: denom}
grpcAddress := c.getFullNode().hostGRPCPort
conn, err := grpc.Dial(grpcAddress, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
return sdkmath.Int{}, err
}
defer conn.Close()

queryClient := bankTypes.NewQueryClient(conn)
res, err := queryClient.Balance(ctx, params)

if err != nil {
return sdkmath.Int{}, err
}

return res.Balance.Amount, nil
}

// AllBalances fetches an account address's balance for all denoms it holds
func (c *CosmosChain) AllBalances(ctx context.Context, address string) (types.Coins, error) {
params := bankTypes.QueryAllBalancesRequest{Address: address}
grpcAddress := c.getFullNode().hostGRPCPort
conn, err := grpc.Dial(grpcAddress, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
return nil, err
}
defer conn.Close()

queryClient := bankTypes.NewQueryClient(conn)
res, err := queryClient.AllBalances(ctx, &params)

if err != nil {
return nil, err
}

return res.GetBalances(), nil
}

func (c *CosmosChain) GetTransaction(txhash string) (*types.TxResponse, error) {
fn := c.getFullNode()
return fn.GetTransaction(fn.CliContext(), txhash)
Expand Down Expand Up @@ -1264,12 +1166,17 @@ func (c *CosmosChain) StartAllValSidecars(ctx context.Context) error {
}

func (c *CosmosChain) VoteOnProposalAllValidators(ctx context.Context, proposalID string, vote string) error {
propID, err := strconv.ParseUint(proposalID, 10, 64)
if err != nil {
return fmt.Errorf("failed to parse proposalID %s: %w", proposalID, err)
}

var eg errgroup.Group
for _, n := range c.Nodes() {
if n.Validator {
n := n
eg.Go(func() error {
return n.VoteOnProposal(ctx, valKey, proposalID, vote)
return n.VoteOnProposal(ctx, valKey, propID, vote)
})
}
}
Expand Down
167 changes: 167 additions & 0 deletions chain/cosmos/module_auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
package cosmos

import (
"context"
"fmt"

authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"

cdctypes "github.com/cosmos/cosmos-sdk/codec/types"
)

// AuthQueryAccount performs a query to get the account details of the specified address
func (c *CosmosChain) AuthQueryAccount(ctx context.Context, addr string) (*cdctypes.Any, error) {
res, err := authtypes.NewQueryClient(c.GetNode().GrpcConn).Account(ctx, &authtypes.QueryAccountRequest{
Address: addr,
})
return res.Account, err
}

// AuthQueryParams performs a query to get the auth module parameters
func (c *CosmosChain) AuthQueryParams(ctx context.Context) (*authtypes.Params, error) {
res, err := authtypes.NewQueryClient(c.GetNode().GrpcConn).Params(ctx, &authtypes.QueryParamsRequest{})
return &res.Params, err
}

// AuthQueryModuleAccounts performs a query to get the account details of all the chain modules
func (c *CosmosChain) AuthQueryModuleAccounts(ctx context.Context) ([]authtypes.ModuleAccount, error) {
res, err := authtypes.NewQueryClient(c.GetNode().GrpcConn).ModuleAccounts(ctx, &authtypes.QueryModuleAccountsRequest{})

maccs := make([]authtypes.ModuleAccount, len(res.Accounts))

for i, acc := range res.Accounts {
var macc authtypes.ModuleAccount
err := c.GetCodec().Unmarshal(acc.Value, &macc)
if err != nil {
return nil, err
}
maccs[i] = macc
}

return maccs, err
}

// AuthGetModuleAccount performs a query to get the account details of the specified chain module
func (c *CosmosChain) AuthQueryModuleAccount(ctx context.Context, moduleName string) (authtypes.ModuleAccount, error) {
res, err := authtypes.NewQueryClient(c.GetNode().GrpcConn).ModuleAccountByName(ctx, &authtypes.QueryModuleAccountByNameRequest{
Name: moduleName,
})
if err != nil {
return authtypes.ModuleAccount{}, err
}

var modAcc authtypes.ModuleAccount
err = c.GetCodec().Unmarshal(res.Account.Value, &modAcc)

return modAcc, err
}

// GetModuleAddress performs a query to get the address of the specified chain module
func (c *CosmosChain) AuthQueryModuleAddress(ctx context.Context, moduleName string) (string, error) {
queryRes, err := c.AuthQueryModuleAccount(ctx, moduleName)
if err != nil {
return "", err
}
return queryRes.BaseAccount.Address, nil
}

// Deprecated: use AuthQueryModuleAddress instead
func (c *CosmosChain) GetModuleAddress(ctx context.Context, moduleName string) (string, error) {
return c.AuthQueryModuleAddress(ctx, moduleName)
}

// GetGovernanceAddress performs a query to get the address of the chain's x/gov module
// Deprecated: use AuthQueryModuleAddress(ctx, "gov") instead
func (c *CosmosChain) GetGovernanceAddress(ctx context.Context) (string, error) {
return c.GetModuleAddress(ctx, "gov")
}

func (c *CosmosChain) AuthQueryBech32Prefix(ctx context.Context) (string, error) {
res, err := authtypes.NewQueryClient(c.GetNode().GrpcConn).Bech32Prefix(ctx, &authtypes.Bech32PrefixRequest{})
return res.Bech32Prefix, err
}

// AddressBytesToString converts a byte array address to a string
func (c *CosmosChain) AuthAddressBytesToString(ctx context.Context, addrBz []byte) (string, error) {
res, err := authtypes.NewQueryClient(c.GetNode().GrpcConn).AddressBytesToString(ctx, &authtypes.AddressBytesToStringRequest{
AddressBytes: addrBz,
})
return res.AddressString, err
}

// AddressStringToBytes converts a string address to a byte array
func (c *CosmosChain) AuthAddressStringToBytes(ctx context.Context, addr string) ([]byte, error) {
res, err := authtypes.NewQueryClient(c.GetNode().GrpcConn).AddressStringToBytes(ctx, &authtypes.AddressStringToBytesRequest{
AddressString: addr,
})
return res.AddressBytes, err
}

// AccountInfo queries the account information of the given address
func (c *CosmosChain) AuthQueryAccountInfo(ctx context.Context, addr string) (*authtypes.BaseAccount, error) {
res, err := authtypes.NewQueryClient(c.GetNode().GrpcConn).AccountInfo(ctx, &authtypes.QueryAccountInfoRequest{
Address: addr,
})
return res.Info, err
}

func (c *CosmosChain) AuthPrintAccountInfo(chain *CosmosChain, res *cdctypes.Any) error {
switch res.TypeUrl {
case "/cosmos.auth.v1beta1.ModuleAccount":
var modAcc authtypes.ModuleAccount
if err := chain.GetCodec().Unmarshal(res.Value, &modAcc); err != nil {
return err
}
fmt.Printf("ModuleAccount: %+v\n", modAcc)
return nil

case "/cosmos.vesting.v1beta1.VestingAccount":
var vestingAcc vestingtypes.BaseVestingAccount
if err := chain.GetCodec().Unmarshal(res.Value, &vestingAcc); err != nil {
return err
}
fmt.Printf("BaseVestingAccount: %+v\n", vestingAcc)
return nil

case "/cosmos.vesting.v1beta1.PeriodicVestingAccount":
var vestingAcc vestingtypes.PeriodicVestingAccount
if err := chain.GetCodec().Unmarshal(res.Value, &vestingAcc); err != nil {
return err
}
fmt.Printf("PeriodicVestingAccount: %+v\n", vestingAcc)
return nil

case "/cosmos.vesting.v1beta1.ContinuousVestingAccount":
var vestingAcc vestingtypes.ContinuousVestingAccount
if err := chain.GetCodec().Unmarshal(res.Value, &vestingAcc); err != nil {
return err
}
fmt.Printf("ContinuousVestingAccount: %+v\n", vestingAcc)
return nil

case "/cosmos.vesting.v1beta1.DelayedVestingAccount":
var vestingAcc vestingtypes.DelayedVestingAccount
if err := chain.GetCodec().Unmarshal(res.Value, &vestingAcc); err != nil {
return err
}
fmt.Printf("DelayedVestingAccount: %+v\n", vestingAcc)
return nil

case "/cosmos.vesting.v1beta1.PermanentLockedAccount":
var vestingAcc vestingtypes.PermanentLockedAccount
if err := chain.GetCodec().Unmarshal(res.Value, &vestingAcc); err != nil {
return err
}
fmt.Printf("PermanentLockedAccount: %+v\n", vestingAcc)
return nil

default:
var baseAcc authtypes.BaseAccount
if err := chain.GetCodec().Unmarshal(res.Value, &baseAcc); err != nil {
return err
}
fmt.Printf("BaseAccount: %+v\n", baseAcc)
return nil
}
}
Loading
Loading