Skip to content

Commit

Permalink
ci: Break up the consumer chain interchaintests into user stories
Browse files Browse the repository at this point in the history
  • Loading branch information
fastfadingviolets committed Nov 5, 2024
1 parent 3dedd7a commit f1125b5
Show file tree
Hide file tree
Showing 7 changed files with 726 additions and 975 deletions.
242 changes: 242 additions & 0 deletions tests/interchain/consumer_chain/changeover_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
package consumer_chain_test

import (
"context"
"fmt"
"strconv"
"strings"
"testing"
"time"

sdkmath "cosmossdk.io/math"

"github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/gaia/v21/tests/interchain/chainsuite"
transfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types"
providertypes "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
"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/stretchr/testify/suite"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"
"golang.org/x/sync/errgroup"
)

type ChangeoverSuite struct {
*chainsuite.Suite
consumerCfg chainsuite.ConsumerConfig
Consumer *chainsuite.Chain
}

func (s *ChangeoverSuite) SetupSuite() {
s.Suite.SetupSuite()
validators := 1
fullNodes := 0
genesisChanges := []cosmos.GenesisKV{
cosmos.NewGenesisKV("app_state.gov.params.voting_period", chainsuite.GovVotingPeriod.String()),
cosmos.NewGenesisKV("app_state.gov.params.max_deposit_period", chainsuite.GovDepositPeriod.String()),
cosmos.NewGenesisKV("app_state.gov.params.min_deposit.0.denom", chainsuite.Ucon),
cosmos.NewGenesisKV("app_state.gov.params.min_deposit.0.amount", strconv.Itoa(chainsuite.GovMinDepositAmount)),
}
spec := &interchaintest.ChainSpec{
Name: "ics-consumer",
ChainName: "ics-consumer",
// Unfortunately, this rc is a bit of a bespoke version; it corresponds to an rc
// in hypha's fork that has a fix for sovereign -> consumer changeovers
Version: "v6.2.0-rc1",
NumValidators: &validators,
NumFullNodes: &fullNodes,
ChainConfig: ibc.ChainConfig{
Denom: chainsuite.Ucon,
GasPrices: "0.025" + chainsuite.Ucon,
GasAdjustment: 2.0,
Gas: "auto",
ConfigFileOverrides: map[string]any{
"config/config.toml": chainsuite.DefaultConfigToml(),
},
ModifyGenesisAmounts: chainsuite.DefaultGenesisAmounts(chainsuite.Ucon),
ModifyGenesis: cosmos.ModifyGenesis(genesisChanges),
Bin: "interchain-security-sd",
Images: []ibc.DockerImage{
{
Repository: chainsuite.HyphaICSRepo,
Version: "v6.2.0-rc1",
UidGid: chainsuite.ICSUidGuid,
},
},
Bech32Prefix: "consumer",
},
}
consumer, err := s.Chain.AddLinkedChain(s.GetContext(), s.T(), s.Relayer, spec)
s.Require().NoError(err)

s.Consumer = consumer

s.UpgradeChain()
}

func (s *ChangeoverSuite) TestRewardsWithChangeover() {
transferCh, err := s.Relayer.GetTransferChannel(s.GetContext(), s.Chain, s.Consumer)
s.Require().NoError(err)
rewardDenom := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom("transfer", transferCh.ChannelID, s.Consumer.Config().Denom)).IBCDenom()

s.Run("changeover", func() {
s.changeSovereignToConsumer(s.Consumer, transferCh)
})

s.Run("rewards", func() {
govAuthority, err := s.Chain.GetGovernanceAddress(s.GetContext())
s.Require().NoError(err)
rewardDenomsProp := providertypes.MsgChangeRewardDenoms{
DenomsToAdd: []string{rewardDenom},
Authority: govAuthority,
}
prop, err := s.Chain.BuildProposal([]cosmos.ProtoMessage{&rewardDenomsProp},
"add denoms to list of registered reward denoms",
"add denoms to list of registered reward denoms",
"", chainsuite.GovDepositAmount, "", false)
s.Require().NoError(err)
propResult, err := s.Chain.SubmitProposal(s.GetContext(), s.Chain.ValidatorWallets[0].Moniker, prop)
s.Require().NoError(err)
s.Require().NoError(s.Chain.PassProposal(s.GetContext(), propResult.ProposalID))

faucetAddrBts, err := s.Consumer.GetAddress(s.GetContext(), interchaintest.FaucetAccountKeyName)
s.Require().NoError(err)
faucetAddr := types.MustBech32ifyAddressBytes(s.Consumer.Config().Bech32Prefix, faucetAddrBts)
_, err = s.Consumer.Validators[0].ExecTx(
s.GetContext(), interchaintest.FaucetAccountKeyName,
"bank", "send", string(faucetAddr), s.Consumer.ValidatorWallets[0].Address,
"1"+s.Consumer.Config().Denom, "--fees", "100000000"+s.Consumer.Config().Denom,
)
s.Require().NoError(err)

s.Require().NoError(testutil.WaitForBlocks(s.GetContext(), chainsuite.BlocksPerDistribution+2, s.Chain, s.Consumer))
s.Require().NoError(s.Relayer.ClearTransferChannel(s.GetContext(), s.Chain, s.Consumer))
s.Require().NoError(testutil.WaitForBlocks(s.GetContext(), 2, s.Chain, s.Consumer))

rewardStr, err := s.Chain.QueryJSON(
s.GetContext(), fmt.Sprintf("total.#(%%\"*%s\")", rewardDenom),
"distribution", "rewards", s.Chain.ValidatorWallets[0].Address,
)
s.Require().NoError(err)
rewards, err := chainsuite.StrToSDKInt(rewardStr.String())
s.Require().NoError(err)
s.Require().True(rewards.GT(sdkmath.NewInt(0)), "rewards: %s", rewards.String())
})
}

