Skip to content

Commit 3a14f8c

Browse files
Cosmos-HarryHarry
and
Harry
authoredApr 25, 2023
Harry/fee middleware (#1174)
* 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>
1 parent 591c136 commit 3a14f8c

File tree

11 files changed

+712
-20
lines changed

11 files changed

+712
-20
lines changed
 

‎cmd/config.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import (
2828
"reflect"
2929
"strings"
3030
"time"
31-
31+
3232
"github.com/cosmos/relayer/v2/relayer"
3333
"github.com/cosmos/relayer/v2/relayer/chains/cosmos"
3434
"github.com/cosmos/relayer/v2/relayer/chains/penumbra"
@@ -668,4 +668,4 @@ func (c *Config) ValidateConnection(ctx context.Context, chain *relayer.Chain, h
668668
}
669669

670670
return nil
671-
}
671+
}

‎cmd/tx.go

+37
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ Most of these commands take a [path] argument. Make sure:
4949
createChannelCmd(a),
5050
closeChannelCmd(a),
5151
lineBreakCommand(),
52+
registerCounterpartyCmd(a),
5253
)
5354

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

10381039
return nil
10391040
}
1041+
1042+
// MsgRegisterCounterpartyPayee registers the counterparty_payee
1043+
func registerCounterpartyCmd(a *appState) *cobra.Command {
1044+
cmd := &cobra.Command{
1045+
Use: "register-counterparty chain_name channel_id port_id relay_addr counterparty_payee",
1046+
Aliases: []string{"reg-cpt"},
1047+
Short: "register the counterparty relayer address for ics-29 fee middleware",
1048+
Args: withUsage(cobra.MatchAll(cobra.ExactArgs(5))),
1049+
Example: strings.TrimSpace(fmt.Sprintf(`
1050+
$ %s register-counterparty channel-1 transfer cosmos1skjwj5whet0lpe65qaq4rpq03hjxlwd9nf39lk juno1g0ny488ws4064mjjxk4keenwfjrthn503ngjxd
1051+
$ %s reg-cpt channel-1 cosmos1skjwj5whet0lpe65qaq4rpq03hjxlwd9nf39lk juno1g0ny488ws4064mjjxk4keenwfjrthn503ngjxd`,
1052+
appName, appName)),
1053+
RunE: func(cmd *cobra.Command, args []string) error {
1054+
1055+
chain, ok := a.config.Chains[args[0]]
1056+
if !ok {
1057+
return errChainNotFound(args[0])
1058+
}
1059+
1060+
channelID := args[1]
1061+
portID := args[2]
1062+
1063+
relayerAddr := args[3]
1064+
counterpartyPayee := args[4]
1065+
1066+
msg, err := chain.ChainProvider.MsgRegisterCounterpartyPayee(portID, channelID, relayerAddr, counterpartyPayee)
1067+
if err != nil {
1068+
return err
1069+
}
1070+
res, success, err := chain.ChainProvider.SendMessage(cmd.Context(), msg, "")
1071+
fmt.Println(res, success, err)
1072+
return nil
1073+
},
1074+
}
1075+
return cmd
1076+
}

‎go.work

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
go 1.20
2+
3+
use (
4+
./interchaintest
5+
.
6+
)

‎go.work.sum

+442
Large diffs are not rendered by default.

‎interchaintest/fee_middleware_test.go

