Skip to content

Commit

Permalink
Harry/fee middleware (#1174)
Browse files Browse the repository at this point in the history
* Register Counterparty relayer cmd and fee middleware test

* debugging the command

* debugging and finalizing the fee_middleware_test.

* debugging and finalizing the fee_middleware_test.

* merged with updated repo

* clear out some commanded code

* nits and suggestions post review

* more nits

* added one val no fullnode as chainspec

---------

Co-authored-by: Harry <harrycosmos@Harrys-MacBook-Pro.local>
  • Loading branch information
Cosmos-Harry and Harry authored Apr 25, 2023
1 parent 591c136 commit 3a14f8c
Show file tree
Hide file tree
Showing 11 changed files with 712 additions and 20 deletions.
4 changes: 2 additions & 2 deletions cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
"reflect"
"strings"
"time"

"github.com/cosmos/relayer/v2/relayer"
"github.com/cosmos/relayer/v2/relayer/chains/cosmos"
"github.com/cosmos/relayer/v2/relayer/chains/penumbra"
Expand Down Expand Up @@ -668,4 +668,4 @@ func (c *Config) ValidateConnection(ctx context.Context, chain *relayer.Chain, h
}

return nil
}
}
37 changes: 37 additions & 0 deletions cmd/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ Most of these commands take a [path] argument. Make sure:
createChannelCmd(a),
closeChannelCmd(a),
lineBreakCommand(),
registerCounterpartyCmd(a),
)

return cmd
Expand Down Expand Up @@ -1037,3 +1038,39 @@ func ensureKeysExist(chains map[string]*relayer.Chain) error {

return nil
}

// MsgRegisterCounterpartyPayee registers the counterparty_payee
func registerCounterpartyCmd(a *appState) *cobra.Command {
cmd := &cobra.Command{
Use: "register-counterparty chain_name channel_id port_id relay_addr counterparty_payee",
Aliases: []string{"reg-cpt"},
Short: "register the counterparty relayer address for ics-29 fee middleware",
Args: withUsage(cobra.MatchAll(cobra.ExactArgs(5))),
Example: strings.TrimSpace(fmt.Sprintf(`
$ %s register-counterparty channel-1 transfer cosmos1skjwj5whet0lpe65qaq4rpq03hjxlwd9nf39lk juno1g0ny488ws4064mjjxk4keenwfjrthn503ngjxd
$ %s reg-cpt channel-1 cosmos1skjwj5whet0lpe65qaq4rpq03hjxlwd9nf39lk juno1g0ny488ws4064mjjxk4keenwfjrthn503ngjxd`,
appName, appName)),
RunE: func(cmd *cobra.Command, args []string) error {

chain, ok := a.config.Chains[args[0]]
if !ok {
return errChainNotFound(args[0])
}

channelID := args[1]
portID := args[2]

relayerAddr := args[3]
counterpartyPayee := args[4]

msg, err := chain.ChainProvider.MsgRegisterCounterpartyPayee(portID, channelID, relayerAddr, counterpartyPayee)
if err != nil {
return err
}
res, success, err := chain.ChainProvider.SendMessage(cmd.Context(), msg, "")
fmt.Println(res, success, err)
return nil
},
}
return cmd
}
6 changes: 6 additions & 0 deletions go.work
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
go 1.20

use (
./interchaintest
.
)
442 changes: 442 additions & 0 deletions go.work.sum

Large diffs are not rendered by default.

202 changes: 202 additions & 0 deletions interchaintest/fee_middleware_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
package interchaintest_test

import (
"context"
"fmt"
"testing"

transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
relayertest "github.com/cosmos/relayer/v2/interchaintest"
interchaintest "github.com/strangelove-ventures/interchaintest/v7"
"github.com/strangelove-ventures/interchaintest/v7/chain/cosmos"
ibc "github.com/strangelove-ventures/interchaintest/v7/ibc"
"github.com/strangelove-ventures/interchaintest/v7/testreporter"
"github.com/strangelove-ventures/interchaintest/v7/testutil"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zaptest"
)