func TestChangeover(t *testing.T) {
s := &ChangeoverSuite{
Suite: chainsuite.NewSuite(chainsuite.SuiteConfig{
CreateRelayer: true,
ChainSpec: &interchaintest.ChainSpec{
NumValidators: &chainsuite.OneValidator,
},
}),
consumerCfg: chainsuite.ConsumerConfig{
ChainName: "ics-consumer",
ShouldCopyProviderKey: allProviderKeysCopied(),
Denom: chainsuite.Ucon,
TopN: 0,
AllowInactiveVals: true,
MinStake: 1_000_000,
},
}
suite.Run(t, s)
}

func (s *ChangeoverSuite) changeSovereignToConsumer(consumer *chainsuite.Chain, transferCh *ibc.ChannelOutput) {
cfg := s.consumerCfg
currentHeight, err := consumer.Height(s.GetContext())
s.Require().NoError(err)
initialHeight := uint64(currentHeight) + 60
cfg.InitialHeight = initialHeight
spawnTime := time.Now().Add(60 * time.Second)
cfg.DistributionTransmissionChannel = transferCh.ChannelID

err = s.Chain.CreateConsumerPermissionless(s.GetContext(), consumer.Config().ChainID, cfg, spawnTime)
s.Require().NoError(err)

consumerChains, _, err := s.Chain.GetNode().ExecQuery(s.GetContext(), "provider", "list-consumer-chains")
s.Require().NoError(err)
consumerChain := gjson.GetBytes(consumerChains, fmt.Sprintf("chains.#(chain_id=%q)", consumer.Config().ChainID))
consumerID := consumerChain.Get("consumer_id").String()

eg := errgroup.Group{}
for i := range consumer.Validators {
i := i
eg.Go(func() error {
key, _, err := consumer.Validators[i].ExecBin(s.GetContext(), "tendermint", "show-validator")
if err != nil {
return err
}
keyStr := strings.TrimSpace(string(key))
_, err = s.Chain.Validators[i].ExecTx(s.GetContext(), s.Chain.ValidatorWallets[i].Moniker, "provider", "opt-in", consumerID, keyStr)
return err
})
}
s.Require().NoError(eg.Wait())

s.Require().NoError(err)
time.Sleep(time.Until(spawnTime))
s.Require().NoError(testutil.WaitForBlocks(s.GetContext(), 2, s.Chain))

proposal := cosmos.SoftwareUpgradeProposal{
Deposit: "5000000" + chainsuite.Ucon,
Title: "Changeover",
Name: "sovereign-changeover",
Description: "Changeover",
Height: int64(initialHeight) - 3,
}
upgradeTx, err := consumer.UpgradeProposal(s.GetContext(), interchaintest.FaucetAccountKeyName, proposal)
s.Require().NoError(err)
err = consumer.PassProposal(s.GetContext(), upgradeTx.ProposalID)
s.Require().NoError(err)

currentHeight, err = consumer.Height(s.GetContext())
s.Require().NoError(err)

timeoutCtx, timeoutCtxCancel := context.WithTimeout(s.GetContext(), (time.Duration(int64(initialHeight)-currentHeight)+10)*chainsuite.CommitTimeout)
defer timeoutCtxCancel()
err = testutil.WaitForBlocks(timeoutCtx, int(int64(initialHeight)-currentHeight)+3, consumer)
s.Require().Error(err)

s.Require().NoError(consumer.StopAllNodes(s.GetContext()))

genesis, err := consumer.GetNode().GenesisFileContent(s.GetContext())
s.Require().NoError(err)

ccvState, _, err := s.Chain.GetNode().ExecQuery(s.GetContext(), "provider", "consumer-genesis", consumerID)
s.Require().NoError(err)
genesis, err = sjson.SetRawBytes(genesis, "app_state.ccvconsumer", ccvState)
s.Require().NoError(err)

genesis, err = sjson.SetBytes(genesis, "app_state.slashing.params.signed_blocks_window", strconv.Itoa(chainsuite.SlashingWindowConsumer))
s.Require().NoError(err)
genesis, err = sjson.SetBytes(genesis, "app_state.ccvconsumer.params.reward_denoms", []string{chainsuite.Ucon})
s.Require().NoError(err)
genesis, err = sjson.SetBytes(genesis, "app_state.ccvconsumer.params.provider_reward_denoms", []string{s.Chain.Config().Denom})
s.Require().NoError(err)
genesis, err = sjson.SetBytes(genesis, "app_state.ccvconsumer.params.blocks_per_distribution_transmission", chainsuite.BlocksPerDistribution)
s.Require().NoError(err)

for _, val := range consumer.Validators {
val := val
eg.Go(func() error {
if err := val.OverwriteGenesisFile(s.GetContext(), []byte(genesis)); err != nil {
return err
}
return val.WriteFile(s.GetContext(), []byte(genesis), ".sovereign/config/genesis.json")
})
}
s.Require().NoError(eg.Wait())

consumer.ChangeBinary(s.GetContext(), "interchain-security-cdd")
s.Require().NoError(consumer.StartAllNodes(s.GetContext()))
s.Require().NoError(s.Relayer.ConnectProviderConsumer(s.GetContext(), s.Chain, consumer))
s.Require().NoError(s.Relayer.StopRelayer(s.GetContext(), chainsuite.GetRelayerExecReporter(s.GetContext())))
s.Require().NoError(s.Relayer.StartRelayer(s.GetContext(), chainsuite.GetRelayerExecReporter(s.GetContext())))
s.Require().NoError(s.Chain.CheckCCV(s.GetContext(), consumer, s.Relayer, 1_000_000, 0, 1))
}
49 changes: 0 additions & 49 deletions tests/interchain/consumer_chain/consumer_launch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,52 +154,3 @@ func TestICS6ConsumerNoKeysChainLaunch(t *testing.T) {
}
suite.Run(t, s)
}

