Skip to content

Commit

Permalink
ibc client authority (backport #198) (#204)
Browse files Browse the repository at this point in the history
Co-authored-by: Andrew Gouin <andrew@gouin.io>
  • Loading branch information
mergify[bot] and agouin authored Jul 14, 2023
1 parent 00ca4b5 commit ca1fa22
Show file tree
Hide file tree
Showing 9 changed files with 273 additions and 9 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/e2e-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Build Docker image
uses: strangelove-ventures/heighliner-build-action@v0.0.3
with:
registry: # empty registry, image only shared for e2e testing
registry: "" # empty registry, image only shared for e2e testing
tag: local # emulate local environment for consistency in interchaintest cases
tar-export-path: ${{ env.TAR_PATH }} # export a tarball that can be uploaded as an artifact for the e2e jobs
platform: linux/amd64 # test runner architecture only
Expand All @@ -42,7 +42,7 @@ jobs:
strategy:
matrix:
# names of `make` commands to run tests
test: ["ictest-tkn-factory", "ictest-packet-forward", "ictest-paramauthority", "ictest-chain-upgrade-noble-1", "ictest-chain-upgrade-grand-1", "ictest-globalFee", "ictest-ics20-bps-fees"]
test: ["ictest-tkn-factory", "ictest-packet-forward", "ictest-paramauthority", "ictest-chain-upgrade-noble-1", "ictest-chain-upgrade-grand-1", "ictest-globalFee", "ictest-ics20-bps-fees", "ictest-client-substitution"]
fail-fast: false

steps:
Expand Down
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,9 @@ ictest-globalFee:

ictest-ics20-bps-fees:
cd interchaintest && go test -race -v -run ^TestICS20BPSFees$$ .


ictest-client-substitution:
cd interchaintest && go test -race -v -run ^TestClientSubstitution$$ .

###############################################################################
### Build Image ###
Expand Down
11 changes: 11 additions & 0 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ import (
packetforward "github.com/strangelove-ventures/packet-forward-middleware/v3/router"
packetforwardkeeper "github.com/strangelove-ventures/packet-forward-middleware/v3/router/keeper"
packetforwardtypes "github.com/strangelove-ventures/packet-forward-middleware/v3/router/types"
paramauthorityibc "github.com/strangelove-ventures/paramauthority/x/ibc"
paramauthorityibctypes "github.com/strangelove-ventures/paramauthority/x/ibc/types"
paramauthority "github.com/strangelove-ventures/paramauthority/x/params"
paramauthoritykeeper "github.com/strangelove-ventures/paramauthority/x/params/keeper"
paramauthorityupgrade "github.com/strangelove-ventures/paramauthority/x/upgrade"
Expand Down Expand Up @@ -603,12 +605,21 @@ func New(
// Uncomment if you want to set a custom migration order here.
// app.mm.SetOrderMigrations(custom order)

// Register interfaces for paramauthority ibc proposal shim
paramauthorityibctypes.RegisterInterfaces(interfaceRegistry)

app.mm.RegisterInvariants(&app.CrisisKeeper)
app.mm.RegisterRoutes(app.Router(), app.QueryRouter(), encodingConfig.Amino)

app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter())
app.mm.RegisterServices(app.configurator)

// Register authoritative IBC client update and IBC upgrade msg handlers
paramauthorityibctypes.RegisterMsgServer(
app.configurator.MsgServer(),
paramauthorityibc.NewMsgServer(app.UpgradeKeeper, app.IBCKeeper.ClientKeeper),
)

// create the simulation manager and define the order of the modules for deterministic simulations
app.sm = module.NewSimulationManager(
auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts),
Expand Down
8 changes: 8 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/spf13/cast"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
paramauthorityibccli "github.com/strangelove-ventures/paramauthority/x/ibc/client/cli"
paramauthorityparamscli "github.com/strangelove-ventures/paramauthority/x/params/client/cli"
paramauthorityupgradecli "github.com/strangelove-ventures/paramauthority/x/upgrade/client/cli"
tmcli "github.com/tendermint/tendermint/libs/cli"
Expand Down Expand Up @@ -284,6 +285,12 @@ func txCommand(moduleBasics module.BasicManager) *cobra.Command {
RunE: client.ValidateCmd,
}

upgradeCmd := paramauthorityupgradecli.GetTxCmd()
upgradeCmd.AddCommand(
paramauthorityibccli.NewCmdSubmitUpdateClientProposal(),
paramauthorityibccli.NewCmdSubmitUpgradeProposal(),
)

cmd.AddCommand(
authcmd.GetSignCommand(),
authcmd.GetSignBatchCommand(),
Expand All @@ -293,6 +300,7 @@ func txCommand(moduleBasics module.BasicManager) *cobra.Command {
authcmd.GetBroadcastCommand(),
authcmd.GetEncodeCommand(),
authcmd.GetDecodeCommand(),
upgradeCmd,
paramauthorityupgradecli.GetTxCmd(),
paramauthorityparamscli.GetTxCmd(),
)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ require (
github.com/spf13/cobra v1.6.1
github.com/spf13/pflag v1.0.5
github.com/strangelove-ventures/packet-forward-middleware/v3 v3.1.5
github.com/strangelove-ventures/paramauthority v0.1.2
github.com/strangelove-ventures/paramauthority v0.2.0
github.com/stretchr/testify v1.8.1
github.com/tendermint/tendermint v0.34.27
github.com/tendermint/tm-db v0.6.7
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -938,8 +938,8 @@ github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+eg
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
github.com/strangelove-ventures/packet-forward-middleware/v3 v3.1.5 h1:iXXjziCSAebzuRUPFSnqD7epSDB8LEPgkh9zhbj7ha4=
github.com/strangelove-ventures/packet-forward-middleware/v3 v3.1.5/go.mod h1:ncgsf5rykh36HkM16BNcKKx1XzVRdWXt+4pph1syDHE=
github.com/strangelove-ventures/paramauthority v0.1.2 h1:PnbztiGi4ZhFqgcYXC86tQX2bLML17gsqC0EKZEhxg0=
github.com/strangelove-ventures/paramauthority v0.1.2/go.mod h1:PHq/b8q6YfBDJpo34RlnWw+cL5m5Bids2prBUWzsoEM=
github.com/strangelove-ventures/paramauthority v0.2.0 h1:h/ApdnvwV0gAjgQAFJ0Z2U6xuARvBnpmzhkvJRdkJZU=
github.com/strangelove-ventures/paramauthority v0.2.0/go.mod h1:31HVpoItQMa4Wj2BimVhQWbIYeb+kdUDJ8MzBEbGj28=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
Expand Down
2 changes: 1 addition & 1 deletion interchaintest/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ require (
github.com/icza/dyno v0.0.0-20220812133438-f0b6f8a18845
github.com/strangelove-ventures/interchaintest/v3 v3.0.0-20230622221919-28c608364e27
github.com/strangelove-ventures/noble v0.0.0-00010101000000-000000000000
github.com/strangelove-ventures/paramauthority v0.1.2
github.com/strangelove-ventures/paramauthority v0.2.0
github.com/stretchr/testify v1.8.4
go.uber.org/zap v1.24.0
)
Expand Down
4 changes: 2 additions & 2 deletions interchaintest/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -987,8 +987,8 @@ github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jH
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
github.com/strangelove-ventures/interchaintest/v3 v3.0.0-20230622221919-28c608364e27 h1:oJ9yZIFp3yRTlH8BOLnACrsjR1fPIpHyOoLFjM5VRBc=
github.com/strangelove-ventures/interchaintest/v3 v3.0.0-20230622221919-28c608364e27/go.mod h1:dWv7E8XtgidmA/A5Gy9x76qMIygES+SxPTnlWjYUb7g=
github.com/strangelove-ventures/paramauthority v0.1.2 h1:PnbztiGi4ZhFqgcYXC86tQX2bLML17gsqC0EKZEhxg0=
github.com/strangelove-ventures/paramauthority v0.1.2/go.mod h1:PHq/b8q6YfBDJpo34RlnWw+cL5m5Bids2prBUWzsoEM=
github.com/strangelove-ventures/paramauthority v0.2.0 h1:h/ApdnvwV0gAjgQAFJ0Z2U6xuARvBnpmzhkvJRdkJZU=
github.com/strangelove-ventures/paramauthority v0.2.0/go.mod h1:31HVpoItQMa4Wj2BimVhQWbIYeb+kdUDJ8MzBEbGj28=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
Expand Down
243 changes: 243 additions & 0 deletions interchaintest/ibc_client_expire_substitute_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
package interchaintest_test

import (
"context"
"encoding/json"
"fmt"
"testing"

"github.com/strangelove-ventures/interchaintest/v3"
"github.com/strangelove-ventures/interchaintest/v3/chain/cosmos"
"github.com/strangelove-ventures/interchaintest/v3/ibc"
"github.com/strangelove-ventures/interchaintest/v3/testreporter"
"github.com/strangelove-ventures/interchaintest/v3/testutil"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zaptest"
)

// run `make local-image`to rebuild updated binary before running test
func TestClientSubstitution(t *testing.T) {
if testing.Short() {
t.Skip()
}

t.Parallel()

ctx := context.Background()

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

client, network := interchaintest.DockerSetup(t)

var (
noble *cosmos.CosmosChain
roles NobleRoles
roles2 NobleRoles
paramauthorityWallet ibc.Wallet
)

chainCfg := ibc.ChainConfig{
Type: "cosmos",
Name: "noble",
ChainID: "noble-1",
Bin: "nobled",
Denom: "token",
Bech32Prefix: "noble",
CoinType: "118",
GasPrices: "0.0token",
GasAdjustment: 1.1,
TrustingPeriod: "504h",
NoHostMount: false,
Images: nobleImageInfo,
EncodingConfig: NobleEncoding(),
PreGenesis: func(cc ibc.ChainConfig) (err error) {
val := noble.Validators[0]
err = createTokenfactoryRoles(ctx, &roles, denomMetadataRupee, val, true)
if err != nil {
return err
}
err = createTokenfactoryRoles(ctx, &roles2, denomMetadataDrachma, val, true)
if err != nil {
return err
}
paramauthorityWallet, err = createParamAuthAtGenesis(ctx, val)
return err
},
ModifyGenesis: func(cc ibc.ChainConfig, b []byte) ([]byte, error) {
g := make(map[string]interface{})
if err := json.Unmarshal(b, &g); err != nil {
return nil, fmt.Errorf("failed to unmarshal genesis file: %w", err)
}
if err := modifyGenesisTokenfactory(g, "tokenfactory", denomMetadataRupee, &roles, true); err != nil {
return nil, err
}
if err := modifyGenesisTokenfactory(g, "fiat-tokenfactory", denomMetadataDrachma, &roles2, true); err != nil {
return nil, err
}
if err := modifyGenesisParamAuthority(g, paramauthorityWallet.FormattedAddress()); err != nil {
return nil, err
}
if err := modifyGenesisTariffDefaults(g, paramauthorityWallet.FormattedAddress()); err != nil {
return nil, err
}
out, err := json.Marshal(&g)
if err != nil {
return nil, fmt.Errorf("failed to marshal genesis bytes to json: %w", err)
}
return out, nil
},
}

nv := 1
nf := 0

cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{
{
ChainConfig: chainCfg,
NumValidators: &nv,
NumFullNodes: &nf,
},
{
Name: "gaia",
Version: "v10.0.2",
NumValidators: &nv,
NumFullNodes: &nf,
},
})

chains, err := cf.Chains(t.Name())
require.NoError(t, err)

noble = chains[0].(*cosmos.CosmosChain)
gaia := chains[1].(*cosmos.CosmosChain)

r := interchaintest.NewBuiltinRelayerFactory(
ibc.CosmosRly,
zaptest.NewLogger(t),
relayerImage,
).Build(t, client, network)

pathName := "noble-gaia"

ic := interchaintest.NewInterchain().
AddChain(noble).
AddChain(gaia).
AddRelayer(r, "r").
AddLink(interchaintest.InterchainLink{
Chain1: noble,
Chain2: gaia,
Relayer: r,
Path: pathName,
})

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

SkipPathCreation: true,
}))
t.Cleanup(func() {
_ = ic.Close()
})

nobleChainID := noble.Config().ChainID
gaiaChainID := gaia.Config().ChainID

err = r.GeneratePath(ctx, eRep, nobleChainID, gaiaChainID, pathName)
require.NoError(t, err)

// create client on noble with short trusting period which will expire.
res := r.Exec(ctx, eRep, []string{"rly", "tx", "client", nobleChainID, gaiaChainID, pathName, "--client-tp", "20s", "--home", "/home/relayer"}, nil)
require.NoError(t, res.Err)

// create client on gaia with longer trusting period so it won't expire for this test.
res = r.Exec(ctx, eRep, []string{"rly", "tx", "client", gaiaChainID, nobleChainID, pathName, "--home", "/home/relayer"}, nil)
require.NoError(t, res.Err)

err = testutil.WaitForBlocks(ctx, 2, noble, gaia)
require.NoError(t, err)

err = r.CreateConnections(ctx, eRep, pathName)
require.NoError(t, err)

err = testutil.WaitForBlocks(ctx, 2, noble, gaia)
require.NoError(t, err)

err = r.CreateChannel(ctx, eRep, pathName, ibc.CreateChannelOptions{
SourcePortName: "transfer",
DestPortName: "transfer",
Order: ibc.Unordered,
Version: "ics20-1",
})
require.NoError(t, err)

const userFunds = int64(10_000_000_000)
users := interchaintest.GetAndFundTestUsers(t, ctx, t.Name(), userFunds, noble, gaia)

nobleClients, err := r.GetClients(ctx, eRep, nobleChainID)
require.NoError(t, err)
require.Len(t, nobleClients, 1)

nobleClient := nobleClients[0]

nobleChannels, err := r.GetChannels(ctx, eRep, nobleChainID)
require.NoError(t, err)
require.Len(t, nobleChannels, 1)
nobleChannel := nobleChannels[0]

err = testutil.WaitForBlocks(ctx, 20, noble)
require.NoError(t, err)

// client should now be expired, no relayer was running to update the clients during the 20s trusting period.

_, err = noble.SendIBCTransfer(ctx, nobleChannel.ChannelID, users[0].KeyName(), ibc.WalletAmount{
Address: users[1].FormattedAddress(),
Amount: 1000000,
Denom: noble.Config().Denom,
}, ibc.TransferOptions{})

require.Error(t, err)
require.ErrorContains(t, err, "status Expired: client is not active")

// create new client on noble
res = r.Exec(ctx, eRep, []string{"rly", "tx", "client", nobleChainID, gaiaChainID, pathName, "--override", "--home", "/home/relayer"}, nil)
require.NoError(t, res.Err)

nobleClients, err = r.GetClients(ctx, eRep, nobleChainID)
require.NoError(t, err)
require.Len(t, nobleClients, 2)

newNobleClient := nobleClients[1]

// substitute new client state into old client
_, err = noble.Validators[0].ExecTx(ctx, paramauthorityWallet.KeyName(), "upgrade", "update-client", nobleClient.ClientID, newNobleClient.ClientID)
require.NoError(t, err)

// update config to old client ID
res = r.Exec(ctx, eRep, []string{"rly", "paths", "update", pathName, "--src-client-id", nobleClient.ClientID, "--home", "/home/relayer"}, nil)
require.NoError(t, res.Err)

// start up relayer and test a transfer
err = r.StartRelayer(ctx, eRep, pathName)
require.NoError(t, err)

t.Cleanup(func() {
_ = r.StopRelayer(ctx, eRep)
})

nobleHeight, err := noble.Height(ctx)
require.NoError(t, err)

// send a packet on the same channel with new client, should succeed.
tx, err := noble.SendIBCTransfer(ctx, nobleChannel.ChannelID, users[0].KeyName(), ibc.WalletAmount{
Address: users[1].FormattedAddress(),
Amount: 1000000,
Denom: noble.Config().Denom,
}, ibc.TransferOptions{})
require.NoError(t, err)

_, err = testutil.PollForAck(ctx, noble, nobleHeight, nobleHeight+10, tx.Packet)
require.NoError(t, err)
}

0 comments on commit ca1fa22

Please sign in to comment.