func TestScenarioFeeMiddleware(t *testing.T) {
if testing.Short() {
t.Skip()
}

t.Parallel()

nv := 1
nf := 0

// Get both chains
cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{
{Name: "juno", ChainName: "chaina", Version: "v13.0.0", NumValidators: &nv, NumFullNodes: &nf, ChainConfig: ibc.ChainConfig{ChainID: "chaina", GasPrices: "0.0ujuno"}},
{Name: "juno", ChainName: "chainb", Version: "v13.0.0", NumValidators: &nv, NumFullNodes: &nf, ChainConfig: ibc.ChainConfig{ChainID: "chainb", GasPrices: "0.0ujuno"}}},
)

chains, err := cf.Chains(t.Name())
require.NoError(t, err)
chainA, chainB := chains[0].(*cosmos.CosmosChain), chains[1].(*cosmos.CosmosChain)

ctx := context.Background()
client, network := interchaintest.DockerSetup(t)

rf := relayertest.NewRelayerFactory(relayertest.RelayerConfig{InitialBlockHistory: 50})
r := rf.Build(t, client, network)

const pathChainAChainB = "chainA-chainB"

// Build the network
ic := interchaintest.NewInterchain().
AddChain(chainA).
AddChain(chainB).
AddRelayer(r, "relayer").
AddLink(interchaintest.InterchainLink{
Chain1: chainA,
Chain2: chainB,
Relayer: r,
Path: pathChainAChainB,
CreateChannelOpts: ibc.CreateChannelOptions{
SourcePortName: "transfer",
DestPortName: "transfer",
Order: ibc.Unordered,
Version: "{\"fee_version\":\"ics29-1\",\"app_version\":\"ics20-1\"}",
},
CreateClientOpts: ibc.DefaultClientOpts(),
})

rep := testreporter.NewNopReporter()
eRep := rep.RelayerExecReporter(t)

require.NoError(t, ic.Build(ctx, eRep, interchaintest.InterchainBuildOptions{
TestName: t.Name(),
Client: client,
NetworkID: network,
SkipPathCreation: false,
}))

t.Cleanup(func() {
_ = ic.Close()
})

err = testutil.WaitForBlocks(ctx, 10, chainA, chainB)
require.NoError(t, err)

// ChainID of ChainA
chainIDA := chainA.Config().ChainID

// Channel of ChainA
chA, err := r.GetChannels(ctx, eRep, chainIDA)
require.NoError(t, err)
channelA := chA[0]

// Fund a user account on chain1 and chain2
const userFunds = int64(1_000_000_000_000)
users := interchaintest.GetAndFundTestUsers(t, ctx, t.Name(), userFunds, chainA, chainB)
userA := users[0]
userAddressA := userA.FormattedAddress()
userB := users[1]
userAddressB := userB.FormattedAddress()

// Addresses of both the chains
walletA, _ := r.GetWallet(chainA.Config().ChainID)
rlyAddressA := walletA.FormattedAddress()

walletB, _ := r.GetWallet(chainB.Config().ChainID)
rlyAddressB := walletB.FormattedAddress()

// register CounterpartyPayee
cmd := []string{
"tx", "register-counterparty",
chainA.Config().Name,
channelA.ChannelID,
"transfer",
rlyAddressA,
rlyAddressB,
}
_ = r.Exec(ctx, eRep, cmd, nil)
require.NoError(t, err)

// Query the relayer CounterpartyPayee on a given channel
query := []string{
chainA.Config().Bin, "query", "ibc-fee", "counterparty-payee", channelA.ChannelID, rlyAddressA,
"--chain-id", chainIDA,
"--node", chainA.GetRPCAddress(),
"--home", chainA.HomeDir(),
"--trace",
}
_, _, err = chainA.Exec(ctx, query, nil)
require.NoError(t, err)

// Get initial account balances
userAOrigBal, err := chainA.GetBalance(ctx, userAddressA, chainA.Config().Denom)
require.NoError(t, err)
require.Equal(t, userFunds, userAOrigBal)

userBOrigBal, err := chainB.GetBalance(ctx, userAddressB, chainB.Config().Denom)
require.NoError(t, err)
require.Equal(t, userFunds, userBOrigBal)

rlyAOrigBal, err := chainA.GetBalance(ctx, rlyAddressA, chainA.Config().Denom)
require.NoError(t, err)
require.Equal(t, userFunds, rlyAOrigBal)