+202
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
package interchaintest_test
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"testing"
7+
8+
transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
9+
relayertest "github.com/cosmos/relayer/v2/interchaintest"
10+
interchaintest "github.com/strangelove-ventures/interchaintest/v7"
11+
"github.com/strangelove-ventures/interchaintest/v7/chain/cosmos"
12+
ibc "github.com/strangelove-ventures/interchaintest/v7/ibc"
13+
"github.com/strangelove-ventures/interchaintest/v7/testreporter"
14+
"github.com/strangelove-ventures/interchaintest/v7/testutil"
15+
"github.com/stretchr/testify/require"
16+
"go.uber.org/zap/zaptest"
17+
)
18+
19+
func TestScenarioFeeMiddleware(t *testing.T) {
20+
if testing.Short() {
21+
t.Skip()
22+
}
23+
24+
t.Parallel()
25+
26+
nv := 1
27+
nf := 0
28+
29+
// Get both chains
30+
cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{
31+
{Name: "juno", ChainName: "chaina", Version: "v13.0.0", NumValidators: &nv, NumFullNodes: &nf, ChainConfig: ibc.ChainConfig{ChainID: "chaina", GasPrices: "0.0ujuno"}},
32+
{Name: "juno", ChainName: "chainb", Version: "v13.0.0", NumValidators: &nv, NumFullNodes: &nf, ChainConfig: ibc.ChainConfig{ChainID: "chainb", GasPrices: "0.0ujuno"}}},
33+
)
34+
35+
chains, err := cf.Chains(t.Name())
36+
require.NoError(t, err)
37+
chainA, chainB := chains[0].(*cosmos.CosmosChain), chains[1].(*cosmos.CosmosChain)
38+
39+
ctx := context.Background()
40+
client, network := interchaintest.DockerSetup(t)
41+
42+
rf := relayertest.NewRelayerFactory(relayertest.RelayerConfig{InitialBlockHistory: 50})
43+
r := rf.Build(t, client, network)
44+
45+
const pathChainAChainB = "chainA-chainB"
46+
47+
// Build the network
48+
ic := interchaintest.NewInterchain().
49+
AddChain(chainA).
50+
AddChain(chainB).
51+
AddRelayer(r, "relayer").
52+
AddLink(interchaintest.InterchainLink{
53+
Chain1: chainA,
54+
Chain2: chainB,
55+
Relayer: r,
56+
Path: pathChainAChainB,
57+
CreateChannelOpts: ibc.CreateChannelOptions{
58+
SourcePortName: "transfer",
59+
DestPortName: "transfer",
60+
Order: ibc.Unordered,
61+
Version: "{\"fee_version\":\"ics29-1\",\"app_version\":\"ics20-1\"}",
62+
},
63+
CreateClientOpts: ibc.DefaultClientOpts(),
64+
})
65+
66+
rep := testreporter.NewNopReporter()
67+
eRep := rep.RelayerExecReporter(t)
68+
69+
require.NoError(t, ic.Build(ctx, eRep, interchaintest.InterchainBuildOptions{
70+
TestName: t.Name(),
71+
Client: client,
72+
NetworkID: network,
73+
SkipPathCreation: false,
74+
}))
75+
76+
t.Cleanup(func() {
77+
_ = ic.Close()
78+
})
79+
80+
err = testutil.WaitForBlocks(ctx, 10, chainA, chainB)
81+
require.NoError(t, err)
82+
83+
// ChainID of ChainA
84+
chainIDA := chainA.Config().ChainID
85+
86+
// Channel of ChainA
87+
chA, err := r.GetChannels(ctx, eRep, chainIDA)
88+
require.NoError(t, err)
89+
channelA := chA[0]
90+
91+
// Fund a user account on chain1 and chain2
92+
const userFunds = int64(1_000_000_000_000)
93+
users := interchaintest.GetAndFundTestUsers(t, ctx, t.Name(), userFunds, chainA, chainB)
94+
userA := users[0]
95+
userAddressA := userA.FormattedAddress()
96+
userB := users[1]
97+
userAddressB := userB.FormattedAddress()
98+
99+
// Addresses of both the chains
100+
walletA, _ := r.GetWallet(chainA.Config().ChainID)
101+
rlyAddressA := walletA.FormattedAddress()
102+
103+
walletB, _ := r.GetWallet(chainB.Config().ChainID)
104+
rlyAddressB := walletB.FormattedAddress()
105+
106+
// register CounterpartyPayee
107+
cmd := []string{
108+
"tx", "register-counterparty",
109+
chainA.Config().Name,
110+
channelA.ChannelID,
111+
"transfer",
112+
rlyAddressA,
113+
rlyAddressB,
114+
}
115+
_ = r.Exec(ctx, eRep, cmd, nil)
116+
require.NoError(t, err)
117+
118+
// Query the relayer CounterpartyPayee on a given channel
119+
query := []string{
120+
chainA.Config().Bin, "query", "ibc-fee", "counterparty-payee", channelA.ChannelID, rlyAddressA,
121+
"--chain-id", chainIDA,
122+
"--node", chainA.GetRPCAddress(),
123+
"--home", chainA.HomeDir(),
124+
"--trace",
125+
}
126+
_, _, err = chainA.Exec(ctx, query, nil)
127+
require.NoError(t, err)
128+
129+
// Get initial account balances
130+
userAOrigBal, err := chainA.GetBalance(ctx, userAddressA, chainA.Config().Denom)
131+
require.NoError(t, err)
132+
require.Equal(t, userFunds, userAOrigBal)
133+
134+
userBOrigBal, err := chainB.GetBalance(ctx, userAddressB, chainB.Config().Denom)
135+
require.NoError(t, err)
136+
require.Equal(t, userFunds, userBOrigBal)
137+
138+
rlyAOrigBal, err := chainA.GetBalance(ctx, rlyAddressA, chainA.Config().Denom)
139+
require.NoError(t, err)
140+
require.Equal(t, userFunds, rlyAOrigBal)
141+
142+
rlyBOrigBal, err := chainB.GetBalance(ctx, rlyAddressB, chainB.Config().Denom)
143+
require.NoError(t, err)
144+
require.Equal(t, userFunds, rlyBOrigBal)
145+
146+
// send tx
147+
const txAmount = 1000
148+
transfer := ibc.WalletAmount{Address: userAddressB, Denom: chainA.Config().Denom, Amount: txAmount}
149+
_, err = chainA.SendIBCTransfer(ctx, channelA.ChannelID, userAddressA, transfer, ibc.TransferOptions{})
150+
require.NoError(t, err)
151+
152+
// Incentivizing async packet by returning MsgPayPacketFeeAsync
153+
packetFeeAsync := []string{
154+
chainA.Config().Bin, "tx", "ibc-fee", "pay-packet-fee", "transfer", channelA.ChannelID, "1",
155+
"--recv-fee", fmt.Sprintf("1000%s", chainA.Config().Denom),
156+
"--ack-fee", fmt.Sprintf("1000%s", chainA.Config().Denom),
157+
"--timeout-fee", fmt.Sprintf("1000%s", chainA.Config().Denom),
158+
"--chain-id", chainIDA,
159+
"--node", chainA.GetRPCAddress(),
160+
"--from", userA.FormattedAddress(),
161+
"--keyring-backend", "test",
162+
"--gas", "400000",
163+
"--yes",
164+
"--home", chainA.HomeDir(),
165+
}
166+
_, _, err = chainA.Exec(ctx, packetFeeAsync, nil)
167+
require.NoError(t, err)
168+
169+
// start the relayer
170+
err = r.StartRelayer(ctx, eRep, pathChainAChainB)
171+
require.NoError(t, err)
172+
173+
t.Cleanup(
174+
func() {
175+
err := r.StopRelayer(ctx, eRep)
176+
if err != nil {
177+
t.Logf("an error occured while stopping the relayer: %s", err)
178+
}
179+
},
180+
)
181+
182+
// Wait for relayer to run
183+
err = testutil.WaitForBlocks(ctx, 5, chainA, chainB)
184+
require.NoError(t, err)
185+
186+
// Assigning denom
187+
chainATokenDenom := transfertypes.GetPrefixedDenom(channelA.PortID, channelA.ChannelID, chainA.Config().Denom)
188+
chainADenomTrace := transfertypes.ParseDenomTrace(chainATokenDenom)
189+
190+
// Get balances after the fees
191+
chainABal, err := chainA.GetBalance(ctx, userAddressA, chainA.Config().Denom)
192+
require.NoError(t, err)
193+
require.Equal(t, userAOrigBal-(txAmount+1000), chainABal)
194+
195+
chainBBal, err := chainB.GetBalance(ctx, userAddressB, chainADenomTrace.IBCDenom())
196+
require.NoError(t, err)
197+
require.Equal(t, int64(txAmount), chainBBal)
198+
199+
rlyABal, err := chainA.GetBalance(ctx, rlyAddressA, chainA.Config().Denom)
200+
require.NoError(t, err)
201+
require.Equal(t, rlyAOrigBal+1000, rlyABal)
202+
}