type MainnetConsumerChainsSuite struct {
*chainsuite.Suite
}

func (s *MainnetConsumerChainsSuite) TestMainnetConsumerChainsAfterUpgrade() {
// We can't do these consumer launches yet because the chains aren't compatible with launching on v21 yet
if semver.Major(s.Env.OldGaiaImageVersion) == s.Env.UpgradeName && s.Env.UpgradeName == "v21" {
s.T().Skip("Skipping Consumer Launch tests when going from v21 -> v21")
}
neutron, err := s.Chain.AddConsumerChain(s.GetContext(), s.Relayer, chainsuite.ConsumerConfig{
ChainName: "neutron",
Version: chainsuite.NeutronVersion,
ShouldCopyProviderKey: allProviderKeysCopied(),
Denom: chainsuite.NeutronDenom,
TopN: 95,
})
s.Require().NoError(err)
stride, err := s.Chain.AddConsumerChain(s.GetContext(), s.Relayer, chainsuite.ConsumerConfig{
ChainName: "stride",
Version: chainsuite.StrideVersion,
ShouldCopyProviderKey: allProviderKeysCopied(),
Denom: chainsuite.StrideDenom,
TopN: 95,
})
s.Require().NoError(err)

s.Require().NoError(s.Chain.CheckCCV(s.GetContext(), neutron, s.Relayer, 1_000_000, 0, 1))
s.Require().NoError(s.Chain.CheckCCV(s.GetContext(), stride, s.Relayer, 1_000_000, 0, 1))

s.UpgradeChain()

s.Require().NoError(s.Chain.CheckCCV(s.GetContext(), neutron, s.Relayer, 1_000_000, 0, 1))
s.Require().NoError(s.Chain.CheckCCV(s.GetContext(), stride, s.Relayer, 1_000_000, 0, 1))
s.Require().NoError(chainsuite.SendSimpleIBCTx(s.GetContext(), s.Chain, neutron, s.Relayer))
s.Require().NoError(chainsuite.SendSimpleIBCTx(s.GetContext(), s.Chain, stride, s.Relayer))
}

func TestMainnetConsumerChainsAfterUpgrade(t *testing.T) {
s := &MainnetConsumerChainsSuite{
Suite: chainsuite.NewSuite(chainsuite.SuiteConfig{
CreateRelayer: true,
ChainSpec: &interchaintest.ChainSpec{
NumValidators: &chainsuite.SixValidators,
},
}),
}
suite.Run(t, s)
}
Loading

0 comments on commit f1125b5

Please sign in to comment.