rlyBOrigBal, err := chainB.GetBalance(ctx, rlyAddressB, chainB.Config().Denom)
require.NoError(t, err)
require.Equal(t, userFunds, rlyBOrigBal)

// send tx
const txAmount = 1000
transfer := ibc.WalletAmount{Address: userAddressB, Denom: chainA.Config().Denom, Amount: txAmount}
_, err = chainA.SendIBCTransfer(ctx, channelA.ChannelID, userAddressA, transfer, ibc.TransferOptions{})
require.NoError(t, err)

// Incentivizing async packet by returning MsgPayPacketFeeAsync
packetFeeAsync := []string{
chainA.Config().Bin, "tx", "ibc-fee", "pay-packet-fee", "transfer", channelA.ChannelID, "1",
"--recv-fee", fmt.Sprintf("1000%s", chainA.Config().Denom),
"--ack-fee", fmt.Sprintf("1000%s", chainA.Config().Denom),
"--timeout-fee", fmt.Sprintf("1000%s", chainA.Config().Denom),
"--chain-id", chainIDA,
"--node", chainA.GetRPCAddress(),
"--from", userA.FormattedAddress(),
"--keyring-backend", "test",
"--gas", "400000",
"--yes",
"--home", chainA.HomeDir(),
}
_, _, err = chainA.Exec(ctx, packetFeeAsync, nil)
require.NoError(t, err)

// start the relayer
err = r.StartRelayer(ctx, eRep, pathChainAChainB)
require.NoError(t, err)

t.Cleanup(
func() {
err := r.StopRelayer(ctx, eRep)
if err != nil {
t.Logf("an error occured while stopping the relayer: %s", err)
}
},
)

// Wait for relayer to run
err = testutil.WaitForBlocks(ctx, 5, chainA, chainB)
require.NoError(t, err)

// Assigning denom
chainATokenDenom := transfertypes.GetPrefixedDenom(channelA.PortID, channelA.ChannelID, chainA.Config().Denom)
chainADenomTrace := transfertypes.ParseDenomTrace(chainATokenDenom)

// Get balances after the fees
chainABal, err := chainA.GetBalance(ctx, userAddressA, chainA.Config().Denom)
require.NoError(t, err)
require.Equal(t, userAOrigBal-(txAmount+1000), chainABal)

chainBBal, err := chainB.GetBalance(ctx, userAddressB, chainADenomTrace.IBCDenom())
require.NoError(t, err)
require.Equal(t, int64(txAmount), chainBBal)

rlyABal, err := chainA.GetBalance(ctx, rlyAddressA, chainA.Config().Denom)
require.NoError(t, err)
require.Equal(t, rlyAOrigBal+1000, rlyABal)
}
17 changes: 2 additions & 15 deletions interchaintest/relayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,14 @@ import (
"testing"

"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/relayer/v2/cmd"
"github.com/cosmos/relayer/v2/internal/relayertest"
"github.com/cosmos/relayer/v2/relayer"
"github.com/cosmos/relayer/v2/relayer/chains/cosmos"
"github.com/cosmos/relayer/v2/relayer/provider"
interchaintestcosmos "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos"
"github.com/strangelove-ventures/interchaintest/v7/ibc"
"github.com/stretchr/testify/require"
"github.com/strangelove-ventures/interchaintest/v7/relayer/rly"
"go.uber.org/zap"
"go.uber.org/zap/zaptest"
)
Expand Down Expand Up @@ -338,26 +337,14 @@ func (r *Relayer) GetWallet(chainID string) (ibc.Wallet, bool) {
}
address := strings.TrimSpace(res.Stdout.String())

var chainCfg ibc.ChainConfig
var keyName string
config := r.sys().MustGetConfig(r.t)
for _, v := range config.ProviderConfigs {
if c, ok := v.Value.(cosmos.CosmosProviderConfig); ok {
if c.ChainID == chainID {
keyName = c.Key
chainCfg = ibc.ChainConfig{
Type: v.Type,
Name: c.ChainName,
ChainID: c.ChainID,
Bech32Prefix: c.AccountPrefix,
GasPrices: c.GasPrices,
GasAdjustment: c.GasAdjustment,
}
}
}
}