‎interchaintest/relayer.go

+2-15
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,14 @@ import (
99
"testing"
1010

1111
"github.com/cosmos/cosmos-sdk/crypto/keyring"
12-
"github.com/cosmos/cosmos-sdk/types"
1312
"github.com/cosmos/relayer/v2/cmd"
1413
"github.com/cosmos/relayer/v2/internal/relayertest"
1514
"github.com/cosmos/relayer/v2/relayer"
1615
"github.com/cosmos/relayer/v2/relayer/chains/cosmos"
1716
"github.com/cosmos/relayer/v2/relayer/provider"
1817
interchaintestcosmos "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos"
1918
"github.com/strangelove-ventures/interchaintest/v7/ibc"
20-
"github.com/stretchr/testify/require"
19+
"github.com/strangelove-ventures/interchaintest/v7/relayer/rly"
2120
"go.uber.org/zap"
2221
"go.uber.org/zap/zaptest"
2322
)
@@ -338,26 +337,14 @@ func (r *Relayer) GetWallet(chainID string) (ibc.Wallet, bool) {
338337
}
339338
address := strings.TrimSpace(res.Stdout.String())
340339

341-
var chainCfg ibc.ChainConfig
342340
var keyName string
343341
config := r.sys().MustGetConfig(r.t)
344342
for _, v := range config.ProviderConfigs {
345343
if c, ok := v.Value.(cosmos.CosmosProviderConfig); ok {
346344
if c.ChainID == chainID {
347345
keyName = c.Key
348-
chainCfg = ibc.ChainConfig{
349-
Type: v.Type,
350-
Name: c.ChainName,
351-
ChainID: c.ChainID,
352-
Bech32Prefix: c.AccountPrefix,
353-
GasPrices: c.GasPrices,
354-
GasAdjustment: c.GasAdjustment,
355-
}
356346
}
357347
}
358348
}
359-
360-
addressBz, err := types.GetFromBech32(address, chainCfg.Bech32Prefix)
361-
require.NoError(r.t, err, "failed to decode bech32 wallet")
362-
return interchaintestcosmos.NewWallet(keyName, addressBz, "", chainCfg), true
349+
return rly.NewWallet(keyName, address, ""), true
363350
}

