Some checks failed
CodeQL / Analyze (push) Waiting to run
Docker Build & Push Simapp (main) / docker-build (push) Waiting to run
golangci-lint / lint (push) Waiting to run
Tests / Code Coverage / build (amd64) (push) Waiting to run
Tests / Code Coverage / build (arm64) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[additional-args:-tags="test_e2e" name:e2e path:./e2e]) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[name:08-wasm path:./modules/light-clients/08-wasm]) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[name:ibc-go path:.]) (push) Waiting to run
Deploy to GitHub Pages / Deploy to GitHub Pages (push) Has been cancelled
Buf-Push / push (push) Has been cancelled
179 lines
5.7 KiB
Go
179 lines
5.7 KiB
Go
package relayer
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/cosmos/interchaintest/v10"
|
|
"github.com/cosmos/interchaintest/v10/ibc"
|
|
"github.com/cosmos/interchaintest/v10/relayer"
|
|
"github.com/cosmos/interchaintest/v10/relayer/hermes"
|
|
mobycli "github.com/moby/moby/client"
|
|
"github.com/pelletier/go-toml"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
const (
|
|
Rly = "rly"
|
|
Hermes = "hermes"
|
|
|
|
HermesRelayerRepository = "ghcr.io/informalsystems/hermes"
|
|
hermesRelayerUser = "2000:2000"
|
|
RlyRelayerRepository = "ghcr.io/cosmos/relayer"
|
|
rlyRelayerUser = "100:1000"
|
|
|
|
// relativeHermesConfigFilePath is the path to the hermes config file relative to the home directory within the container.
|
|
relativeHermesConfigFilePath = ".hermes/config.toml"
|
|
)
|
|
|
|
// Config holds configuration values for the relayer used in the tests.
|
|
type Config struct {
|
|
// Tag is the tag used for the relayer image.
|
|
Tag string `yaml:"tag"`
|
|
// ID specifies the type of relayer that this is.
|
|
ID string `yaml:"id"`
|
|
// Image is the image that should be used for the relayer.
|
|
Image string `yaml:"image"`
|
|
}
|
|
|
|
// New returns an implementation of ibc.Relayer depending on the provided RelayerType.
|
|
func New(t *testing.T, cfg Config, logger *zap.Logger, dockerClient *mobycli.Client, network string) ibc.Relayer {
|
|
t.Helper()
|
|
switch cfg.ID {
|
|
case Rly:
|
|
return newCosmosRelayer(t, cfg.Tag, logger, dockerClient, network, cfg.Image)
|
|
case Hermes:
|
|
return newHermesRelayer(t, cfg.Tag, logger, dockerClient, network, cfg.Image)
|
|
default:
|
|
panic(fmt.Errorf("unknown relayer specified: %s", cfg.ID))
|
|
}
|
|
}
|
|
|
|
// ApplyPacketFilter applies a packet filter to the hermes config file, which specifies a complete set of channels
|
|
// to watch for packets.
|
|
func ApplyPacketFilter(ctx context.Context, t *testing.T, r ibc.Relayer, chainID string, channels []ibc.ChannelOutput) error {
|
|
t.Helper()
|
|
|
|
h, ok := r.(*hermes.Relayer)
|
|
if !ok {
|
|
t.Logf("relayer %T does not support packet filtering, or it has not been implemented yet.", r)
|
|
return nil
|
|
}
|
|
|
|
return modifyHermesConfigFile(ctx, h, func(config map[string]any) error {
|
|
chains, ok := config["chains"].([]map[string]any)
|
|
if !ok {
|
|
return errors.New("failed to get chains from hermes config")
|
|
}
|
|
var chain map[string]any
|
|
for _, c := range chains {
|
|
if c["id"] == chainID {
|
|
chain = c
|
|
break
|
|
}
|
|
}
|
|
|
|
if chain == nil {
|
|
return fmt.Errorf("failed to find chain with id %s", chainID)
|
|
}
|
|
|
|
var channelEndpoints [][]string
|
|
for _, c := range channels {
|
|
channelEndpoints = append(channelEndpoints, []string{c.PortID, c.ChannelID})
|
|
}
|
|
|
|
// [chains.packet_filter]
|
|
// # policy = 'allow'
|
|
// # list = [
|
|
// # ['ica*', '*'],
|
|
// # ['transfer', 'channel-0'],
|
|
// # ]
|
|
|
|
// TODO(chatton): explicitly enable watching of ICA channels
|
|
// this will ensure the ICA tests pass, but this will need to be modified to make sure
|
|
// ICA tests will succeed in parallel.
|
|
channelEndpoints = append(channelEndpoints, []string{"ica*", "*"})
|
|
|
|
// we explicitly override the full list, this allows this function to provide a complete set of channels to watch.
|
|
chain["packet_filter"] = map[string]any{
|
|
"policy": "allow",
|
|
"list": channelEndpoints,
|
|
}
|
|
|
|
return nil
|
|
})
|
|
}
|
|
|
|
// modifyHermesConfigFile reads the hermes config file, applies a modification function and returns an error if any.
|
|
func modifyHermesConfigFile(ctx context.Context, h *hermes.Relayer, modificationFn func(map[string]any) error) error {
|
|
bz, err := h.ReadFileFromHomeDir(ctx, relativeHermesConfigFilePath)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to read hermes config file: %w", err)
|
|
}
|
|
|
|
var config map[string]any
|
|
if err := toml.Unmarshal(bz, &config); err != nil {
|
|
return errors.New("failed to unmarshal hermes config bytes")
|
|
}
|
|
|
|
if modificationFn != nil {
|
|
if err := modificationFn(config); err != nil {
|
|
return fmt.Errorf("failed to modify hermes config: %w", err)
|
|
}
|
|
}
|
|
|
|
bz, err = toml.Marshal(config)
|
|
if err != nil {
|
|
return errors.New("failed to marshal hermes config bytes")
|
|
}
|
|
|
|
return h.WriteFileToHomeDir(ctx, relativeHermesConfigFilePath, bz)
|
|
}
|
|
|
|
// newCosmosRelayer returns an instance of the go relayer.
|
|
// Options are used to allow for relayer version selection and specifying the default processing option.
|
|
func newCosmosRelayer(t *testing.T, tag string, logger *zap.Logger, dockerClient *mobycli.Client, network, relayerImage string) ibc.Relayer {
|
|
t.Helper()
|
|
|
|
customImageOption := relayer.CustomDockerImage(relayerImage, tag, rlyRelayerUser)
|
|
relayerProcessingOption := relayer.StartupFlags("-p", "events") // relayer processes via events
|
|
|
|
relayerFactory := interchaintest.NewBuiltinRelayerFactory(ibc.CosmosRly, logger, customImageOption, relayerProcessingOption)
|
|
|
|
return relayerFactory.Build(
|
|
t, dockerClient, network,
|
|
)
|
|
}
|
|
|
|
// newHermesRelayer returns an instance of the hermes relayer.
|
|
func newHermesRelayer(t *testing.T, tag string, logger *zap.Logger, dockerClient *mobycli.Client, network, relayerImage string) ibc.Relayer {
|
|
t.Helper()
|
|
|
|
customImageOption := relayer.CustomDockerImage(relayerImage, tag, hermesRelayerUser)
|
|
relayerFactory := interchaintest.NewBuiltinRelayerFactory(ibc.Hermes, logger, customImageOption)
|
|
|
|
return relayerFactory.Build(
|
|
t, dockerClient, network,
|
|
)
|
|
}
|
|
|
|
// Map is a mapping from test names to a relayer set for that test.
|
|
type Map map[string]map[ibc.Wallet]bool
|
|
|
|
// AddRelayer adds the given relayer to the relayer set for the given test name.
|
|
func (r Map) AddRelayer(testName string, ibcrelayer ibc.Wallet) {
|
|
if _, ok := r[testName]; !ok {
|
|
r[testName] = make(map[ibc.Wallet]bool)
|
|
}
|
|
r[testName][ibcrelayer] = true
|
|
}
|
|
|
|
// ContainsRelayer returns true if the given relayer is in the relayer set for the given test name.
|
|
func (r Map) ContainsRelayer(testName string, wallet ibc.Wallet) bool {
|
|
if relayerSet, ok := r[testName]; ok {
|
|
return relayerSet[wallet]
|
|
}
|
|
return false
|
|
}
|