addressBz, err := types.GetFromBech32(address, chainCfg.Bech32Prefix)
require.NoError(r.t, err, "failed to decode bech32 wallet")
return interchaintestcosmos.NewWallet(keyName, addressBz, "", chainCfg), true
return rly.NewWallet(keyName, address, ""), true
}
5 changes: 3 additions & 2 deletions internal/relayertest/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"go.uber.org/zap/zaptest"
"gopkg.in/yaml.v3"
)

// System is a system under test.
Expand Down Expand Up @@ -129,10 +130,10 @@ func (s *System) MustAddChain(t *testing.T, chainName string, pcw cmd.ProviderCo
func (s *System) MustGetConfig(t *testing.T) (config cmd.ConfigInputWrapper) {
t.Helper()

configBz, err := os.ReadFile(filepath.Join(s.HomeDir, "config.yaml"))
configBz, err := os.ReadFile(filepath.Join(s.HomeDir, "config", "config.yaml"))
require.NoError(t, err, "failed to read config file")

err = json.Unmarshal(configBz, &config)
err = yaml.Unmarshal(configBz, &config)
require.NoError(t, err, "failed to unmarshal config file")

return config
Expand Down
2 changes: 2 additions & 0 deletions relayer/chains/cosmos/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/staking"
"github.com/cosmos/cosmos-sdk/x/upgrade"
upgradeclient "github.com/cosmos/cosmos-sdk/x/upgrade/client"
ibcfee "github.com/cosmos/ibc-go/v7/modules/apps/29-fee"
"github.com/cosmos/ibc-go/v7/modules/apps/transfer"
ibc "github.com/cosmos/ibc-go/v7/modules/core"

Expand Down Expand Up @@ -58,6 +59,7 @@ var ModuleBasics = []module.AppModuleBasic{
ibc.AppModuleBasic{},
cosmosmodule.AppModuleBasic{},
stride.AppModuleBasic{},
ibcfee.AppModuleBasic{},
}

type Codec struct {
Expand Down
7 changes: 7 additions & 0 deletions relayer/chains/cosmos/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/cosmos/cosmos-sdk/store/rootmulti"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
feetypes "github.com/cosmos/ibc-go/v7/modules/apps/29-fee/types"
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
Expand Down Expand Up @@ -1272,6 +1273,12 @@ func (cc *CosmosProvider) UpdateFeesSpent(chain, key string, fees sdk.Coins) {
}
}

// MsgRegisterCounterpartyPayee creates an sdk.Msg to broadcast the counterparty address
func (cc *CosmosProvider) MsgRegisterCounterpartyPayee(portID, channelID, relayerAddr, counterpartyPayee string) (provider.RelayerMessage,error) {
msg := feetypes.NewMsgRegisterCounterpartyPayee(portID, channelID, relayerAddr, counterpartyPayee)
return NewCosmosMessage(msg),nil
}

// PrepareFactory mutates the tx factory with the appropriate account number, sequence number, and min gas settings.
func (cc *CosmosProvider) PrepareFactory(txf tx.Factory) (tx.Factory, error) {
var (
Expand Down
7 changes: 6 additions & 1 deletion relayer/chains/penumbra/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -1352,7 +1352,6 @@ func (cc *PenumbraProvider) MsgConnectionOpenTry(msgOpenInit provider.Connection
return cosmos.NewCosmosMessage(msg), nil
}


func (cc *PenumbraProvider) MsgConnectionOpenAck(msgOpenTry provider.ConnectionInfo, proof provider.ConnectionProof) (provider.RelayerMessage, error) {
signer, err := cc.Address()
if err != nil {
Expand Down Expand Up @@ -2233,3 +2232,9 @@ func (cc *PenumbraProvider) SendMessagesToMempool(ctx context.Context, msgs []pr
cc.log.Debug("Received response from sending messages", zap.Any("response", sendRsp), zap.Error(err))
return err
}

// MsgRegisterCounterpartyPayee creates an sdk.Msg to broadcast the counterparty address
func (cc *PenumbraProvider) MsgRegisterCounterpartyPayee(portID, channelID, relayerAddr, counterpartyPayee string) (provider.RelayerMessage, error) {
//TODO implement me
panic("implement me")
}
Loading

0 comments on commit 3a14f8c

Please sign in to comment.