‎internal/relayertest/system.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/stretchr/testify/require"
1616
"go.uber.org/zap"
1717
"go.uber.org/zap/zaptest"
18+
"gopkg.in/yaml.v3"
1819
)
1920

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

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

135-
err = json.Unmarshal(configBz, &config)
136+
err = yaml.Unmarshal(configBz, &config)
136137
require.NoError(t, err, "failed to unmarshal config file")
137138

138139
return config

‎relayer/chains/cosmos/codec.go

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/cosmos/cosmos-sdk/x/staking"
2424
"github.com/cosmos/cosmos-sdk/x/upgrade"
2525
upgradeclient "github.com/cosmos/cosmos-sdk/x/upgrade/client"
26+
ibcfee "github.com/cosmos/ibc-go/v7/modules/apps/29-fee"
2627
"github.com/cosmos/ibc-go/v7/modules/apps/transfer"
2728
ibc "github.com/cosmos/ibc-go/v7/modules/core"
2829

@@ -58,6 +59,7 @@ var ModuleBasics = []module.AppModuleBasic{
5859
ibc.AppModuleBasic{},
5960
cosmosmodule.AppModuleBasic{},
6061
stride.AppModuleBasic{},
62+
ibcfee.AppModuleBasic{},
6163
}
6264

6365
type Codec struct {

‎relayer/chains/cosmos/tx.go

+7
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/cosmos/cosmos-sdk/store/rootmulti"
2626
sdk "github.com/cosmos/cosmos-sdk/types"
2727
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
28+
feetypes "github.com/cosmos/ibc-go/v7/modules/apps/29-fee/types"
2829
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
2930
"github.com/cosmos/cosmos-sdk/types/tx/signing"
3031
transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
@@ -1272,6 +1273,12 @@ func (cc *CosmosProvider) UpdateFeesSpent(chain, key string, fees sdk.Coins) {
12721273
}
12731274
}
12741275

1276+
// MsgRegisterCounterpartyPayee creates an sdk.Msg to broadcast the counterparty address
1277+
func (cc *CosmosProvider) MsgRegisterCounterpartyPayee(portID, channelID, relayerAddr, counterpartyPayee string) (provider.RelayerMessage,error) {
1278+
msg := feetypes.NewMsgRegisterCounterpartyPayee(portID, channelID, relayerAddr, counterpartyPayee)
1279+
return NewCosmosMessage(msg),nil
1280+
}
1281+
12751282
// PrepareFactory mutates the tx factory with the appropriate account number, sequence number, and min gas settings.
12761283
func (cc *CosmosProvider) PrepareFactory(txf tx.Factory) (tx.Factory, error) {
12771284
var (

‎relayer/chains/penumbra/tx.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -1352,7 +1352,6 @@ func (cc *PenumbraProvider) MsgConnectionOpenTry(msgOpenInit provider.Connection
13521352
return cosmos.NewCosmosMessage(msg), nil
13531353
}
13541354

1355-
13561355
func (cc *PenumbraProvider) MsgConnectionOpenAck(msgOpenTry provider.ConnectionInfo, proof provider.ConnectionProof) (provider.RelayerMessage, error) {
13571356
signer, err := cc.Address()
13581357
if err != nil {
@@ -2233,3 +2232,9 @@ func (cc *PenumbraProvider) SendMessagesToMempool(ctx context.Context, msgs []pr
22332232
cc.log.Debug("Received response from sending messages", zap.Any("response", sendRsp), zap.Error(err))
22342233
return err
22352234
}
2235+
2236+
// MsgRegisterCounterpartyPayee creates an sdk.Msg to broadcast the counterparty address
2237+
func (cc *PenumbraProvider) MsgRegisterCounterpartyPayee(portID, channelID, relayerAddr, counterpartyPayee string) (provider.RelayerMessage, error) {
2238+
//TODO implement me
2239+
panic("implement me")
2240+
}

0 commit comments

Comments
 (0)
Please sign in to comment.