diff --git a/interchaintest/icsdirect/README.md b/interchaintest/icsdirect/README.md deleted file mode 100644 index 3988616..0000000 --- a/interchaintest/icsdirect/README.md +++ /dev/null @@ -1 +0,0 @@ -# ICS Direct E2E diff --git a/interchaintest/icsdirect/chainsuite/chain.go b/interchaintest/icsdirect/chainsuite/chain.go deleted file mode 100644 index 0c5436f..0000000 --- a/interchaintest/icsdirect/chainsuite/chain.go +++ /dev/null @@ -1,484 +0,0 @@ -package chainsuite - -import ( - "context" - "encoding/json" - "fmt" - "strconv" - "strings" - "sync" - "time" - - e2e "github.com/lightlabs-dev/prysm/interchaintest" - "github.com/strangelove-ventures/interchaintest/v8" - "github.com/strangelove-ventures/interchaintest/v8/chain/cosmos" - "github.com/strangelove-ventures/interchaintest/v8/ibc" - "github.com/strangelove-ventures/interchaintest/v8/testutil" - "github.com/tidwall/gjson" - "golang.org/x/sync/errgroup" - - sdkmath "cosmossdk.io/math" - abcitypes "github.com/cometbft/cometbft/abci/types" - govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" -) - -// This moniker is hardcoded into interchaintest -const validatorMoniker = "validator" - -type Chain struct { - *cosmos.CosmosChain - ValidatorWallets []ValidatorWallet - RelayerWallet ibc.Wallet -} - -type ValidatorWallet struct { - Moniker string - Address string - ValoperAddress string - ValConsAddress string -} - -func chainFromCosmosChain(cosmos *cosmos.CosmosChain, relayerWallet ibc.Wallet) (*Chain, error) { - c := &Chain{CosmosChain: cosmos} - wallets, err := getValidatorWallets(context.Background(), c) - if err != nil { - return nil, err - } - c.ValidatorWallets = wallets - c.RelayerWallet = relayerWallet - return c, nil -} - -// CreateChain creates a single new chain with the given version and returns the chain object. -func CreateChain(ctx context.Context, testName interchaintest.TestName, spec *interchaintest.ChainSpec) (*Chain, error) { - cf := interchaintest.NewBuiltinChainFactory( - GetLogger(ctx), - []*interchaintest.ChainSpec{spec}, - ) - - chains, err := cf.Chains(testName.Name()) - if err != nil { - return nil, err - } - cosmosChain := chains[0].(*cosmos.CosmosChain) - relayerWallet, err := cosmosChain.BuildRelayerWallet(ctx, "relayer-"+cosmosChain.Config().ChainID) - if err != nil { - return nil, err - } - - ic := interchaintest.NewInterchain().AddChain(cosmosChain, ibc.WalletAmount{ - Address: relayerWallet.FormattedAddress(), - Denom: cosmosChain.Config().Denom, - Amount: sdkmath.NewInt(ValidatorFunds), - }) - - dockerClient, dockerNetwork := GetDockerContext(ctx) - - if err := ic.Build(ctx, GetRelayerExecReporter(ctx), interchaintest.InterchainBuildOptions{ - Client: dockerClient, - NetworkID: dockerNetwork, - TestName: testName.Name(), - }); err != nil { - return nil, err - } - - chain, err := chainFromCosmosChain(cosmosChain, relayerWallet) - if err != nil { - return nil, err - } - return chain, nil -} - -func (c *Chain) GenerateTx(ctx context.Context, valIdx int, command ...string) (string, error) { - command = append([]string{"tx"}, command...) - command = append(command, "--generate-only", "--keyring-backend", "test", "--chain-id", c.Config().ChainID) - command = c.Validators[valIdx].NodeCommand(command...) - stdout, _, err := c.Validators[valIdx].Exec(ctx, command, nil) - if err != nil { - return "", err - } - return string(stdout), nil -} - -func (c *Chain) WaitForProposalStatus(ctx context.Context, proposalID string, status govv1.ProposalStatus) error { - propID, err := strconv.ParseInt(proposalID, 10, 64) - if err != nil { - return err - } - chainHeight, err := c.Height(ctx) - if err != nil { - return err - } - // At 4s per block, 75 blocks is about 5 minutes. - maxHeight := chainHeight + 75 - _, err = cosmos.PollForProposalStatusV1(ctx, c.CosmosChain, chainHeight, maxHeight, uint64(propID), status) - return err -} - -func (c *Chain) PassProposal(ctx context.Context, proposalID string) error { - propID, err := strconv.ParseInt(proposalID, 10, 64) - if err != nil { - return err - } - err = c.VoteOnProposalAllValidators(ctx, uint64(propID), cosmos.ProposalVoteYes) - if err != nil { - return err - } - return c.WaitForProposalStatus(ctx, proposalID, govv1.StatusPassed) -} - -func (c *Chain) ReplaceImagesAndRestart(ctx context.Context, version string) error { - // bring down nodes to prepare for upgrade - err := c.StopAllNodes(ctx) - if err != nil { - return err - } - - // upgrade version on all nodes - c.UpgradeVersion(ctx, c.GetNode().DockerClient, c.GetNode().Image.Repository, version) - - // start all nodes back up. - // validators reach consensus on first block after upgrade height - // and block production resumes. - err = c.StartAllNodes(ctx) - if err != nil { - return err - } - - timeoutCtx, timeoutCancel := context.WithTimeout(ctx, 60*time.Second) - defer timeoutCancel() - err = testutil.WaitForBlocks(timeoutCtx, 5, c) - if err != nil { - return fmt.Errorf("failed to wait for blocks after upgrade: %w", err) - } - - // Flush "successfully migrated key info" messages - for _, val := range c.Validators { - _, _, err := val.ExecBin(ctx, "keys", "list", "--keyring-backend", "test") - if err != nil { - return err - } - } - return nil -} - -func (c *Chain) Upgrade(ctx context.Context, upgradeName, version string) error { - height, err := c.Height(ctx) - if err != nil { - return err - } - - haltHeight := height + UpgradeDelta - - proposal := cosmos.SoftwareUpgradeProposal{ - Deposit: GovDepositAmount, // greater than min deposit - Title: "Upgrade to " + upgradeName, - Name: upgradeName, - Description: "Upgrade to " + upgradeName, - Height: haltHeight, - } - upgradeTx, err := c.UpgradeProposal(ctx, interchaintest.FaucetAccountKeyName, proposal) - if err != nil { - return err - } - if err := c.PassProposal(ctx, upgradeTx.ProposalID); err != nil { - return err - } - - height, err = c.Height(ctx) - if err != nil { - return err - } - - // wait for the chain to halt. We're asking for blocks after the halt height, so we should time out. - timeoutCtx, timeoutCtxCancel := context.WithTimeout(ctx, (time.Duration(haltHeight-height)+10)*e2e.CommitTimeout) - defer timeoutCtxCancel() - err = testutil.WaitForBlocks(timeoutCtx, int(haltHeight-height)+3, c) - if err == nil { - return fmt.Errorf("chain should not produce blocks after halt height") - } else if timeoutCtx.Err() == nil { - return fmt.Errorf("chain should not produce blocks after halt height") - } - - height, err = c.Height(ctx) - if err != nil { - return err - } - - // make sure that chain is halted; some chains may produce one more block after halt height - if height-haltHeight > 1 { - return fmt.Errorf("height %d is not within one block of halt height %d; chain isn't halted", height, haltHeight) - } - - return c.ReplaceImagesAndRestart(ctx, version) -} - -func (c *Chain) GetValidatorPower(ctx context.Context, hexaddr string) (int64, error) { - var power int64 - err := CheckEndpoint(ctx, c.GetHostRPCAddress()+"/validators", func(b []byte) error { - power = gjson.GetBytes(b, fmt.Sprintf("result.validators.#(address==\"%s\").voting_power", hexaddr)).Int() - if power == 0 { - return fmt.Errorf("validator %s power not found; validators are: %s", hexaddr, string(b)) - } - return nil - }) - if err != nil { - return 0, err - } - return power, nil -} - -func (c *Chain) GetValidatorHex(ctx context.Context, val int) (string, error) { - json, err := c.Validators[val].ReadFile(ctx, "config/priv_validator_key.json") - if err != nil { - return "", err - } - providerHex := gjson.GetBytes(json, "address").String() - return providerHex, nil -} - -func getValidatorWallets(ctx context.Context, chain *Chain) ([]ValidatorWallet, error) { - wallets := make([]ValidatorWallet, len(chain.Validators)) - lock := new(sync.Mutex) - eg := new(errgroup.Group) - for i := range chain.Validators { - i := i - eg.Go(func() error { - // This moniker is hardcoded into the chain's genesis process. - moniker := validatorMoniker - address, err := chain.Validators[i].KeyBech32(ctx, moniker, "acc") - if err != nil { - return err - } - valoperAddress, err := chain.Validators[i].KeyBech32(ctx, moniker, "val") - if err != nil { - return err - } - valCons, _, err := chain.Validators[i].ExecBin(ctx, "comet", "show-address") - if err != nil { - return err - } - lock.Lock() - defer lock.Unlock() - wallets[i] = ValidatorWallet{ - Moniker: moniker, - Address: address, - ValoperAddress: valoperAddress, - ValConsAddress: strings.TrimSpace(string(valCons)), - } - return nil - }) - } - if err := eg.Wait(); err != nil { - return nil, err - } - return wallets, nil -} - -func (c *Chain) QueryJSON(ctx context.Context, jsonPath string, query ...string) (gjson.Result, error) { - stdout, _, err := c.GetNode().ExecQuery(ctx, query...) - if err != nil { - return gjson.Result{}, err - } - retval := gjson.GetBytes(stdout, jsonPath) - if !retval.Exists() { - return gjson.Result{}, fmt.Errorf("json path %s not found in query result %s", jsonPath, stdout) - } - return retval, nil -} - -// GetProposalID parses the proposal ID from the tx; necessary when the proposal type isn't accessible to interchaintest yet -func (c *Chain) GetProposalID(ctx context.Context, txhash string) (string, error) { - stdout, _, err := c.GetNode().ExecQuery(ctx, "tx", txhash) - if err != nil { - return "", err - } - result := struct { - Events []abcitypes.Event `json:"events"` - }{} - if err := json.Unmarshal(stdout, &result); err != nil { - return "", err - } - for _, event := range result.Events { - if event.Type == "submit_proposal" { - for _, attr := range event.Attributes { - if string(attr.Key) == "proposal_id" { - return string(attr.Value), nil - } - } - } - } - return "", fmt.Errorf("proposal ID not found in tx %s", txhash) -} - -func (c *Chain) hasOrderingFlag(ctx context.Context) (bool, error) { - cmd := c.GetNode().BinCommand("tx", "interchain-accounts", "controller", "register", "--help") - stdout, _, err := c.GetNode().Exec(ctx, cmd, nil) - if err != nil { - return false, err - } - return strings.Contains(string(stdout), "ordering"), nil -} - -func (c *Chain) GetICAAddress(ctx context.Context, srcAddress string, srcConnection string) string { - var icaAddress string - - // it takes a moment for it to be created - timeoutCtx, timeoutCancel := context.WithTimeout(ctx, 90*time.Second) - defer timeoutCancel() - for timeoutCtx.Err() == nil { - time.Sleep(5 * time.Second) - stdout, _, err := c.GetNode().ExecQuery(timeoutCtx, - "interchain-accounts", "controller", "interchain-account", - srcAddress, srcConnection, - ) - if err != nil { - GetLogger(ctx).Sugar().Warnf("error querying interchain account: %s", err) - continue - } - result := map[string]interface{}{} - err = json.Unmarshal(stdout, &result) - if err != nil { - GetLogger(ctx).Sugar().Warnf("error unmarshalling interchain account: %s", err) - continue - } - icaAddress = result["address"].(string) - if icaAddress != "" { - break - } - } - return icaAddress -} - -func (c *Chain) SetupICAAccount(ctx context.Context, host *Chain, relayer *Relayer, srcAddress string, valIdx int, initialFunds int64) (string, error) { - srcChannel, err := relayer.GetTransferChannel(ctx, c, host) - if err != nil { - return "", err - } - srcConnection := srcChannel.ConnectionHops[0] - - hasOrdering, err := c.hasOrderingFlag(ctx) - if err != nil { - return "", err - } - - if hasOrdering { - _, err = c.Validators[valIdx].ExecTx(ctx, srcAddress, - "interchain-accounts", "controller", "register", - "--ordering", "ORDER_ORDERED", "--version", "", - srcConnection, - ) - } else { - _, err = c.Validators[valIdx].ExecTx(ctx, srcAddress, - "interchain-accounts", "controller", "register", - srcConnection, - ) - } - if err != nil { - return "", err - } - - icaAddress := c.GetICAAddress(ctx, srcAddress, srcConnection) - if icaAddress == "" { - return "", fmt.Errorf("ICA address not found") - } - - err = host.SendFunds(ctx, interchaintest.FaucetAccountKeyName, ibc.WalletAmount{ - Denom: host.Config().Denom, - Amount: sdkmath.NewInt(initialFunds), - Address: icaAddress, - }) - if err != nil { - return "", err - } - - return icaAddress, nil -} - -func (c *Chain) AddLinkedChain(ctx context.Context, testName interchaintest.TestName, relayer *Relayer, spec *interchaintest.ChainSpec) (*Chain, error) { - dockerClient, dockerNetwork := GetDockerContext(ctx) - - cf := interchaintest.NewBuiltinChainFactory( - GetLogger(ctx), - []*interchaintest.ChainSpec{spec}, - ) - - chains, err := cf.Chains(testName.Name()) - if err != nil { - return nil, err - } - cosmosChainB := chains[0].(*cosmos.CosmosChain) - relayerWallet, err := cosmosChainB.BuildRelayerWallet(ctx, "relayer-"+cosmosChainB.Config().ChainID) - if err != nil { - return nil, err - } - - ic := interchaintest.NewInterchain().AddChain(cosmosChainB, ibc.WalletAmount{ - Address: relayerWallet.FormattedAddress(), - Denom: cosmosChainB.Config().Denom, - Amount: sdkmath.NewInt(ValidatorFunds), - }) - - if err := ic.Build(ctx, GetRelayerExecReporter(ctx), interchaintest.InterchainBuildOptions{ - Client: dockerClient, - NetworkID: dockerNetwork, - TestName: testName.Name(), - }); err != nil { - return nil, err - } - - chainB, err := chainFromCosmosChain(cosmosChainB, relayerWallet) - if err != nil { - return nil, err - } - rep := GetRelayerExecReporter(ctx) - if err := relayer.SetupChainKeys(ctx, chainB); err != nil { - return nil, err - } - if err := relayer.StopRelayer(ctx, rep); err != nil { - return nil, err - } - if err := relayer.StartRelayer(ctx, rep); err != nil { - return nil, err - } - - if err := relayer.GeneratePath(ctx, rep, c.Config().ChainID, chainB.Config().ChainID, relayerTransferPathFor(c, chainB)); err != nil { - return nil, err - } - - if err := relayer.LinkPath(ctx, rep, relayerTransferPathFor(c, chainB), ibc.CreateChannelOptions{ - DestPortName: TransferPortID, - SourcePortName: TransferPortID, - Order: ibc.Unordered, - }, ibc.DefaultClientOpts()); err != nil { - return nil, err - } - - return chainB, nil -} - -func (c *Chain) ModifyConfig(ctx context.Context, testName interchaintest.TestName, configChanges map[string]testutil.Toml) error { - eg := errgroup.Group{} - for _, val := range c.Validators { - val := val - eg.Go(func() error { - for file, changes := range configChanges { - if err := testutil.ModifyTomlConfigFile( - ctx, GetLogger(ctx), - val.DockerClient, testName.Name(), val.VolumeName, - file, changes, - ); err != nil { - return err - } - } - if err := val.StopContainer(ctx); err != nil { - return err - } - return val.StartContainer(ctx) - }) - } - if err := eg.Wait(); err != nil { - return err - } - return nil -} diff --git a/interchaintest/icsdirect/chainsuite/chain_ics.go b/interchaintest/icsdirect/chainsuite/chain_ics.go deleted file mode 100644 index c996d7e..0000000 --- a/interchaintest/icsdirect/chainsuite/chain_ics.go +++ /dev/null @@ -1,683 +0,0 @@ -package chainsuite - -import ( - "context" - "encoding/json" - "fmt" - "path" - "strconv" - "time" - - "github.com/strangelove-ventures/interchaintest/v8" - "github.com/strangelove-ventures/interchaintest/v8/chain/cosmos" - "github.com/strangelove-ventures/interchaintest/v8/ibc" - "github.com/strangelove-ventures/interchaintest/v8/testutil" - "github.com/tidwall/gjson" - "github.com/tidwall/sjson" - "go.uber.org/multierr" - - clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" - ccvclient "github.com/cosmos/interchain-security/v6/x/ccv/provider/client" - e2e "github.com/lightlabs-dev/prysm/interchaintest" - - sdkmath "cosmossdk.io/math" - - providertypes "github.com/cosmos/interchain-security/v6/x/ccv/provider/types" -) - -type ConsumerBootstrapCb func(ctx context.Context, consumer *cosmos.CosmosChain) - -type ConsumerConfig struct { - ChainName string - Version string - Denom string - ShouldCopyProviderKey []bool - TopN int - ValidatorSetCap int - ValidatorPowerCap int - AllowInactiveVals bool - MinStake uint64 - Allowlist []string - Denylist []string - InitialHeight uint64 - DistributionTransmissionChannel string - Spec *interchaintest.ChainSpec - - DuringDepositPeriod ConsumerBootstrapCb - DuringVotingPeriod ConsumerBootstrapCb - BeforeSpawnTime ConsumerBootstrapCb - AfterSpawnTime ConsumerBootstrapCb -} - -type proposalWaiter struct { - canDeposit chan struct{} - isInVoting chan struct{} - canVote chan struct{} - isPassed chan struct{} -} - -func (pw *proposalWaiter) waitForDepositAllowed() { - <-pw.canDeposit -} - -func (pw *proposalWaiter) startVotingPeriod() { - close(pw.isInVoting) -} - -func (pw *proposalWaiter) waitForVoteAllowed() { - <-pw.canVote -} - -func (pw *proposalWaiter) pass() { - close(pw.isPassed) -} - -func (pw *proposalWaiter) AllowVote() { - close(pw.canVote) -} - -func (pw *proposalWaiter) WaitForPassed() { - <-pw.isPassed -} - -func (pw *proposalWaiter) AllowDeposit() { - close(pw.canDeposit) -} - -func (pw *proposalWaiter) WaitForVotingPeriod() { - <-pw.isInVoting -} - -func newProposalWaiter() *proposalWaiter { - return &proposalWaiter{ - canDeposit: make(chan struct{}), - isInVoting: make(chan struct{}), - canVote: make(chan struct{}), - isPassed: make(chan struct{}), - } -} - -func (p *Chain) AddConsumerChain(ctx context.Context, relayer *Relayer, config ConsumerConfig) (*Chain, error) { - dockerClient, dockerNetwork := GetDockerContext(ctx) - - if len(config.ShouldCopyProviderKey) < len(p.Validators) { - return nil, fmt.Errorf("shouldCopyProviderKey should have at least %d elements", len(p.Validators)) - } - - spawnTime := time.Now().Add(ChainSpawnWait) - // We need -test- in there because certain consumer IDs are hardcoded into the binary and we can't re-launch them - chainID := fmt.Sprintf("%s-test-%d", config.ChainName, len(p.Consumers)+1) - - var proposalWaiter *proposalWaiter - var errCh chan error - - // For Prysm we know that we have the tx provider create-consumer command, so we just use that - // if p.GetNode().HasCommand(ctx, "tx", "provider", "create-consumer") { - errCh = make(chan error, 1) - close(errCh) - err := p.CreateConsumerPermissionless(ctx, chainID, config, spawnTime) - if err != nil { - return nil, err - } - // } else { - // var err error - // proposalWaiter, errCh, err = p.SubmitConsumerAdditionProposal(ctx, chainID, config, spawnTime) - // if err != nil { - // return nil, err - // } - // } - - defaultSpec := p.DefaultConsumerChainSpec(ctx, chainID, config, spawnTime, proposalWaiter) - config.Spec = MergeChainSpecs(defaultSpec, config.Spec) - providerICS := p.GetNode().ICSVersion(ctx) - if config.Spec.InterchainSecurityConfig.ConsumerVerOverride == "" { - // This will disable the genesis transform - config.Spec.InterchainSecurityConfig.ConsumerVerOverride = providerICS - } - cf := interchaintest.NewBuiltinChainFactory( - GetLogger(ctx), - []*interchaintest.ChainSpec{config.Spec}, - ) - chains, err := cf.Chains(p.GetNode().TestName) - if err != nil { - return nil, err - } - cosmosConsumer := chains[0].(*cosmos.CosmosChain) - - // We can't use AddProviderConsumerLink here because the provider chain is already built; we'll have to do everything by hand. - p.Consumers = append(p.Consumers, cosmosConsumer) - cosmosConsumer.Provider = p.CosmosChain - - relayerWallet, err := cosmosConsumer.BuildRelayerWallet(ctx, "relayer-"+cosmosConsumer.Config().ChainID) - if err != nil { - return nil, err - } - wallets := make([]ibc.Wallet, len(p.Validators)+1) - wallets[0] = relayerWallet - // This is a hack, but we need to create wallets for the validators that have the right moniker. - for i := 1; i <= len(p.Validators); i++ { - wallets[i], err = cosmosConsumer.BuildRelayerWallet(ctx, validatorMoniker) - if err != nil { - return nil, err - } - } - walletAmounts := make([]ibc.WalletAmount, len(wallets)) - for i, wallet := range wallets { - walletAmounts[i] = ibc.WalletAmount{ - Address: wallet.FormattedAddress(), - Denom: cosmosConsumer.Config().Denom, - Amount: sdkmath.NewInt(ValidatorFunds), - } - } - ic := interchaintest.NewInterchain(). - AddChain(cosmosConsumer, walletAmounts...). - AddRelayer(relayer, "relayer") - - if err := ic.Build(ctx, GetRelayerExecReporter(ctx), interchaintest.InterchainBuildOptions{ - Client: dockerClient, - NetworkID: dockerNetwork, - TestName: p.GetNode().TestName, - }); err != nil { - return nil, err - } - - // The chain should be built now, so we gotta check for errors in passing the proposal. - if err := <-errCh; err != nil { - return nil, err - } - - for i, val := range cosmosConsumer.Validators { - if err := val.RecoverKey(ctx, validatorMoniker, wallets[i+1].Mnemonic()); err != nil { - return nil, err - } - } - consumer, err := chainFromCosmosChain(cosmosConsumer, relayerWallet) - if err != nil { - return nil, err - } - - err = relayer.SetupChainKeys(ctx, consumer) - if err != nil { - return nil, err - } - rep := GetRelayerExecReporter(ctx) - if err := relayer.StopRelayer(ctx, rep); err != nil { - return nil, err - } - if err := relayer.StartRelayer(ctx, rep); err != nil { - return nil, err - } - err = relayer.ConnectProviderConsumer(ctx, p, consumer) - if err != nil { - return nil, err - } - - return consumer, nil -} - -func (p *Chain) CreateConsumerPermissionless(ctx context.Context, chainID string, config ConsumerConfig, spawnTime time.Time) error { - revisionHeight := config.InitialHeight - if revisionHeight == 0 { - revisionHeight = 1 - } - initParams := &providertypes.ConsumerInitializationParameters{ - InitialHeight: clienttypes.Height{RevisionNumber: clienttypes.ParseChainID(chainID), RevisionHeight: revisionHeight}, - SpawnTime: spawnTime, - BlocksPerDistributionTransmission: BlocksPerDistribution, - CcvTimeoutPeriod: 2419200000000000, - TransferTimeoutPeriod: 3600000000000, - ConsumerRedistributionFraction: "0.75", - HistoricalEntries: 10000, - UnbondingPeriod: 1728000000000000, - GenesisHash: []byte("Z2VuX2hhc2g="), - BinaryHash: []byte("YmluX2hhc2g="), - DistributionTransmissionChannel: config.DistributionTransmissionChannel, - } - powerShapingParams := &providertypes.PowerShapingParameters{ - Top_N: 0, - ValidatorSetCap: uint32(config.ValidatorSetCap), - ValidatorsPowerCap: uint32(config.ValidatorPowerCap), - AllowInactiveVals: config.AllowInactiveVals, - MinStake: config.MinStake, - Allowlist: config.Allowlist, - Denylist: config.Denylist, - } - params := providertypes.MsgCreateConsumer{ - ChainId: chainID, - Metadata: providertypes.ConsumerMetadata{ - Name: config.ChainName, - Description: "Consumer chain", - Metadata: "ipfs://", - }, - InitializationParameters: initParams, - PowerShapingParameters: powerShapingParams, - } - - paramsBz, err := json.Marshal(params) - if err != nil { - return err - } - err = p.GetNode().WriteFile(ctx, paramsBz, "consumer-addition.json") - if err != nil { - return err - } - _, err = p.GetNode().ExecTx(ctx, interchaintest.FaucetAccountKeyName, "provider", "create-consumer", path.Join(p.GetNode().HomeDir(), "consumer-addition.json")) - if err != nil { - return err - } - if config.TopN > 0 { - govAddress, err := p.GetGovernanceAddress(ctx) - if err != nil { - return err - } - consumerID, err := p.QueryJSON(ctx, fmt.Sprintf("chains.#(chain_id=%q).consumer_id", chainID), "provider", "list-consumer-chains") - if err != nil { - return err - } - update := &providertypes.MsgUpdateConsumer{ - ConsumerId: consumerID.String(), - NewOwnerAddress: govAddress, - Metadata: &providertypes.ConsumerMetadata{ - Name: config.ChainName, - Description: "Consumer chain", - Metadata: "ipfs://", - }, - InitializationParameters: initParams, - PowerShapingParameters: powerShapingParams, - } - updateBz, err := json.Marshal(update) - if err != nil { - return err - } - err = p.GetNode().WriteFile(ctx, updateBz, "consumer-update.json") - if err != nil { - return err - } - _, err = p.GetNode().ExecTx(ctx, interchaintest.FaucetAccountKeyName, "provider", "update-consumer", path.Join(p.GetNode().HomeDir(), "consumer-update.json")) - if err != nil { - return err - } - powerShapingParams.Top_N = uint32(config.TopN) - update = &providertypes.MsgUpdateConsumer{ - Owner: govAddress, - ConsumerId: consumerID.String(), - Metadata: &providertypes.ConsumerMetadata{ - Name: config.ChainName, - Description: "Consumer chain", - Metadata: "ipfs://", - }, - InitializationParameters: initParams, - PowerShapingParameters: powerShapingParams, - } - prop, err := p.BuildProposal([]cosmos.ProtoMessage{update}, "update consumer", "update consumer", "", GovDepositAmount, "", false) - if err != nil { - return err - } - txhash, err := p.GetNode().SubmitProposal(ctx, p.ValidatorWallets[0].Moniker, prop) - if err != nil { - return err - } - propID, err := p.GetProposalID(ctx, txhash) - if err != nil { - return err - } - if err := p.PassProposal(ctx, propID); err != nil { - return err - } - - } - return nil -} - -func (p *Chain) DefaultConsumerChainSpec(ctx context.Context, chainID string, config ConsumerConfig, spawnTime time.Time, proposalWaiter *proposalWaiter) *interchaintest.ChainSpec { - const ( - strideChain = "stride" - icsConsumer = "ics-consumer" - neutronChain = "neutron" - ) - fullNodes := len(p.FullNodes) - validators := len(p.Validators) - - chainType := config.ChainName - version := config.Version - denom := config.Denom - shouldCopyProviderKey := config.ShouldCopyProviderKey - - bechPrefix := "" - if chainType == icsConsumer { - majorVersion, err := strconv.Atoi(version[1:2]) - if err != nil { - // this really shouldn't happen unless someone misconfigured something - panic(fmt.Sprintf("failed to parse major version from %s: %v", version, err)) - } - if majorVersion >= 4 { - bechPrefix = "consumer" - } - } else if chainType == strideChain { - bechPrefix = "stride" - } - genesisOverrides := []cosmos.GenesisKV{ - cosmos.NewGenesisKV("app_state.slashing.params.signed_blocks_window", strconv.Itoa(SlashingWindowConsumer)), - cosmos.NewGenesisKV("app_state.ccvconsumer.params.reward_denoms", []string{denom}), - cosmos.NewGenesisKV("app_state.ccvconsumer.params.provider_reward_denoms", []string{p.Config().Denom}), - cosmos.NewGenesisKV("app_state.ccvconsumer.params.blocks_per_distribution_transmission", BlocksPerDistribution), - } - if config.TopN >= 0 { - genesisOverrides = append(genesisOverrides, cosmos.NewGenesisKV("app_state.ccvconsumer.params.soft_opt_out_threshold", "0.0")) - } - if chainType == neutronChain { - genesisOverrides = append(genesisOverrides, - cosmos.NewGenesisKV("app_state.globalfee.params.minimum_gas_prices", []interface{}{ - map[string]interface{}{ - "amount": "0.005", - "denom": denom, - }, - }), - ) - } - - if chainType == strideChain { - genesisOverrides = append(genesisOverrides, - cosmos.NewGenesisKV("app_state.gov.params.voting_period", e2e.GovVotingPeriod.String()), - ) - } - modifyGenesis := func(cc ibc.ChainConfig, b []byte) ([]byte, error) { - b, err := cosmos.ModifyGenesis(genesisOverrides)(cc, b) - if err != nil { - return nil, err - } - if chainType == strideChain { - b, err = sjson.SetBytes(b, "app_state.epochs.epochs.#(identifier==\"day\").duration", "120s") - if err != nil { - return nil, err - } - b, err = sjson.SetBytes(b, "app_state.epochs.epochs.#(identifier==\"stride_epoch\").duration", "30s") - if err != nil { - return nil, err - } - } - if gjson.GetBytes(b, "consensus").Exists() { - return sjson.SetBytes(b, "consensus.block.max_gas", "50000000") - } - return sjson.SetBytes(b, "consensus_params.block.max_gas", "50000000") - } - - return &interchaintest.ChainSpec{ - Name: chainType, - Version: version, - ChainName: chainID, - NumFullNodes: &fullNodes, - NumValidators: &validators, - ChainConfig: ibc.ChainConfig{ - Denom: denom, - GasPrices: "0.005" + denom, - GasAdjustment: 2.0, - Gas: "auto", - ChainID: chainID, - ConfigFileOverrides: map[string]any{ - "config/config.toml": e2e.DefaultConfigToml(), - }, - PreGenesis: func(consumer ibc.Chain) error { - if config.DuringDepositPeriod != nil { - config.DuringDepositPeriod(ctx, consumer.(*cosmos.CosmosChain)) - } - if proposalWaiter != nil { - proposalWaiter.AllowDeposit() - proposalWaiter.WaitForVotingPeriod() - } - if config.DuringVotingPeriod != nil { - config.DuringVotingPeriod(ctx, consumer.(*cosmos.CosmosChain)) - } - if proposalWaiter != nil { - proposalWaiter.AllowVote() - proposalWaiter.WaitForPassed() - } - tCtx, tCancel := context.WithDeadline(ctx, spawnTime) - defer tCancel() - if config.BeforeSpawnTime != nil { - config.BeforeSpawnTime(tCtx, consumer.(*cosmos.CosmosChain)) - } - // interchaintest will set up the validator keys right before PreGenesis. - // Now we just need to wait for the chain to spawn before interchaintest can get the ccv file. - // This wait is here and not there because of changes we've made to interchaintest that need to be upstreamed in an orderly way. - GetLogger(ctx).Sugar().Infof("waiting for chain %s to spawn at %s", chainID, spawnTime) - <-tCtx.Done() - if err := testutil.WaitForBlocks(ctx, 2, p); err != nil { - return err - } - if config.AfterSpawnTime != nil { - config.AfterSpawnTime(ctx, consumer.(*cosmos.CosmosChain)) - } - return nil - }, - Bech32Prefix: bechPrefix, - ModifyGenesisAmounts: DefaultGenesisAmounts(denom), - ModifyGenesis: modifyGenesis, - InterchainSecurityConfig: ibc.ICSConfig{ - ConsumerCopyProviderKey: func(i int) bool { - return shouldCopyProviderKey[i] - }, - }, - }, - } -} - -// func (p *Chain) SubmitConsumerAdditionProposal(ctx context.Context, chainID string, config ConsumerConfig, spawnTime time.Time) (*proposalWaiter, chan error, error) { -// // TODO: fix ICT so we have legacy and new -// // propWaiter := newProposalWaiter() -// // prop := p.buildConsumerAdditionJSON(chainID, config, spawnTime) -// // propTx, err := p.CreateConsumerAction(ctx, interchaintest.FaucetAccountKeyName, prop) -// // if err != nil { -// // return nil, nil, err -// // } -// // errCh := make(chan error, 1) -// // go func() { -// // defer close(errCh) -// // if err := p.WaitForProposalStatus(ctx, propTx.ProposalID, govv1.StatusDepositPeriod); err != nil { -// // errCh <- err -// // panic(err) -// // } -// // propWaiter.waitForDepositAllowed() - -// // if _, err := p.GetNode().ExecTx(ctx, interchaintest.FaucetAccountKeyName, "gov", "deposit", propTx.ProposalID, prop.Deposit); err != nil { -// // errCh <- err -// // panic(err) -// // } - -// // if err := p.WaitForProposalStatus(ctx, propTx.ProposalID, govv1.StatusVotingPeriod); err != nil { -// // errCh <- err -// // panic(err) -// // } -// // propWaiter.startVotingPeriod() -// // propWaiter.waitForVoteAllowed() - -// // if err := p.PassProposal(ctx, propTx.ProposalID); err != nil { -// // errCh <- err -// // panic(err) -// // } -// // propWaiter.pass() -// // }() -// // return propWaiter, errCh, nil -// panic("not implemented") -// return nil, nil, nil -// } - -func (p *Chain) buildConsumerAdditionJSON(chainID string, config ConsumerConfig, spawnTime time.Time) ccvclient.ConsumerAdditionProposalJSON { - prop := ccvclient.ConsumerAdditionProposalJSON{ - Title: fmt.Sprintf("Addition of %s consumer chain", chainID), - Summary: "Proposal to add new consumer chain", - ChainId: chainID, - InitialHeight: clienttypes.Height{RevisionNumber: clienttypes.ParseChainID(chainID), RevisionHeight: 1}, - GenesisHash: []byte("gen_hash"), - BinaryHash: []byte("bin_hash"), - SpawnTime: spawnTime, - - BlocksPerDistributionTransmission: BlocksPerDistribution, - CcvTimeoutPeriod: 2419200000000000, - TransferTimeoutPeriod: 3600000000000, - ConsumerRedistributionFraction: "0.75", - HistoricalEntries: 10000, - UnbondingPeriod: 1728000000000000, - Deposit: strconv.Itoa(e2e.GovMinDepositAmount/2) + p.Config().Denom, - } - if config.TopN >= 0 { - prop.TopN = uint32(config.TopN) - } - if config.ValidatorSetCap > 0 { - prop.ValidatorSetCap = uint32(config.ValidatorSetCap) - } - if config.ValidatorPowerCap > 0 { - prop.ValidatorsPowerCap = uint32(config.ValidatorPowerCap) - } - if config.AllowInactiveVals { - prop.AllowInactiveVals = true - } - if config.MinStake > 0 { - prop.MinStake = config.MinStake - } - return prop -} - -func (p *Chain) CheckCCV(ctx context.Context, consumer *Chain, relayer *Relayer, amount, valIdx, blocksPerEpoch int) error { - providerAddress := p.ValidatorWallets[valIdx] - - json, err := p.Validators[valIdx].ReadFile(ctx, "config/priv_validator_key.json") - if err != nil { - return err - } - providerHex := gjson.GetBytes(json, "address").String() - json, err = consumer.Validators[valIdx].ReadFile(ctx, "config/priv_validator_key.json") - if err != nil { - return err - } - consumerHex := gjson.GetBytes(json, "address").String() - - providerPowerBefore, err := p.GetValidatorPower(ctx, providerHex) - if err != nil { - return err - } - - if err := p.Validators[valIdx].StakingDelegate(ctx, providerAddress.Moniker, providerAddress.ValoperAddress, fmt.Sprintf("%d%s", amount, p.Config().Denom)); err != nil { - return err - } - - if blocksPerEpoch > 1 { - providerPower, err := p.GetValidatorPower(ctx, providerHex) - if err != nil { - return err - } - if providerPowerBefore >= providerPower { - return fmt.Errorf("provider power did not increase after delegation") - } - consumerPower, err := consumer.GetValidatorPower(ctx, consumerHex) - if err != nil { - return err - } - if providerPower == consumerPower { - return fmt.Errorf("consumer power updated too soon") - } - if err := testutil.WaitForBlocks(ctx, blocksPerEpoch, p); err != nil { - return err - } - } - - if err := relayer.ClearCCVChannel(ctx, p, consumer); err != nil { - return err - } - if err := testutil.WaitForBlocks(ctx, 2, p, consumer); err != nil { - return err - } - - tCtx, tCancel := context.WithTimeout(ctx, 15*time.Minute) - defer tCancel() - var retErr error - for tCtx.Err() == nil { - retErr = nil - providerPower, err := p.GetValidatorPower(ctx, providerHex) - if err != nil { - return err - } - consumerPower, err := consumer.GetValidatorPower(ctx, consumerHex) - if err != nil { - return err - } - if providerPowerBefore >= providerPower { - retErr = fmt.Errorf("provider power did not increase after delegation") - } else if providerPower != consumerPower { - retErr = fmt.Errorf("consumer power did not update after provider delegation") - } - if retErr == nil { - break - } - time.Sleep(e2e.CommitTimeout) - } - return retErr -} - -func (p *Chain) IsValoperJailed(ctx context.Context, valoper string) (bool, error) { - out, _, err := p.Validators[0].ExecQuery(ctx, "staking", "validator", valoper) - if err != nil { - return false, err - } - if gjson.GetBytes(out, "jailed").Exists() { - return gjson.GetBytes(out, "jailed").Bool(), nil - } - return gjson.GetBytes(out, "validator.jailed").Bool(), nil -} - -func (p *Chain) IsValidatorJailedForConsumerDowntime(ctx context.Context, relayer *Relayer, consumer *Chain, validatorIdx int) (jailed bool, err error) { - if err = consumer.Validators[validatorIdx].PauseContainer(ctx); err != nil { - return - } - defer func() { - sErr := consumer.Validators[validatorIdx].UnpauseContainer(ctx) - if sErr != nil { - err = multierr.Append(err, sErr) - return - } - time.Sleep(10 * e2e.CommitTimeout) - if jailed && err == nil { - if _, err = p.Validators[validatorIdx].ExecTx(ctx, p.ValidatorWallets[validatorIdx].Moniker, "slashing", "unjail"); err != nil { - return - } - var stillJailed bool - if stillJailed, err = p.IsValoperJailed(ctx, p.ValidatorWallets[validatorIdx].ValoperAddress); stillJailed { - err = fmt.Errorf("validator %d is still jailed after unjailing", validatorIdx) - } - } - }() - if p.Config().ChainID != consumer.Config().ChainID { - if err := relayer.ClearCCVChannel(ctx, p, consumer); err != nil { - return false, err - } - tCtx, tCancel := context.WithTimeout(ctx, SlashingWindowConsumer*2*e2e.CommitTimeout) - defer tCancel() - if err = testutil.WaitForBlocks(tCtx, SlashingWindowConsumer+1, consumer); err != nil { - if tCtx.Err() != nil { - err = fmt.Errorf("chain %s is stopped: %w", consumer.Config().ChainID, err) - } - return - } - if err := relayer.ClearCCVChannel(ctx, p, consumer); err != nil { - return false, err - } - } - tCtx, tCancel := context.WithTimeout(ctx, 30*e2e.CommitTimeout) - defer tCancel() - for tCtx.Err() == nil { - jailed, err = p.IsValoperJailed(ctx, p.ValidatorWallets[validatorIdx].ValoperAddress) - if err != nil || jailed { - return - } - time.Sleep(e2e.CommitTimeout) - } - return false, nil -} - -func (c *Chain) GetConsumerID(ctx context.Context, consumerID string) (string, error) { - consumerIDJSON, err := c.QueryJSON(ctx, fmt.Sprintf("chains.#(chain_id=%q).consumer_id", consumerID), "provider", "list-consumer-chains") - if err != nil { - return "", err - } - return consumerIDJSON.String(), nil -} diff --git a/interchaintest/icsdirect/chainsuite/config.go b/interchaintest/icsdirect/chainsuite/config.go deleted file mode 100644 index 6f1c4c0..0000000 --- a/interchaintest/icsdirect/chainsuite/config.go +++ /dev/null @@ -1,161 +0,0 @@ -package chainsuite - -import ( - "time" - - "github.com/strangelove-ventures/interchaintest/v8" - - sdkmath "cosmossdk.io/math" - - "github.com/cosmos/cosmos-sdk/types" - e2e "github.com/lightlabs-dev/prysm/interchaintest" -) - -type ChainScope int - -const ( - ChainScopeSuite ChainScope = iota - ChainScopeTest ChainScope = iota -) - -type SuiteConfig struct { - ChainSpec *interchaintest.ChainSpec - UpgradeOnSetup bool - CreateRelayer bool - Scope ChainScope -} - -var ( - Name = e2e.Name - Uatom = e2e.Denom - GovDepositAmount = "5000000" + Uatom - GasPrices = "0.005" + Uatom -) - -const ( - Ucon = "ucon" - NeutronDenom = "untn" - StrideDenom = "ustr" - DowntimeJailDuration = 10 * time.Second - ProviderSlashingWindow = 10 - // ValidatorCount = 1 - UpgradeDelta = 30 - ValidatorFunds = 11_000_000_000 - ChainSpawnWait = 155 * time.Second - SlashingWindowConsumer = 20 - BlocksPerDistribution = 10 - StrideVersion = "v22.0.0" - NeutronVersion = "v3.0.2" - TransferPortID = "transfer" - // This is needed because not every ics image is in the default heighliner registry - HyphaICSRepo = "ghcr.io/hyphacoop/ics" - ICSUidGuid = "1025:1025" -) - -// These have to be vars so we can take their address -var ( - OneValidator int = 1 - SixValidators int = 6 -) - -func MergeChainSpecs(spec, other *interchaintest.ChainSpec) *interchaintest.ChainSpec { - if spec == nil { - return other - } - if other == nil { - return spec - } - spec.ChainConfig = spec.MergeChainSpecConfig(other.ChainConfig) - if other.Name != "" { - spec.Name = other.Name - } - if other.ChainName != "" { - spec.ChainName = other.ChainName - } - if other.Version != "" { - spec.Version = other.Version - } - if other.NoHostMount != nil { - spec.NoHostMount = other.NoHostMount - } - if other.NumValidators != nil { - spec.NumValidators = other.NumValidators - } - if other.NumFullNodes != nil { - spec.NumFullNodes = other.NumFullNodes - } - return spec -} - -func (c SuiteConfig) Merge(other SuiteConfig) SuiteConfig { - c.ChainSpec = MergeChainSpecs(c.ChainSpec, other.ChainSpec) - c.UpgradeOnSetup = other.UpgradeOnSetup - c.CreateRelayer = other.CreateRelayer - c.Scope = other.Scope - return c -} - -func DefaultGenesisAmounts(denom string) func(i int) (types.Coin, types.Coin) { - return func(i int) (types.Coin, types.Coin) { - if i >= SixValidators { - panic("your chain has too many validators") - } - return types.Coin{ - Denom: denom, - Amount: sdkmath.NewInt(ValidatorFunds), - }, types.Coin{ - Denom: denom, - Amount: sdkmath.NewInt([]int64{ - 30_000_000, - 29_000_000, - 20_000_000, - 10_000_000, - 7_000_000, - 4_000_000, - }[i]), - } - } -} - -func DefaultChainSpec(env Environment) *interchaintest.ChainSpec { - // fullNodes := 0 - // var repository string - // if env.DockerRegistry == "" { - // repository = env.ImageName - // } else { - // repository = fmt.Sprintf("%s/%s", env.DockerRegistry, env.ImageName) - // } - // return &interchaintest.ChainSpec{ - // Name: Name, - // ChainName: Name, - // NumFullNodes: &fullNodes, - // NumValidators: &OneValidator, - // Version: env.OldGaiaImageVersion, - // ChainConfig: ibc.ChainConfig{ - // Type: "cosmos", - // Name: Name, - // ChainID: e2e.ChainID, - // Bin: e2e.Binary, - // Bech32Prefix: "prysm", - // Denom: Uatom, - // GasPrices: GasPrices, - // GasAdjustment: 2.0, - // ConfigFileOverrides: map[string]any{ - // "config/config.toml": DefaultConfigToml(), - // }, - // Images: []ibc.DockerImage{{ - // Repository: repository, - // UidGid: "1025:1025", // this is the user in heighliner docker images - // }}, - // ModifyGenesis: cosmos.ModifyGenesis(DefaultGenesis()), - // ModifyGenesisAmounts: DefaultGenesisAmounts(Uatom), - // }, - // } - return &e2e.DefaultChainSpec -} - -func DefaultSuiteConfig(env Environment) SuiteConfig { - return SuiteConfig{ - ChainSpec: DefaultChainSpec(env), - } -} diff --git a/interchaintest/icsdirect/chainsuite/context.go b/interchaintest/icsdirect/chainsuite/context.go deleted file mode 100644 index 4ccd90e..0000000 --- a/interchaintest/icsdirect/chainsuite/context.go +++ /dev/null @@ -1,86 +0,0 @@ -package chainsuite - -import ( - "context" - "fmt" - "time" - - "github.com/docker/docker/client" - "github.com/strangelove-ventures/interchaintest/v8" - "github.com/strangelove-ventures/interchaintest/v8/testreporter" - "github.com/stretchr/testify/suite" - "go.uber.org/zap" - "go.uber.org/zap/zaptest" -) - -type testReporterKey struct{} - -type relayerExecReporterKey struct{} - -type loggerKey struct{} - -type dockerKey struct{} - -type dockerContext struct { - NetworkID string - Client *client.Client -} - -func WithDockerContext(ctx context.Context, d *dockerContext) context.Context { - return context.WithValue(ctx, dockerKey{}, d) -} - -func GetDockerContext(ctx context.Context) (*client.Client, string) { - d, _ := ctx.Value(dockerKey{}).(*dockerContext) - return d.Client, d.NetworkID -} - -func WithTestReporter(ctx context.Context, r *testreporter.Reporter) context.Context { - return context.WithValue(ctx, testReporterKey{}, r) -} - -func GetTestReporter(ctx context.Context) *testreporter.Reporter { - r, _ := ctx.Value(testReporterKey{}).(*testreporter.Reporter) - return r -} - -func WithRelayerExecReporter(ctx context.Context, r *testreporter.RelayerExecReporter) context.Context { - return context.WithValue(ctx, relayerExecReporterKey{}, r) -} - -func GetRelayerExecReporter(ctx context.Context) *testreporter.RelayerExecReporter { - r, _ := ctx.Value(relayerExecReporterKey{}).(*testreporter.RelayerExecReporter) - return r -} - -func WithLogger(ctx context.Context, l *zap.Logger) context.Context { - return context.WithValue(ctx, loggerKey{}, l) -} - -func GetLogger(ctx context.Context) *zap.Logger { - l, _ := ctx.Value(loggerKey{}).(*zap.Logger) - return l -} - -func NewSuiteContext(s *suite.Suite) (context.Context, error) { - ctx := context.Background() - - dockerClient, dockerNetwork := interchaintest.DockerSetup(s.T()) - dockerContext := &dockerContext{ - NetworkID: dockerNetwork, - Client: dockerClient, - } - ctx = WithDockerContext(ctx, dockerContext) - logger := zaptest.NewLogger(s.T()) - ctx = WithLogger(ctx, logger) - - f, err := interchaintest.CreateLogFile(fmt.Sprintf("%d.json", time.Now().Unix())) - if err != nil { - return nil, err - } - testReporter := testreporter.NewReporter(f) - ctx = WithTestReporter(ctx, testReporter) - relayerExecReporter := testReporter.RelayerExecReporter(s.T()) - ctx = WithRelayerExecReporter(ctx, relayerExecReporter) - return ctx, nil -} diff --git a/interchaintest/icsdirect/chainsuite/envconfig.go b/interchaintest/icsdirect/chainsuite/envconfig.go deleted file mode 100644 index 1725a8f..0000000 --- a/interchaintest/icsdirect/chainsuite/envconfig.go +++ /dev/null @@ -1,21 +0,0 @@ -package chainsuite - -import ( - "github.com/kelseyhightower/envconfig" -) - -const prefix = "TEST" - -type Environment struct { - DockerRegistry string `envconfig:"DOCKER_REGISTRY"` - ImageName string `envconfig:"GAIA_IMAGE_NAME" default:"prysm"` - OldGaiaImageVersion string `envconfig:"OLD_GAIA_IMAGE_VERSION"` - NewGaiaImageVersion string `envconfig:"NEW_GAIA_IMAGE_VERSION"` - UpgradeName string `envconfig:"UPGRADE_NAME"` -} - -func GetEnvironment() Environment { - var env Environment - envconfig.MustProcess(prefix, &env) - return env -} diff --git a/interchaintest/icsdirect/chainsuite/http.go b/interchaintest/icsdirect/chainsuite/http.go deleted file mode 100644 index 5b0ef8b..0000000 --- a/interchaintest/icsdirect/chainsuite/http.go +++ /dev/null @@ -1,20 +0,0 @@ -package chainsuite - -import ( - "context" - "io" - "net/http" -) - -func CheckEndpoint(ctx context.Context, url string, f func([]byte) error) error { - resp, err := http.Get(url) //nolint:gosec - if err != nil { - return err - } - defer resp.Body.Close() - bts, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - return f(bts) -} diff --git a/interchaintest/icsdirect/chainsuite/ibc.go b/interchaintest/icsdirect/chainsuite/ibc.go deleted file mode 100644 index 2bb792b..0000000 --- a/interchaintest/icsdirect/chainsuite/ibc.go +++ /dev/null @@ -1,71 +0,0 @@ -package chainsuite - -import ( - "context" - "fmt" - "time" - - "cosmossdk.io/math" - transfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" - e2e "github.com/lightlabs-dev/prysm/interchaintest" - "github.com/strangelove-ventures/interchaintest/v8/ibc" -) - -func SendSimpleIBCTx(ctx context.Context, chainA *Chain, chainB *Chain, relayer *Relayer) error { - addr1 := chainA.ValidatorWallets[0].Address - addr2 := chainB.ValidatorWallets[0].Address - - senderTxChannel, err := relayer.GetTransferChannel(ctx, chainA, chainB) - if err != nil { - return err - } - - srcDenomTrace := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom("transfer", senderTxChannel.Counterparty.ChannelID, chainA.Config().Denom)) - dstIbcDenom := srcDenomTrace.IBCDenom() - - initial1, err := chainA.GetBalance(ctx, addr1, chainA.Config().Denom) - if err != nil { - return err - } - initial2, err := chainB.GetBalance(ctx, addr2, dstIbcDenom) - if err != nil { - return err - } - - amountToSend := math.NewInt(1_000_000) - _, err = chainA.Validators[0].SendIBCTransfer(ctx, senderTxChannel.ChannelID, chainA.ValidatorWallets[0].Moniker, ibc.WalletAmount{ - Denom: chainA.Config().Denom, - Amount: amountToSend, - Address: addr2, - }, ibc.TransferOptions{}) - if err != nil { - return err - } - tCtx, tCancel := context.WithTimeout(ctx, 30*e2e.CommitTimeout) - defer tCancel() - - for tCtx.Err() == nil { - time.Sleep(e2e.CommitTimeout) - var final1, final2 math.Int - final1, err = chainA.GetBalance(ctx, addr1, chainA.Config().Denom) - if err != nil { - continue - } - final2, err = chainB.GetBalance(ctx, addr2, dstIbcDenom) - if err != nil { - continue - } - - if !initial2.Add(amountToSend).Equal(final2) { - err = fmt.Errorf("destination balance not updated; expected %s, got %s", initial2.Add(amountToSend), final2) - continue - } - if !final1.LTE(initial1.Sub(amountToSend)) { - err = fmt.Errorf("source balance not updated; expected <= %s, got %s", initial1.Sub(amountToSend), final1) - continue - } - break - } - - return err -} diff --git a/interchaintest/icsdirect/chainsuite/relayer.go b/interchaintest/icsdirect/chainsuite/relayer.go deleted file mode 100644 index c99489e..0000000 --- a/interchaintest/icsdirect/chainsuite/relayer.go +++ /dev/null @@ -1,203 +0,0 @@ -package chainsuite - -import ( - "context" - "encoding/json" - "fmt" - "sort" - "time" - - e2e "github.com/lightlabs-dev/prysm/interchaintest" - "github.com/strangelove-ventures/interchaintest/v8" - "github.com/strangelove-ventures/interchaintest/v8/ibc" - "github.com/strangelove-ventures/interchaintest/v8/relayer" - "github.com/tidwall/gjson" -) - -type Relayer struct { - ibc.Relayer -} - -func NewRelayer(ctx context.Context, testName interchaintest.TestName) (*Relayer, error) { - dockerClient, dockerNetwork := GetDockerContext(ctx) - rly := interchaintest.NewBuiltinRelayerFactory( - ibc.Hermes, - GetLogger(ctx), - relayer.CustomDockerImage("ghcr.io/informalsystems/hermes", "1.10.3", "2000:2000"), - ).Build(testName, dockerClient, dockerNetwork) - return &Relayer{Relayer: rly}, nil -} - -func (r *Relayer) SetupChainKeys(ctx context.Context, chain *Chain) error { - rep := GetRelayerExecReporter(ctx) - rpcAddr, grpcAddr := chain.GetRPCAddress(), chain.GetGRPCAddress() - if !r.UseDockerNetwork() { - rpcAddr, grpcAddr = chain.GetHostRPCAddress(), chain.GetHostGRPCAddress() - } - - chainName := chain.Config().ChainID - if err := r.AddChainConfiguration(ctx, rep, chain.Config(), chainName, rpcAddr, grpcAddr); err != nil { - return err - } - - return r.RestoreKey(ctx, rep, chain.Config(), chainName, chain.RelayerWallet.Mnemonic()) -} - -func (r *Relayer) GetTransferChannel(ctx context.Context, chain, counterparty *Chain) (*ibc.ChannelOutput, error) { - return r.GetChannelWithPort(ctx, chain, counterparty, TransferPortID) -} - -func (r *Relayer) GetChannelWithPort(ctx context.Context, chain, counterparty *Chain, portID string) (*ibc.ChannelOutput, error) { - clients, err := r.GetClients(ctx, GetRelayerExecReporter(ctx), chain.Config().ChainID) - if err != nil { - return nil, err - } - for _, c := range clients { - if c.ClientState.ChainID == counterparty.Config().ChainID { - stdout, _, err := chain.GetNode().ExecQuery(ctx, "ibc", "connection", "connections") - if err != nil { - return nil, fmt.Errorf("error querying connections: %w", err) - } - connections := gjson.GetBytes(stdout, fmt.Sprintf("connections.#(client_id==\"%s\")#.id", c.ClientID)).Array() - if len(connections) == 0 { - continue - } - for _, connID := range connections { - stdout, _, err := chain.GetNode().ExecQuery(ctx, "ibc", "channel", "connections", connID.String()) - if err != nil { - return nil, err - } - channelJSON := gjson.GetBytes(stdout, fmt.Sprintf("channels.#(port_id==\"%s\")", portID)).String() - if channelJSON != "" { - channelOutput := &ibc.ChannelOutput{} - if err := json.Unmarshal([]byte(channelJSON), channelOutput); err != nil { - return nil, fmt.Errorf("error unmarshalling channel output %s: %w", channelJSON, err) - } - return channelOutput, nil - } - } - } - } - return nil, fmt.Errorf("no channel found for port %s", portID) -} - -func (r *Relayer) ClearCCVChannel(ctx context.Context, provider, consumer *Chain) error { - var channel *ibc.ChannelOutput - channel, err := r.GetChannelWithPort(ctx, consumer, provider, "consumer") - if err != nil { - return err - } - rs := r.Exec(ctx, GetRelayerExecReporter(ctx), []string{ - "hermes", "clear", "packets", "--port", "consumer", "--channel", channel.ChannelID, - "--chain", consumer.Config().ChainID, - }, nil) - if rs.Err != nil { - return fmt.Errorf("error clearing packets: %w", rs.Err) - } - return nil -} - -func (r *Relayer) ClearTransferChannel(ctx context.Context, chainA, chainB *Chain) error { - channel, err := r.GetTransferChannel(ctx, chainA, chainB) - if err != nil { - return err - } - rs := r.Exec(ctx, GetRelayerExecReporter(ctx), []string{ - "hermes", "clear", "packets", "--port", channel.PortID, "--channel", channel.ChannelID, - "--chain", chainA.Config().ChainID, - }, nil) - if rs.Err != nil { - return fmt.Errorf("error clearing packets: %w", rs.Err) - } - return nil -} - -func (r *Relayer) ConnectProviderConsumer(ctx context.Context, provider *Chain, consumer *Chain) error { - icsPath := relayerICSPathFor(provider, consumer) - rep := GetRelayerExecReporter(ctx) - if err := r.GeneratePath(ctx, rep, consumer.Config().ChainID, provider.Config().ChainID, icsPath); err != nil { - return err - } - - consumerClients, err := r.GetClients(ctx, rep, consumer.Config().ChainID) - if err != nil { - return err - } - sort.Slice(consumerClients, func(i, j int) bool { - return consumerClients[i].ClientID > consumerClients[j].ClientID - }) - var consumerClient *ibc.ClientOutput - for _, client := range consumerClients { - if client.ClientState.ChainID == provider.Config().ChainID { - consumerClient = client - break - } - } - if consumerClient == nil { - return fmt.Errorf("consumer chain %s does not have a client tracking the provider chain %s", consumer.Config().ChainID, provider.Config().ChainID) - } - consumerClientID := consumerClient.ClientID - - providerClients, err := r.GetClients(ctx, rep, provider.Config().ChainID) - if err != nil { - return err - } - sort.Slice(providerClients, func(i, j int) bool { - return providerClients[i].ClientID > providerClients[j].ClientID - }) - - var providerClient *ibc.ClientOutput - for _, client := range providerClients { - if client.ClientState.ChainID == consumer.Config().ChainID { - providerClient = client - break - } - } - if providerClient == nil { - return fmt.Errorf("provider chain %s does not have a client tracking the consumer chain %s for path %s on relayer %s", - provider.Config().ChainID, consumer.Config().ChainID, icsPath, r) - } - providerClientID := providerClient.ClientID - - if err := r.UpdatePath(ctx, rep, icsPath, ibc.PathUpdateOptions{ - SrcClientID: &consumerClientID, - DstClientID: &providerClientID, - }); err != nil { - return err - } - - if err := r.CreateConnections(ctx, rep, icsPath); err != nil { - return err - } - - if err := r.CreateChannel(ctx, rep, icsPath, ibc.CreateChannelOptions{ - SourcePortName: "consumer", - DestPortName: "provider", - Order: ibc.Ordered, - Version: "1", - }); err != nil { - return err - } - - tCtx, tCancel := context.WithTimeout(ctx, 30*e2e.CommitTimeout) - defer tCancel() - for tCtx.Err() == nil { - var ch *ibc.ChannelOutput - ch, err = r.GetTransferChannel(ctx, provider, consumer) - if err == nil && ch != nil { - break - } else if err == nil { - err = fmt.Errorf("channel not found") - } - time.Sleep(e2e.CommitTimeout) - } - return err -} - -func relayerICSPathFor(chainA, chainB *Chain) string { - return fmt.Sprintf("ics-%s-%s", chainA.Config().ChainID, chainB.Config().ChainID) -} - -func relayerTransferPathFor(chainA, chainB *Chain) string { - return fmt.Sprintf("transfer-%s-%s", chainA.Config().ChainID, chainB.Config().ChainID) -} diff --git a/interchaintest/icsdirect/chainsuite/suite.go b/interchaintest/icsdirect/chainsuite/suite.go deleted file mode 100644 index b055b5a..0000000 --- a/interchaintest/icsdirect/chainsuite/suite.go +++ /dev/null @@ -1,72 +0,0 @@ -package chainsuite - -import ( - "context" - - "github.com/stretchr/testify/suite" - "golang.org/x/mod/semver" -) - -type Suite struct { - suite.Suite - Config SuiteConfig - Env Environment - Chain *Chain - Relayer *Relayer - ctx context.Context -} - -func NewSuite(config SuiteConfig) *Suite { - env := GetEnvironment() - defaultConfig := DefaultSuiteConfig(env) - newCfg := defaultConfig.Merge(config) - return &Suite{Config: newCfg, Env: env} -} - -func (s *Suite) createChain() { - ctx, err := NewSuiteContext(&s.Suite) - s.Require().NoError(err) - s.ctx = ctx - s.Chain, err = CreateChain(s.GetContext(), s.T(), s.Config.ChainSpec) - s.Require().NoError(err) - if s.Config.CreateRelayer { - s.Relayer, err = NewRelayer(s.GetContext(), s.T()) - s.Require().NoError(err) - err = s.Relayer.SetupChainKeys(s.GetContext(), s.Chain) - s.Require().NoError(err) - } - if s.Config.UpgradeOnSetup { - s.UpgradeChain() - } -} - -func (s *Suite) SetupTest() { - if s.Config.Scope == ChainScopeTest { - s.createChain() - } -} - -func (s *Suite) SetupSuite() { - if s.Config.Scope == ChainScopeSuite { - s.createChain() - } -} - -func (s *Suite) GetContext() context.Context { - s.Require().NotNil(s.ctx, "Tried to GetContext before it was set. SetupSuite must run first") - return s.ctx -} - -func (s *Suite) UpgradeChain() { - GetLogger(s.GetContext()).Sugar().Infof("Upgrade %s from %s to %s", s.Env.UpgradeName, s.Env.OldGaiaImageVersion, s.Env.NewGaiaImageVersion) - if s.Env.UpgradeName == semver.Major(s.Env.OldGaiaImageVersion) { - // Not an on-chain upgrade, just replace the image. - s.Require().NoError(s.Chain.ReplaceImagesAndRestart(s.GetContext(), s.Env.NewGaiaImageVersion)) - } else { - s.Require().NoError(s.Chain.Upgrade(s.GetContext(), s.Env.UpgradeName, s.Env.NewGaiaImageVersion)) - } - if s.Relayer != nil { - s.Require().NoError(s.Relayer.StopRelayer(s.GetContext(), GetRelayerExecReporter(s.GetContext()))) - s.Require().NoError(s.Relayer.StartRelayer(s.GetContext(), GetRelayerExecReporter(s.GetContext()))) - } -} diff --git a/interchaintest/icsdirect/chainsuite/utils.go b/interchaintest/icsdirect/chainsuite/utils.go deleted file mode 100644 index a722282..0000000 --- a/interchaintest/icsdirect/chainsuite/utils.go +++ /dev/null @@ -1,17 +0,0 @@ -package chainsuite - -import ( - "fmt" - "strings" - - sdkmath "cosmossdk.io/math" -) - -func StrToSDKInt(s string) (sdkmath.Int, error) { - s, _, _ = strings.Cut(s, ".") - i, ok := sdkmath.NewIntFromString(s) - if !ok { - return sdkmath.Int{}, fmt.Errorf("s: %s", s) - } - return i, nil -} diff --git a/interchaintest/icsdirect/consumer_launch_test.go b/interchaintest/icsdirect/consumer_launch_test.go deleted file mode 100644 index 79ab38c..0000000 --- a/interchaintest/icsdirect/consumer_launch_test.go +++ /dev/null @@ -1,105 +0,0 @@ -package consumer_chain_test - -import ( - "fmt" - "testing" - - "github.com/strangelove-ventures/interchaintest/v8" - "github.com/strangelove-ventures/interchaintest/v8/ibc" - "github.com/stretchr/testify/suite" - - e2e "github.com/lightlabs-dev/prysm/interchaintest" - "github.com/lightlabs-dev/prysm/interchaintest/icsdirect/chainsuite" -) - -type ConsumerLaunchSuite struct { - *chainsuite.Suite - OtherChain string - OtherChainVersionPreUpgrade string - OtherChainVersionPostUpgrade string - ShouldCopyProviderKey []bool -} - -func TestICS6ConsumerNoKeysChainLaunch(t *testing.T) { - s := &ConsumerLaunchSuite{ - Suite: chainsuite.NewSuite(chainsuite.SuiteConfig{ - CreateRelayer: true, - ChainSpec: &interchaintest.ChainSpec{ - NumValidators: &chainsuite.SixValidators, - ChainConfig: e2e.DefaultChainConfig, - }, - }), - OtherChain: "ics-consumer", - OtherChainVersionPreUpgrade: "v6.2.1", // OtherChainVersionPreUpgrade: selectConsumerVersion("v6.0.0", "v6.2.1"), - OtherChainVersionPostUpgrade: "v6.2.1", - ShouldCopyProviderKey: noProviderKeysCopied(), - } - suite.Run(t, s) -} - -func (s *ConsumerLaunchSuite) TestChainLaunch() { - cfg := chainsuite.ConsumerConfig{ - ChainName: s.OtherChain, - Version: s.OtherChainVersionPreUpgrade, - ShouldCopyProviderKey: s.ShouldCopyProviderKey, - Denom: chainsuite.Ucon, - TopN: 94, - Spec: &interchaintest.ChainSpec{ - ChainConfig: ibc.ChainConfig{ - Images: []ibc.DockerImage{ - { - Repository: chainsuite.HyphaICSRepo, - Version: s.OtherChainVersionPreUpgrade, - UidGid: chainsuite.ICSUidGuid, - }, - }, - }, - }, - } - fmt.Println("Consumer Launch Test Setup", cfg) - - consumer, err := s.Chain.AddConsumerChain(s.GetContext(), s.Relayer, cfg) - s.Require().NoError(err) - err = s.Chain.CheckCCV(s.GetContext(), consumer, s.Relayer, 1_000_000, 0, 1) - s.Require().NoError(err) - - // s.UpgradeChain() - - // err = s.Chain.CheckCCV(s.GetContext(), consumer, s.Relayer, 1_000_000, 0, 1) - // s.Require().NoError(err) - // s.Require().NoError(chainsuite.SendSimpleIBCTx(s.GetContext(), s.Chain, consumer, s.Relayer)) - - // jailed, err := s.Chain.IsValidatorJailedForConsumerDowntime(s.GetContext(), s.Relayer, consumer, 1) - // s.Require().NoError(err) - // s.Require().True(jailed, "validator 1 should be jailed for downtime") - // jailed, err = s.Chain.IsValidatorJailedForConsumerDowntime(s.GetContext(), s.Relayer, consumer, 5) - // s.Require().NoError(err) - // s.Require().False(jailed, "validator 5 should not be jailed for downtime") - - // cfg.Version = s.OtherChainVersionPostUpgrade - // cfg.Spec.ChainConfig.Images[0].Version = s.OtherChainVersionPostUpgrade - // consumer2, err := s.Chain.AddConsumerChain(s.GetContext(), s.Relayer, cfg) - // s.Require().NoError(err) - // err = s.Chain.CheckCCV(s.GetContext(), consumer2, s.Relayer, 1_000_000, 0, 1) - // s.Require().NoError(err) - // s.Require().NoError(chainsuite.SendSimpleIBCTx(s.GetContext(), s.Chain, consumer2, s.Relayer)) - - // jailed, err = s.Chain.IsValidatorJailedForConsumerDowntime(s.GetContext(), s.Relayer, consumer2, 1) - // s.Require().NoError(err) - // s.Require().True(jailed, "validator 1 should be jailed for downtime") - // jailed, err = s.Chain.IsValidatorJailedForConsumerDowntime(s.GetContext(), s.Relayer, consumer2, 5) - // s.Require().NoError(err) - // s.Require().False(jailed, "validator 5 should not be jailed for downtime") -} - -func noProviderKeysCopied() []bool { - return []bool{false, false, false, false, false, false} -} - -// func allProviderKeysCopied() []bool { -// return []bool{true, true, true, true, true, true} -// } - -// func someProviderKeysCopied() []bool { -// return []bool{true, false, true, false, true, false} -// }