From 91194604d3f0fd322ebc33fcb842cfab65ade4e2 Mon Sep 17 00:00:00 2001 From: Bernd Mueller Date: Thu, 29 Aug 2024 17:14:19 +0200 Subject: [PATCH 1/9] Fix e2e tests + PSS e2e tests use permissionless --- tests/e2e/actions.go | 668 ++++++++++++++++-------- tests/e2e/config.go | 2 + tests/e2e/main.go | 63 ++- tests/e2e/state.go | 78 ++- tests/e2e/steps_partial_set_security.go | 544 ++++++------------- tests/e2e/test_driver.go | 14 +- tests/e2e/testlib/types.go | 4 +- tests/e2e/testlib/utils.go | 49 ++ 8 files changed, 786 insertions(+), 636 deletions(-) diff --git a/tests/e2e/actions.go b/tests/e2e/actions.go index 088ad19801..17e3525cc8 100644 --- a/tests/e2e/actions.go +++ b/tests/e2e/actions.go @@ -2,7 +2,6 @@ package main import ( "bufio" - "encoding/base64" "encoding/json" "fmt" "log" @@ -16,10 +15,12 @@ import ( "sync" "time" + sdk "github.com/cosmos/cosmos-sdk/types" clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" "github.com/tidwall/gjson" "golang.org/x/mod/semver" + ibctransfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types" e2e "github.com/cosmos/interchain-security/v5/tests/e2e/testlib" "github.com/cosmos/interchain-security/v5/x/ccv/provider/client" "github.com/cosmos/interchain-security/v5/x/ccv/provider/types" @@ -42,6 +43,13 @@ type SendTokensAction struct { Amount uint } +type TxResponse struct { + TxHash string `json:"txhash"` + Code int `json:"code"` + RawLog string `json:"raw_log"` + Events []sdk.Event `json:"events"` +} + func (tr Chain) sendTokens( action SendTokensAction, verbose bool, @@ -250,6 +258,124 @@ func (tr Chain) submitTextProposal( tr.waitBlocks(action.Chain, 1, 10*time.Second) } +type UpdateConsumerChainAction struct { + Chain ChainID + From ValidatorID + ConsumerChain ChainID + SpawnTime uint + InitialHeight clienttypes.Height + DistributionChannel string + TopN uint32 + ValidatorsPowerCap uint32 + ValidatorSetCap uint32 + Allowlist []string + Denylist []string + MinStake uint64 + AllowInactiveVals bool + NewOwner string +} + +func (tr Chain) updateConsumerChain(action UpdateConsumerChainAction, verbose bool) { + + spawn_time := tr.testConfig.containerConfig.Now.Add(time.Duration(action.SpawnTime) * time.Millisecond) + params := ccvtypes.DefaultParams() + initParams := types.ConsumerInitializationParameters{ + InitialHeight: action.InitialHeight, + GenesisHash: []byte("gen_hash"), + BinaryHash: []byte("bin_hash"), + SpawnTime: spawn_time, + + UnbondingPeriod: params.UnbondingPeriod, + CcvTimeoutPeriod: params.CcvTimeoutPeriod, + TransferTimeoutPeriod: params.TransferTimeoutPeriod, + ConsumerRedistributionFraction: params.ConsumerRedistributionFraction, + BlocksPerDistributionTransmission: params.BlocksPerDistributionTransmission, + HistoricalEntries: params.HistoricalEntries, + DistributionTransmissionChannel: action.DistributionChannel, + } + + powerShapingParams := types.PowerShapingParameters{ + Top_N: action.TopN, + ValidatorsPowerCap: action.ValidatorsPowerCap, + ValidatorSetCap: action.ValidatorSetCap, + Allowlist: action.Allowlist, + Denylist: action.Denylist, + MinStake: action.MinStake, + AllowInactiveVals: action.AllowInactiveVals, + } + + consumerID := tr.testConfig.chainConfigs[action.ConsumerChain].ConsumerId + update := types.MsgUpdateConsumer{ + ConsumerId: string(consumerID), + NewOwnerAddress: action.NewOwner, + InitializationParameters: &initParams, + PowerShapingParameters: &powerShapingParams, + } + tr.UpdateConsumer(action.Chain, action.From, update) +} + +type InitializeConsumerChainAction struct { + Chain ChainID + From ValidatorID + ConsumerChain ChainID + SpawnTime uint + InitialHeight clienttypes.Height + DistributionChannel string + TopN uint32 + ValidatorsPowerCap uint32 + ValidatorSetCap uint32 + Allowlist []string + Denylist []string + MinStake uint64 + AllowInactiveVals bool +} + +// initializeConsumerChain creates and initializes a consumer chain +func (tr Chain) initializeConsumerChain(action InitializeConsumerChainAction, verbose bool) { + + spawn_time := tr.testConfig.containerConfig.Now.Add(time.Duration(action.SpawnTime) * time.Millisecond) + params := ccvtypes.DefaultParams() + initParams := types.ConsumerInitializationParameters{ + InitialHeight: action.InitialHeight, + GenesisHash: []byte("gen_hash"), + BinaryHash: []byte("bin_hash"), + SpawnTime: spawn_time, + + UnbondingPeriod: params.UnbondingPeriod, + CcvTimeoutPeriod: params.CcvTimeoutPeriod, + TransferTimeoutPeriod: params.TransferTimeoutPeriod, + ConsumerRedistributionFraction: params.ConsumerRedistributionFraction, + BlocksPerDistributionTransmission: params.BlocksPerDistributionTransmission, + HistoricalEntries: params.HistoricalEntries, + DistributionTransmissionChannel: action.DistributionChannel, + } + + powerShapingParams := types.PowerShapingParameters{ + Top_N: action.TopN, + ValidatorsPowerCap: action.ValidatorsPowerCap, + ValidatorSetCap: action.ValidatorSetCap, + Allowlist: action.Allowlist, + Denylist: action.Denylist, + MinStake: action.MinStake, + AllowInactiveVals: action.AllowInactiveVals, + } + + metadata := types.ConsumerMetadata{ + Name: "chain name of " + string(action.Chain), + Description: "no description", + Metadata: "no metadata", + } + + // create consumer + consumerID := tr.CreateConsumer(action.Chain, action.ConsumerChain, action.From, metadata, &initParams, nil) + + update := types.MsgUpdateConsumer{ + ConsumerId: consumerID, + PowerShapingParameters: &powerShapingParams, + } + tr.UpdateConsumer(action.Chain, action.From, update) +} + type SubmitConsumerAdditionProposalAction struct { PreCCV bool Chain ChainID @@ -268,72 +394,230 @@ type SubmitConsumerAdditionProposalAction struct { AllowInactiveVals bool } +func (tr Chain) UpdateConsumer(providerChain ChainID, validator ValidatorID, update types.MsgUpdateConsumer) { + + fmt.Println("Update proposal for consumer_id=", update.ConsumerId) + content, err := json.Marshal(update) + if err != nil { + log.Fatalf("failed marshalling MsgUpdate", err.Error()) + } + jsonFile := "/update_consumer.json" + bz, err := tr.target.ExecCommand( + "/bin/bash", "-c", fmt.Sprintf(`echo '%s' > %s`, content, jsonFile), + ).CombinedOutput() + if err != nil { + log.Fatal(err, "\n", string(bz)) + } + + // Send consumer chain update + cmd := tr.target.ExecCommand( + tr.testConfig.chainConfigs[providerChain].BinaryName, + "tx", "provider", "update-consumer", jsonFile, + `--from`, `validator`+fmt.Sprint(validator), + `--chain-id`, string(tr.testConfig.chainConfigs[providerChain].ChainId), + `--home`, tr.getValidatorHome(providerChain, validator), + `--gas`, `900000`, + `--node`, tr.getValidatorNode(providerChain, validator), + `--keyring-backend`, `test`, + "--output", "json", + `-y`, + ) + + fmt.Println("Update Consumer", "cmd:", cmd.String(), "content:\n", string(content)) + + bz, err = cmd.CombinedOutput() + if err != nil { + log.Fatal("update consumer failed ", "error: ", err, "output: ", string(bz)) + } + + fmt.Println("update consumer", "output", string(bz)) + + // Check transaction + txResponse := &TxResponse{} + err = json.Unmarshal(bz, txResponse) + if err != nil { + log.Fatalf("unmarshalling tx response on update-consumer: %s, json: %s", err.Error(), string(bz)) + } + + if txResponse.Code != 0 { + log.Fatalf("sending update-consumer transaction failed with error code %d, Log:'%s'", txResponse.Code, txResponse.RawLog) + } + tr.waitBlocks(ChainID("provi"), 2, 10*time.Second) +} + +// CreateConsumer creates a consumer chain and returns its consumer-id +func (tr Chain) CreateConsumer(providerChain, consumerChain ChainID, validator ValidatorID, metadata types.ConsumerMetadata, initParams *types.ConsumerInitializationParameters, powershaping *types.PowerShapingParameters) string { + + chainID := string(tr.testConfig.chainConfigs[consumerChain].ChainId) + rec := types.MsgCreateConsumer{ + ChainId: chainID, + Metadata: metadata, + InitializationParameters: initParams, + PowerShapingParameters: powershaping, + } + + content, err := json.Marshal(rec) + if err != nil { + log.Fatalf("failed marshalling ConsumerRegistrationRecord", err.Error()) + } + jsonFile := "/create_consumer.json" + bz, err := tr.target.ExecCommand( + "/bin/bash", "-c", fmt.Sprintf(`echo '%s' > %s`, content, jsonFile), + ).CombinedOutput() + if err != nil { + log.Fatal(err, "\n", string(bz)) + } + + // Send consumer chain registration + cmd := tr.target.ExecCommand( + tr.testConfig.chainConfigs[providerChain].BinaryName, + "tx", "provider", "create-consumer", jsonFile, + `--from`, `validator`+fmt.Sprint(validator), + `--chain-id`, string(tr.testConfig.chainConfigs[providerChain].ChainId), + `--home`, tr.getValidatorHome(providerChain, validator), + `--gas`, `900000`, + `--node`, tr.getValidatorNode(providerChain, validator), + `--keyring-backend`, `test`, + "--output", "json", + `-y`, + ) + + fmt.Println("Create consumer", "cmd", cmd.String()) + fmt.Println("Create consumer", "json", string(content)) + + bz, err = cmd.CombinedOutput() + if err != nil { + log.Fatal("create consumer failed ", "error: ", err, "output: ", string(bz)) + } + + fmt.Println("create consumer output=", string(bz)) + + txResponse := &TxResponse{} + err = json.Unmarshal(bz, txResponse) + if err != nil { + log.Fatalf("unmarshalling tx response on consumer-registration: %s, json: %s", err.Error(), string(bz)) + } + + if txResponse.Code != 0 { + log.Fatalf("sending transaction failed with error code %d, Log:'%s'", txResponse.Code, txResponse.RawLog) + } + + // TODO: introduce waitForTx + tr.waitBlocks(providerChain, 2, 10*time.Second) + + // Get Consumer ID from tx + cmd = tr.target.ExecCommand( + tr.testConfig.chainConfigs[providerChain].BinaryName, + "query", "tx", txResponse.TxHash, + `--node`, tr.getValidatorNode(providerChain, validator), + "--output", "json", + ) + bz, err = cmd.CombinedOutput() + if err != nil { + log.Fatal("not able to query tx containing consumer registration: cmd:", cmd, "err:", err.Error(), "out:", string(bz)) + } + + err = json.Unmarshal(bz, txResponse) + if err != nil { + log.Fatalf("unmarshalling tx containing consumer registration: %s, json: %s", err.Error(), string(bz)) + } + + consumer_id := "" + for _, event := range txResponse.Events { + if event.Type != "consumer_creation" { + continue + } + attr, exists := event.GetAttribute("consumer_id") + if !exists { + log.Fatalf("no event with consumer_id found in tx content of consumer-registration: %v", event) + } + consumer_id = attr.Value + } + if consumer_id == "" { + log.Fatalf("no consumer-id found in consumer creation transaction events for chain '%s'. events: %v", consumerChain, txResponse.Events) + } + + cfg, exists := tr.testConfig.chainConfigs[e2e.ChainID(chainID)] + if !exists { + log.Fatal("no chain config found for consumer chain", chainID) + } + if cfg.ConsumerId != "" && cfg.ConsumerId != e2e.ConsumerID(consumer_id) { + log.Fatal("chain ", chainID, " registered already with a different consumer ID", consumer_id) + } + + // Set the new created consumer-id on the chain's config + cfg.ConsumerId = e2e.ConsumerID(consumer_id) + tr.testConfig.chainConfigs[e2e.ChainID(chainID)] = cfg + + return consumer_id +} + func (tr Chain) submitConsumerAdditionProposal( action SubmitConsumerAdditionProposalAction, verbose bool, ) { - spawnTime := tr.testConfig.containerConfig.Now.Add(time.Duration(action.SpawnTime) * time.Millisecond) params := ccvtypes.DefaultParams() - template := ` - { - "messages": [ - { - "@type": "/interchain_security.ccv.provider.v1.MsgConsumerAddition", - "chain_id": "%s", - "initial_height": { - "revision_number": "%d", - "revision_height": "%d" - }, - "genesis_hash": "%s", - "binary_hash": "%s", - "spawn_time": "%s", - "unbonding_period": "%s", - "ccv_timeout_period": "%s", - "transfer_timeout_period": "%s", - "consumer_redistribution_fraction": "%s", - "blocks_per_distribution_transmission": "%d", - "historical_entries": "%d", - "distribution_transmission_channel": "%s", - "top_N": %d, - "validators_power_cap": %d, - "validator_set_cap": %d, - "allowlist": %s, - "denylist": %s, - "authority": "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn", - "allow_inactive_vals": %t, - "min_stake": "%d" - } - ], -"metadata": "ipfs://CID", -"deposit": "%dstake", -"title": "Propose the addition of a new chain", -"summary": "Gonna be a great chain", -"expedited": false -}` - jsonStr := fmt.Sprintf(template, - string(tr.testConfig.chainConfigs[action.ConsumerChain].ChainId), - action.InitialHeight.RevisionNumber, - action.InitialHeight.RevisionHeight, - base64.StdEncoding.EncodeToString([]byte("gen_hash")), - base64.StdEncoding.EncodeToString([]byte("bin_hash")), - spawnTime.Local().Format(time.RFC3339Nano), - params.UnbondingPeriod, - params.CcvTimeoutPeriod, - params.TransferTimeoutPeriod, - params.ConsumerRedistributionFraction, - params.BlocksPerDistributionTransmission, - params.HistoricalEntries, - action.DistributionChannel, - action.TopN, - action.ValidatorsPowerCap, - action.ValidatorSetCap, - action.Allowlist, - action.Denylist, - action.AllowInactiveVals, - action.MinStake, - action.Deposit) + spawn_time := tr.testConfig.containerConfig.Now.Add(time.Duration(action.SpawnTime) * time.Millisecond) - //#nosec G204 -- bypass unsafe quoting warning (no production code) + Metadata := types.ConsumerMetadata{ + Name: "chain " + string(action.Chain), + Description: "no description", + Metadata: "no metadata", + } + + InitializationParameters := types.ConsumerInitializationParameters{ + InitialHeight: action.InitialHeight, + GenesisHash: []byte("gen_hash"), + BinaryHash: []byte("bin_hash"), + SpawnTime: spawn_time, + + UnbondingPeriod: params.UnbondingPeriod, + CcvTimeoutPeriod: params.CcvTimeoutPeriod, + TransferTimeoutPeriod: params.TransferTimeoutPeriod, + ConsumerRedistributionFraction: params.ConsumerRedistributionFraction, + BlocksPerDistributionTransmission: params.BlocksPerDistributionTransmission, + HistoricalEntries: params.HistoricalEntries, + DistributionTransmissionChannel: action.DistributionChannel, + } + + consumer_id := tr.CreateConsumer(action.Chain, action.ConsumerChain, action.From, Metadata, nil, nil) + authority := "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn" + + // Update consumer to change owner to governance before submitting the proposal + update := &types.MsgUpdateConsumer{ + ConsumerId: consumer_id, + NewOwnerAddress: authority, + } + // For the MsgUpdateConsumer sen in the proposal + PowerShapingParameters := types.PowerShapingParameters{ + Top_N: 0, + ValidatorsPowerCap: action.ValidatorsPowerCap, + ValidatorSetCap: action.ValidatorSetCap, + Allowlist: action.Allowlist, + Denylist: action.Denylist, + MinStake: action.MinStake, + AllowInactiveVals: action.AllowInactiveVals, + } + update.PowerShapingParameters = &PowerShapingParameters + tr.UpdateConsumer(action.Chain, action.From, *update) + + // - set PowerShaping params TopN > 0 for consumer chain + update.PowerShapingParameters.Top_N = action.TopN + update.Signer = authority + update.InitializationParameters = &InitializationParameters + update.InitializationParameters.SpawnTime = spawn_time + update.Metadata = &Metadata + + // Generate proposal content + title := "Propose the addition of a new chain" + description := "description of the consumer modification proposal" + summary := "Gonna be a great chain" + expedited := false + metadata := "ipfs://CID" + deposit := fmt.Sprintf("%dstake", action.Deposit) + jsonStr := e2e.GenerateGovProposalContent(title, summary, metadata, deposit, description, expedited, update) + + // #nosec G204 -- bypass unsafe quoting warning (no production code) proposalFile := "/consumer-addition.proposal" bz, err := tr.target.ExecCommand( "/bin/bash", "-c", fmt.Sprintf(`echo '%s' > %s`, jsonStr, proposalFile), @@ -352,6 +636,7 @@ func (tr Chain) submitConsumerAdditionProposal( `--gas`, `900000`, `--node`, tr.getValidatorNode(action.Chain, action.From), `--keyring-backend`, `test`, + `-o json`, `-y`, ) @@ -361,7 +646,17 @@ func (tr Chain) submitConsumerAdditionProposal( } bz, err = cmd.CombinedOutput() if err != nil { - log.Fatal("submit-proposal failed:", err, "\n", string(bz)) + log.Fatal("executing submit-proposal failed:", err, "\n", string(bz)) + } + + txResponse := &TxResponse{} + err = json.Unmarshal(bz, txResponse) + if err != nil { + log.Fatalf("failed unmarshalling tx response on submit consumer update: %s, json: %s", err.Error(), string(bz)) + } + + if txResponse.Code != 0 { + log.Fatalf("gov submit consumer update transaction failed with error code %d, Log:'%s'", txResponse.Code, txResponse.RawLog) } if verbose { @@ -467,31 +762,22 @@ func (tr Chain) submitConsumerRemovalProposal( action SubmitConsumerRemovalProposalAction, verbose bool, ) { - template := ` - { - "messages": [ - { - "@type": "/interchain_security.ccv.provider.v1.MsgConsumerRemoval", - "chain_id": "%s", - "stop_time": "%s", - "authority": "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn" - } - ], - "metadata": "ipfs://CID", - "deposit": "%dstake", - "title": "%s", - "summary": "It was a great chain", - "expedited": false - } -` + consumerID := string(tr.testConfig.chainConfigs[action.ConsumerChain].ConsumerId) title := fmt.Sprintf("Stop the %v chain", action.ConsumerChain) - stopTime := tr.testConfig.containerConfig.Now.Add(action.StopTimeOffset).Format(time.RFC3339Nano) + description := "stop consumer chain" + summary := "It was a great chain" + expedited := false + metadata := "ipfs://CID" + deposit := fmt.Sprintf("%dstake", action.Deposit) + authority := "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn" - jsonStr := fmt.Sprintf(template, - string(tr.testConfig.chainConfigs[action.ConsumerChain].ChainId), - stopTime, - action.Deposit, - title) + msgRemoveConsumer := types.MsgRemoveConsumer{ + ConsumerId: consumerID, + StopTime: tr.testConfig.containerConfig.Now.Add(action.StopTimeOffset), + Signer: authority, + } + + jsonStr := e2e.GenerateGovProposalContent(title, summary, metadata, deposit, description, expedited, &msgRemoveConsumer) // #nosec G204 -- bypass unsafe quoting warning (no production code) proposalFile := "/consumer-removal.proposal" @@ -599,45 +885,29 @@ func (tr Chain) submitConsumerModificationProposal( action SubmitConsumerModificationProposalAction, verbose bool, ) { - template := ` -{ -"messages": [ - { - "@type": "/interchain_security.ccv.provider.v1.MsgConsumerModification", - "title": "Propose the modification of the PSS parameters of a chain", - "description": "description of the consumer modification proposal", - "chain_id": "%s", - "top_N": %d, - "validators_power_cap": %d, - "validator_set_cap": %d, - "allowlist": %s, - "denylist": %s, - "authority": "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn", - "min_stake": %d, - "allow_inactive_vals": %t - } - ], -"metadata": "ipfs://CID", -"deposit": "%sstake", -"title": "Propose the modification of the PSS parameters of a chain", -"summary": "summary of a modification proposal", -"expedited": false - } -` - - jsonStr := fmt.Sprintf(template, - string(tr.testConfig.chainConfigs[action.ConsumerChain].ChainId), - action.TopN, - action.ValidatorsPowerCap, - action.ValidatorSetCap, - action.Allowlist, - action.Denylist, - action.Deposit, - action.MinStake, - action.AllowInactiveVals, - ) + consumerID := string(tr.testConfig.chainConfigs[action.ConsumerChain].ConsumerId) + title := "Propose the modification of the PSS parameters of a chain" + description := "description of the consumer modification proposal" + summary := "summary of a modification proposal" + expedited := false + metadata := "ipfs://CID" + deposit := fmt.Sprintf("%dstake", action.Deposit) + authority := "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn" + + msgConsMod := types.MsgUpdateConsumer{ + Signer: authority, + ConsumerId: consumerID, + PowerShapingParameters: &types.PowerShapingParameters{ + Top_N: action.TopN, + ValidatorsPowerCap: action.ValidatorsPowerCap, + ValidatorSetCap: action.ValidatorSetCap, + Allowlist: action.Allowlist, + Denylist: action.Denylist, + }, + } + jsonStr := e2e.GenerateGovProposalContent(title, summary, metadata, deposit, description, expedited, &msgConsMod) // #nosec G204 -- bypass unsafe quoting warning (no production code) proposalFile := "/consumer-mod.proposal" bz, err := tr.target.ExecCommand( @@ -754,26 +1024,21 @@ func (tr Chain) submitEnableTransfersProposalAction( ) { // gov signed address got by checking the gov module acc address in the test container // interchain-security-cdd q auth module-account gov --node tcp://7.7.9.253:26658 - template := ` - { - "messages": [ - { - "@type": "/ibc.applications.transfer.v1.MsgUpdateParams", - "signer": "consumer10d07y265gmmuvt4z0w9aw880jnsr700jlh7295", - "params": { - "send_enabled": true, - "receive_enabled": true - } - } - ], - "metadata": "ipfs://CID", - "deposit": "%dstake", - "title": "%s", - "summary": "Enable transfer send", - "expedited": false - } - ` - jsonStr := fmt.Sprintf(template, action.Deposit, action.Title) + + msgUpdateParams := ibctransfertypes.MsgUpdateParams{ + Signer: "consumer10d07y265gmmuvt4z0w9aw880jnsr700jlh7295", + Params: ibctransfertypes.Params{ + SendEnabled: true, + ReceiveEnabled: true, + }, + } + // Generate proposal content + description := "update IBC params" + summary := "Enable transfer send/receive" + expedited := false + metadata := "ipfs://CID" + deposit := fmt.Sprintf("%dstake", action.Deposit) + jsonStr := e2e.GenerateGovProposalContent(action.Title, summary, metadata, deposit, description, expedited, &msgUpdateParams) //#nosec G204 -- bypass unsafe quoting warning (no production code) bz, err := tr.target.ExecCommand( @@ -880,23 +1145,34 @@ func (tr *Chain) startConsumerChain( func (tr *Chain) getConsumerGenesis(providerChain, consumerChain ChainID) string { fmt.Println("Exporting consumer genesis from provider") providerBinaryName := tr.testConfig.chainConfigs[providerChain].BinaryName + consumerID := string(tr.testConfig.chainConfigs[consumerChain].ConsumerId) - cmd := tr.target.ExecCommand( - providerBinaryName, + now := time.Now() + timeout := now.Add(30 * time.Second) + var bz []byte + var err error + for { + cmd := tr.target.ExecCommand( + providerBinaryName, - "query", "provider", "consumer-genesis", - string(tr.testConfig.chainConfigs[consumerChain].ChainId), + "query", "provider", "consumer-genesis", consumerID, - `--node`, tr.target.GetQueryNode(providerChain), - `-o`, `json`, - ) + `--node`, tr.target.GetQueryNode(providerChain), + `-o`, `json`, + ) + bz, err = cmd.CombinedOutput() + if err == nil { + break + } - bz, err := cmd.CombinedOutput() - if err != nil { - log.Fatal(err, "\n", string(bz)) + if time.Now().After(timeout) { + log.Print("Failed running command: ", cmd) + log.Fatal(err, "\n", string(bz)) + } + time.Sleep(2 * time.Second) } - if tr.testConfig.transformGenesis || needsGenesisTransform(tr.testConfig) { + if tr.testConfig.transformGenesis || needsGenesisTransform(*tr.testConfig) { return string(tr.transformConsumerGenesis(consumerChain, bz)) } else { fmt.Println("No genesis transformation performed") @@ -1071,28 +1347,9 @@ func (tr Chain) changeoverChain( action ChangeoverChainAction, verbose bool, ) { - // sleep until the consumer chain genesis is ready on consumer - time.Sleep(5 * time.Second) - cmd := tr.target.ExecCommand( - tr.testConfig.chainConfigs[action.ProviderChain].BinaryName, - - "query", "provider", "consumer-genesis", - string(tr.testConfig.chainConfigs[action.SovereignChain].ChainId), - - `--node`, tr.target.GetQueryNode(action.ProviderChain), - `-o`, `json`, - ) - - if verbose { - log.Println("changeoverChain cmd: ", cmd.String()) - } - bz, err := cmd.CombinedOutput() - if err != nil { - log.Fatal(err, "\n", string(bz)) - } + consumerGenesis := ".app_state.ccvconsumer = " + tr.getConsumerGenesis(action.ProviderChain, action.SovereignChain) - consumerGenesis := ".app_state.ccvconsumer = " + string(bz) consumerGenesisChanges := tr.testConfig.chainConfigs[action.SovereignChain].GenesisChanges if consumerGenesisChanges != "" { consumerGenesis = consumerGenesis + " | " + consumerGenesisChanges @@ -2229,32 +2486,24 @@ type SubmitChangeRewardDenomsProposalAction struct { } func (tr Chain) submitChangeRewardDenomsProposal(action SubmitChangeRewardDenomsProposalAction, verbose bool) { - template := ` -{ - "messages": [ - { - "@type": "/interchain_security.ccv.provider.v1.MsgChangeRewardDenoms", - "denoms_to_add": ["%s"], - "denoms_to_remove": ["%s"], - "authority": "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn" - } - ], - "metadata": "ipfs://CID", - "deposit": "%dstake", - "title": "change reward denoms", - "summary": "Proposal to change reward denoms", - "expedited": false -}` - denomsToAdd := action.Denom - denomsToRemove := "stake" - jsonStr := fmt.Sprintf(template, - denomsToAdd, - denomsToRemove, - action.Deposit) + changeRewMsg := types.MsgChangeRewardDenoms{ + DenomsToAdd: []string{action.Denom}, + DenomsToRemove: []string{"stake"}, + Authority: "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn", + } + + // Generate proposal content + title := "change reward denoms" + description := "change reward denoms" + summary := "Proposal to change reward denoms" + expedited := false + metadata := "ipfs://CID" + deposit := fmt.Sprintf("%dstake", action.Deposit) + jsonStr := e2e.GenerateGovProposalContent(title, summary, metadata, deposit, description, expedited, &changeRewMsg) //#nosec G204 -- bypass unsafe quoting warning (no production code) - proposalFile := "/change-reward.proposal" + proposalFile := "/change-rewards.proposal" bz, err := tr.target.ExecCommand( "/bin/bash", "-c", fmt.Sprintf(`echo '%s' > %s`, jsonStr, proposalFile), ).CombinedOutput() @@ -2480,10 +2729,11 @@ func (tr Chain) assignConsumerPubKey(action AssignConsumerPubKeyAction, verbose if tr.testConfig.useCometmock { gas = "9000000" } + assignKey := fmt.Sprintf( `%s tx provider assign-consensus-key %s '%s' --from validator%s --chain-id %s --home %s --node %s --gas %s --keyring-backend test -y -o json`, tr.testConfig.chainConfigs[ChainID("provi")].BinaryName, - string(tr.testConfig.chainConfigs[action.Chain].ChainId), + string(tr.testConfig.chainConfigs[action.Chain].ConsumerId), action.ConsumerPubkey, action.Validator, tr.testConfig.chainConfigs[ChainID("provi")].ChainId, @@ -2659,7 +2909,7 @@ type OptInAction struct { Validator ValidatorID } -func (tr Chain) optIn(action OptInAction, target ExecutionTarget, verbose bool) { +func (tr Chain) optIn(action OptInAction, verbose bool) { // Note: to get error response reported back from this command '--gas auto' needs to be set. gas := "auto" // Unfortunately, --gas auto does not work with CometMock. so when using CometMock, just use --gas 9000000 then @@ -2671,7 +2921,7 @@ func (tr Chain) optIn(action OptInAction, target ExecutionTarget, verbose bool) optIn := fmt.Sprintf( `%s tx provider opt-in %s --from validator%s --chain-id %s --home %s --node %s --gas %s --keyring-backend test -y -o json`, tr.testConfig.chainConfigs[ChainID("provi")].BinaryName, - string(tr.testConfig.chainConfigs[action.Chain].ChainId), + string(tr.testConfig.chainConfigs[action.Chain].ConsumerId), action.Validator, tr.testConfig.chainConfigs[ChainID("provi")].ChainId, tr.getValidatorHome(ChainID("provi"), action.Validator), @@ -2679,7 +2929,7 @@ func (tr Chain) optIn(action OptInAction, target ExecutionTarget, verbose bool) gas, ) - cmd := target.ExecCommand( + cmd := tr.target.ExecCommand( "/bin/bash", "-c", optIn, ) @@ -2709,7 +2959,7 @@ type OptOutAction struct { ExpectError bool } -func (tr Chain) optOut(action OptOutAction, target ExecutionTarget, verbose bool) { +func (tr Chain) optOut(action OptOutAction, verbose bool) { // Note: to get error response reported back from this command '--gas auto' needs to be set. gas := "auto" // Unfortunately, --gas auto does not work with CometMock. so when using CometMock, just use --gas 9000000 then @@ -2721,7 +2971,7 @@ func (tr Chain) optOut(action OptOutAction, target ExecutionTarget, verbose bool optOut := fmt.Sprintf( `%s tx provider opt-out %s --from validator%s --chain-id %s --home %s --node %s --gas %s --keyring-backend test -y -o json`, tr.testConfig.chainConfigs[ChainID("provi")].BinaryName, - string(tr.testConfig.chainConfigs[action.Chain].ChainId), + string(tr.testConfig.chainConfigs[action.Chain].ConsumerId), action.Validator, tr.testConfig.chainConfigs[ChainID("provi")].ChainId, tr.getValidatorHome(ChainID("provi"), action.Validator), @@ -2729,7 +2979,7 @@ func (tr Chain) optOut(action OptOutAction, target ExecutionTarget, verbose bool gas, ) - cmd := target.ExecCommand( + cmd := tr.target.ExecCommand( "/bin/bash", "-c", optOut, ) @@ -2759,6 +3009,7 @@ func (tr Chain) optOut(action OptOutAction, target ExecutionTarget, verbose bool type SetConsumerCommissionRateAction struct { Chain ChainID + ConsumerID ConsumerID Validator ValidatorID CommissionRate float64 @@ -2767,7 +3018,7 @@ type SetConsumerCommissionRateAction struct { ExpectedError string } -func (tr Chain) setConsumerCommissionRate(action SetConsumerCommissionRateAction, target ExecutionTarget, verbose bool) { +func (tr Chain) setConsumerCommissionRate(action SetConsumerCommissionRateAction, verbose bool) { // Note: to get error response reported back from this command '--gas auto' needs to be set. gas := "auto" // Unfortunately, --gas auto does not work with CometMock. so when using CometMock, just use --gas 9000000 then @@ -2775,11 +3026,16 @@ func (tr Chain) setConsumerCommissionRate(action SetConsumerCommissionRateAction gas = "9000000" } + consumerID := string(tr.testConfig.chainConfigs[action.Chain].ConsumerId) + if action.ConsumerID != "" { + consumerID = string(action.ConsumerID) + } + // Use: "set-consumer-commission-rate [consumer-chain-id] [commission-rate]" setCommissionRate := fmt.Sprintf( `%s tx provider set-consumer-commission-rate %s %f --from validator%s --chain-id %s --home %s --node %s --gas %s --keyring-backend test -y -o json`, tr.testConfig.chainConfigs[ChainID("provi")].BinaryName, - string(tr.testConfig.chainConfigs[action.Chain].ChainId), + consumerID, action.CommissionRate, action.Validator, tr.testConfig.chainConfigs[ChainID("provi")].ChainId, @@ -2788,7 +3044,7 @@ func (tr Chain) setConsumerCommissionRate(action SetConsumerCommissionRateAction gas, ) - cmd := target.ExecCommand( + cmd := tr.target.ExecCommand( "/bin/bash", "-c", setCommissionRate, ) diff --git a/tests/e2e/config.go b/tests/e2e/config.go index 4fa762b5f7..ef5ed75d42 100644 --- a/tests/e2e/config.go +++ b/tests/e2e/config.go @@ -74,6 +74,7 @@ var hermesTemplates = map[string]string{ // type aliases for shared types from e2e package type ( ChainID = e2e.ChainID + ConsumerID = e2e.ConsumerID ValidatorID = e2e.ValidatorID ValidatorConfig = e2e.ValidatorConfig ChainConfig = e2e.ChainConfig @@ -122,6 +123,7 @@ type TestConfig struct { timeOffset time.Duration transformGenesis bool name string + Consumer2ChainID map[ConsumerID]ChainID // dynamic mapping of } // Initialize initializes the TestConfig instance by setting the runningChains field to an empty map. diff --git a/tests/e2e/main.go b/tests/e2e/main.go index 2864c9b413..bb8480a049 100644 --- a/tests/e2e/main.go +++ b/tests/e2e/main.go @@ -4,6 +4,8 @@ import ( "flag" "fmt" "log" + "log/slog" + "os" "strings" "sync" "time" @@ -246,6 +248,12 @@ var stepChoices = map[string]StepChoice{ description: "test minting without inactive validators as a sanity check", testConfig: MintTestCfg, }, + "permissionless-ics": { + name: "permissionless-ics", + steps: stepsPermissionlessICS(), + description: "test permissionless ics", + testConfig: DefaultTestCfg, + }, "inactive-vals-outside-max-validators": { name: "inactive-vals-outside-max-validators", steps: stepsInactiveValsTopNReproduce(), @@ -334,27 +342,27 @@ func getTestCases(selectedPredefinedTests, selectedTestFiles TestSet, providerVe // Run default tests if no test cases were selected if len(selectedPredefinedTests) == 0 && len(selectedTestFiles) == 0 { selectedPredefinedTests = TestSet{ - "changeover", - "happy-path", - "democracy-reward", - "democracy", - "slash-throttle", - "consumer-double-sign", - "consumer-misbehaviour", - "consumer-double-downtime", - "partial-set-security-opt-in", - "partial-set-security-top-n", - "partial-set-security-validator-set-cap", - "partial-set-security-validators-power-cap", - "partial-set-security-validators-allowlisted", - "partial-set-security-validators-denylisted", - "partial-set-security-modification-proposal", - "active-set-changes", - "inactive-provider-validators-on-consumer", - "inactive-vals-topN", - "inactive-provider-validators-governance", - "min-stake", - "inactive-vals-mint", + "changeover", // PASSED + "happy-path", // PASSED + "democracy-reward", // PASSED + "democracy", // PASSED + "slash-throttle", // PASSED + "consumer-double-sign", // TODO PERMISSIONLESS: failing + "consumer-misbehaviour", // TODO PERMISSIONLESS: failing + "consumer-double-downtime", // PASSED + "partial-set-security-opt-in", // PASSED + "partial-set-security-top-n", // PASSED + "partial-set-security-validator-set-cap", // PASSED + "partial-set-security-validators-power-cap", // PASSED + "partial-set-security-validators-allowlisted", // PASSED + "partial-set-security-validators-denylisted", // PASSED + "partial-set-security-modification-proposal", // TODO PERMISSIONLESS: failing + "active-set-changes", // PASSED + "inactive-provider-validators-on-consumer", // PASSED + "inactive-vals-topN", // TODO PERMISSIONLESS: failing + "inactive-provider-validators-governance", // PASSED + "min-stake", // PASSED + "inactive-vals-mint", // PASSED } if includeMultiConsumer != nil && *includeMultiConsumer { selectedPredefinedTests = append(selectedPredefinedTests, "multiconsumer") @@ -483,6 +491,18 @@ func createTestRunners(testCases []testStepsWithConfig) []TestRunner { return runners } +func SetupLogger() { + opts := &slog.HandlerOptions{ + AddSource: false, + Level: slog.LevelInfo, + } + if *verbose { + opts.Level = slog.LevelDebug + } + logger := slog.New(slog.NewTextHandler(os.Stdout, opts)) + slog.SetDefault(logger) +} + func executeTests(runners []TestRunner) error { if parallel != nil && *parallel { fmt.Println("=============== running all tests in parallel ===============") @@ -596,6 +616,7 @@ func main() { log.Fatalf("Error parsing command arguments %s\n", err) } + //SetupLogger() testCases := getTestCases(selectedTests, selectedTestfiles, providerVersions, consumerVersions) testRunners := createTestRunners(testCases) defer deleteTargets(testRunners) diff --git a/tests/e2e/state.go b/tests/e2e/state.go index f29c8f59f0..e6cd3c0256 100644 --- a/tests/e2e/state.go +++ b/tests/e2e/state.go @@ -12,6 +12,7 @@ import ( clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" e2e "github.com/cosmos/interchain-security/v5/tests/e2e/testlib" + "github.com/cosmos/interchain-security/v5/x/ccv/provider/types" "github.com/kylelemons/godebug/pretty" "github.com/tidwall/gjson" "gopkg.in/yaml.v2" @@ -38,7 +39,7 @@ type State map[ChainID]ChainState type Chain struct { target e2e.TargetDriver - testConfig TestConfig + testConfig *TestConfig } func (tr Chain) GetChainState(chain ChainID, modelState ChainState) ChainState { @@ -335,7 +336,7 @@ func intPtr(i int) *int { } type Commands struct { - containerConfig ContainerConfig // FIXME only needed for 'Now' time tracking + containerConfig *ContainerConfig validatorConfigs map[ValidatorID]ValidatorConfig chainConfigs map[ChainID]ChainConfig target e2e.PlatformDriver @@ -440,6 +441,10 @@ func (tr Commands) GetProposal(chain ChainID, proposal uint) Proposal { log.Fatal(err, "\n", propRaw) } + messages := gjson.Get(propRaw, `proposal.messages`) + for _, msg := range messages.Array() { + fmt.Println("msg val", msg) + } // for legacy proposal types submitted using "tx submit-legacyproposal" (cosmos-sdk/v1/MsgExecLegacyContent) propType := gjson.Get(propRaw, `proposal.messages.0.value.content.type`).String() rawContent := gjson.Get(propRaw, `proposal.messages.0.value.content.value`) @@ -465,6 +470,26 @@ func (tr Commands) GetProposal(chain ChainID, proposal uint) Proposal { Title: title, Description: description, } + case "/interchain_security.ccv.provider.v1.MsgUpdateConsumer": + spawnTime := rawContent.Get("initialization_parameters.spawn_time").Time().Sub(tr.containerConfig.Now) + consumerId := rawContent.Get("consumer_id").String() + consumer_chain_id := ChainID("") + for _, chainCfg := range tr.chainConfigs { + if chainCfg.ConsumerId == e2e.ConsumerID(consumerId) { + consumer_chain_id = chainCfg.ChainId + } + } + return e2e.ConsumerAdditionProposal{ + Deposit: uint(deposit), + Chain: consumer_chain_id, + Status: status, + SpawnTime: int(spawnTime.Milliseconds()), + InitialHeight: clienttypes.Height{ + RevisionNumber: rawContent.Get("initialization_parameters.initial_height.revision_number").Uint(), + RevisionHeight: rawContent.Get("initialization_parameters.initial_height.revision_height").Uint(), + }, + } + case "/interchain_security.ccv.provider.v1.MsgConsumerAddition": chainId := rawContent.Get("chain_id").String() spawnTime := rawContent.Get("spawn_time").Time().Sub(tr.containerConfig.Now) @@ -498,13 +523,13 @@ func (tr Commands) GetProposal(chain ChainID, proposal uint) Proposal { Title: title, Type: "/cosmos.upgrade.v1beta1.SoftwareUpgradeProposal", } - case "/interchain_security.ccv.provider.v1.MsgConsumerRemoval": - chainId := rawContent.Get("chain_id").String() + case "/interchain_security.ccv.provider.v1.MsgRemoveConsumer": + consumerID := rawContent.Get("consumer_id").String() stopTime := rawContent.Get("stop_time").Time().Sub(tr.containerConfig.Now) var chain ChainID for i, conf := range tr.chainConfigs { - if string(conf.ChainId) == chainId { + if string(conf.ConsumerId) == consumerID { chain = i break } @@ -746,8 +771,13 @@ func (tr Commands) GetConsumerChains(chain ChainID) map[ChainID]bool { arr := gjson.Get(string(bz), "chains").Array() chains := make(map[ChainID]bool) for _, c := range arr { - id := c.Get("chain_id").String() - chains[ChainID(id)] = true + phase := c.Get("phase").String() + if phase == types.ConsumerPhase_name[int32(types.ConsumerPhase_CONSUMER_PHASE_INITIALIZED)] || + phase == types.ConsumerPhase_name[int32(types.ConsumerPhase_CONSUMER_PHASE_REGISTERED)] || + phase == types.ConsumerPhase_name[int32(types.ConsumerPhase_CONSUMER_PHASE_LAUNCHED)] { + id := c.Get("chain_id").String() + chains[ChainID(id)] = true + } } return chains @@ -755,10 +785,11 @@ func (tr Commands) GetConsumerChains(chain ChainID) map[ChainID]bool { func (tr Commands) GetConsumerAddress(consumerChain ChainID, validator ValidatorID) string { binaryName := tr.chainConfigs[ChainID("provi")].BinaryName + consumer_id := tr.chainConfigs[ChainID(consumerChain)].ConsumerId cmd := tr.target.ExecCommand(binaryName, "query", "provider", "validator-consumer-key", - string(consumerChain), tr.validatorConfigs[validator].ValconsAddress, + string(consumer_id), tr.validatorConfigs[validator].ValconsAddress, `--node`, tr.GetQueryNode(ChainID("provi")), `-o`, `json`, ) @@ -773,10 +804,12 @@ func (tr Commands) GetConsumerAddress(consumerChain ChainID, validator Validator func (tr Commands) GetProviderAddressFromConsumer(consumerChain ChainID, validator ValidatorID) string { binaryName := tr.chainConfigs[ChainID("provi")].BinaryName + consumer_id := tr.chainConfigs[ChainID(consumerChain)].ConsumerId + cmd := tr.target.ExecCommand(binaryName, "query", "provider", "validator-provider-key", - string(consumerChain), tr.validatorConfigs[validator].ConsumerValconsAddressOnProvider, + string(consumer_id), tr.validatorConfigs[validator].ConsumerValconsAddressOnProvider, `--node`, tr.GetQueryNode(ChainID("provi")), `-o`, `json`, ) @@ -898,7 +931,11 @@ func (tr Commands) GetHasToValidate( arr := gjson.Get(string(bz), "consumer_chain_ids").Array() chains := []ChainID{} for _, c := range arr { - chains = append(chains, ChainID(c.String())) + for _, chain := range tr.chainConfigs { + if chain.ConsumerId == ConsumerID(c.String()) { + chains = append(chains, chain.ChainId) + } + } } return chains @@ -969,20 +1006,25 @@ func (tr Commands) GetTrustedHeight( func (tr Commands) GetProposedConsumerChains(chain ChainID) []string { binaryName := tr.chainConfigs[chain].BinaryName - bz, err := tr.target.ExecCommand(binaryName, - "query", "provider", "list-proposed-consumer-chains", + cmd := tr.target.ExecCommand(binaryName, + "query", "provider", "list-consumer-chains", `--node`, tr.GetQueryNode(chain), `-o`, `json`, - ).CombinedOutput() + ) + bz, err := cmd.CombinedOutput() if err != nil { log.Fatal(err, "\n", string(bz)) } - arr := gjson.Get(string(bz), "proposedChains").Array() + arr := gjson.Get(string(bz), "chains").Array() chains := []string{} for _, c := range arr { - cid := c.Get("chainID").String() - chains = append(chains, cid) + cid := c.Get("chain_id").String() + phase := c.Get("phase").String() + if phase == types.ConsumerPhase_name[int32(types.ConsumerPhase_CONSUMER_PHASE_INITIALIZED)] || + phase == types.ConsumerPhase_name[int32(types.ConsumerPhase_CONSUMER_PHASE_REGISTERED)] { + chains = append(chains, cid) + } } return chains @@ -1013,9 +1055,11 @@ func (tr Commands) GetQueryNodeIP(chain ChainID) string { // GetConsumerCommissionRate returns the commission rate of the given validator on the given consumerChain func (tr Commands) GetConsumerCommissionRate(consumerChain ChainID, validator ValidatorID) float64 { binaryName := tr.chainConfigs[ChainID("provi")].BinaryName + consumerID := tr.chainConfigs[consumerChain].ConsumerId + cmd := tr.target.ExecCommand(binaryName, "query", "provider", "validator-consumer-commission-rate", - string(consumerChain), tr.validatorConfigs[validator].ValconsAddress, + string(consumerID), tr.validatorConfigs[validator].ValconsAddress, `--node`, tr.GetQueryNode(ChainID("provi")), `-o`, `json`, ) diff --git a/tests/e2e/steps_partial_set_security.go b/tests/e2e/steps_partial_set_security.go index 80eff1aedd..4c2a5c457c 100644 --- a/tests/e2e/steps_partial_set_security.go +++ b/tests/e2e/steps_partial_set_security.go @@ -2,6 +2,7 @@ package main import ( "strconv" + "time" gov "github.com/cosmos/cosmos-sdk/x/gov/types/v1" clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" @@ -32,6 +33,7 @@ func stepsOptInChain() []Step { { Action: SetConsumerCommissionRateAction{ Chain: ChainID("consu"), + ConsumerID: "99999", Validator: ValidatorID("bob"), CommissionRate: 0.123, ExpectError: true, @@ -40,31 +42,17 @@ func stepsOptInChain() []Step { State: State{}, }, { - Action: SubmitConsumerAdditionProposalAction{ + Action: InitializeConsumerChainAction{ Chain: ChainID("provi"), From: ValidatorID("alice"), - Deposit: 10000001, ConsumerChain: ChainID("consu"), - SpawnTime: 0, + SpawnTime: uint(time.Minute * 10), // set spawn-time far in the future InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, TopN: 0, }, State: State{ ChainID("provi"): ChainState{ - Proposals: &map[uint]Proposal{ - 1: ConsumerAdditionProposal{ - Deposit: 10000001, - Chain: ChainID("consu"), - SpawnTime: 0, - InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD)), - }, - }, - HasToValidate: &map[ValidatorID][]ChainID{ - ValidatorID("alice"): {}, - ValidatorID("bob"): {}, - ValidatorID("carol"): {}, - }, + ProposedConsumerChains: &[]string{"consu"}, }, }, }, @@ -127,25 +115,15 @@ func stepsOptInChain() []Step { }, }, { - Action: VoteGovProposalAction{ - Chain: ChainID("provi"), - From: []ValidatorID{ValidatorID("alice"), ValidatorID("bob")}, - Vote: []string{"yes", "yes"}, - PropNumber: 1, - }, - State: State{ - ChainID("provi"): ChainState{ - Proposals: &map[uint]Proposal{ - 1: ConsumerAdditionProposal{ - Deposit: 10000001, - Chain: ChainID("consu"), - SpawnTime: 0, - InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_PASSED)), - }, - }, - }, + Action: UpdateConsumerChainAction{ + Chain: ChainID("provi"), + From: ValidatorID("alice"), + ConsumerChain: ChainID("consu"), + SpawnTime: 0, // launch now + InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, + TopN: 0, }, + State: State{}, }, { // we start all the validators but only "alice" and "bob" have opted in and hence @@ -1052,35 +1030,16 @@ func stepsValidatorSetCappedChain() []Step { }, }, { - Action: SubmitConsumerAdditionProposalAction{ - Chain: ChainID("provi"), - From: ValidatorID("alice"), - Deposit: 10000001, - ConsumerChain: ChainID("consu"), - SpawnTime: 0, - InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, - TopN: 0, - // we can have at most 2 validators validating the consumer chain + Action: InitializeConsumerChainAction{ + Chain: ChainID("provi"), + From: ValidatorID("alice"), + ConsumerChain: ChainID("consu"), + SpawnTime: uint(time.Minute * 10), // set spawn-time far in the future + InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, + TopN: 0, ValidatorSetCap: 2, }, - State: State{ - ChainID("provi"): ChainState{ - Proposals: &map[uint]Proposal{ - 1: ConsumerAdditionProposal{ - Deposit: 10000001, - Chain: ChainID("consu"), - SpawnTime: 0, - InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD)), - }, - }, - HasToValidate: &map[ValidatorID][]ChainID{ - ValidatorID("alice"): {}, - ValidatorID("bob"): {}, - ValidatorID("carol"): {}, - }, - }, - }, + State: State{}, }, // Οpt in "alice", "bob", and "carol." Note, that "alice" and "bob" use the provider's public key // (see `UseConsumerKey` is set to `false` in `getDefaultValidators`) and hence do not need a consumer-key assignment. @@ -1143,25 +1102,17 @@ func stepsValidatorSetCappedChain() []Step { State: State{}, }, { - Action: VoteGovProposalAction{ - Chain: ChainID("provi"), - From: []ValidatorID{ValidatorID("alice"), ValidatorID("bob")}, - Vote: []string{"yes", "yes"}, - PropNumber: 1, - }, - State: State{ - ChainID("provi"): ChainState{ - Proposals: &map[uint]Proposal{ - 1: ConsumerAdditionProposal{ - Deposit: 10000001, - Chain: ChainID("consu"), - SpawnTime: 0, - InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_PASSED)), - }, - }, - }, + // Update with SpawnTime 0 will trigger launch of consumer chain + Action: UpdateConsumerChainAction{ + Chain: ChainID("provi"), + From: ValidatorID("alice"), + ConsumerChain: ChainID("consu"), + SpawnTime: 0, // launch now + InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, + TopN: 0, + ValidatorSetCap: 2, }, + State: State{}, }, { Action: StartConsumerChainAction{ @@ -1513,38 +1464,15 @@ func stepsValidatorsAllowlistedChain() []Step { }, }, { - Action: SubmitConsumerAdditionProposalAction{ + Action: InitializeConsumerChainAction{ Chain: ChainID("provi"), From: ValidatorID("alice"), - Deposit: 10000001, ConsumerChain: ChainID("consu"), - SpawnTime: 0, + SpawnTime: uint(time.Minute * 10), // set spawn-time far in the future InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, TopN: 0, - // only "alice" and "bob" are allowlisted (see `getDefaultValidators` in `tests/e2e/config.go`) - Allowlist: []string{ - "cosmosvalcons1qmq08eruchr5sf5s3rwz7djpr5a25f7xw4mceq", - "cosmosvalcons1nx7n5uh0ztxsynn4sje6eyq2ud6rc6klc96w39", - }, - }, - State: State{ - ChainID("provi"): ChainState{ - Proposals: &map[uint]Proposal{ - 1: ConsumerAdditionProposal{ - Deposit: 10000001, - Chain: ChainID("consu"), - SpawnTime: 0, - InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD)), - }, - }, - HasToValidate: &map[ValidatorID][]ChainID{ - ValidatorID("alice"): {}, - ValidatorID("bob"): {}, - ValidatorID("carol"): {}, - }, - }, }, + State: State{}, }, // Οpt in "alice", "bob", and "carol." Note, that "alice" and "bob" use the provider's public key // (see `UseConsumerKey` is set to `false` in `getDefaultValidators`) and hence do not need a consumer-key assignment. @@ -1606,25 +1534,21 @@ func stepsValidatorsAllowlistedChain() []Step { State: State{}, }, { - Action: VoteGovProposalAction{ - Chain: ChainID("provi"), - From: []ValidatorID{ValidatorID("alice"), ValidatorID("bob")}, - Vote: []string{"yes", "yes"}, - PropNumber: 1, - }, - State: State{ - ChainID("provi"): ChainState{ - Proposals: &map[uint]Proposal{ - 1: ConsumerAdditionProposal{ - Deposit: 10000001, - Chain: ChainID("consu"), - SpawnTime: 0, - InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_PASSED)), - }, - }, + // Update with SpawnTime 0 will trigger launch of consumer chain + Action: UpdateConsumerChainAction{ + Chain: ChainID("provi"), + From: ValidatorID("alice"), + ConsumerChain: ChainID("consu"), + SpawnTime: 0, // launch now + InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, + TopN: 0, + // only "alice" and "bob" are allowlisted (see `getDefaultValidators` in `tests/e2e/config.go`) + Allowlist: []string{ + "cosmosvalcons1qmq08eruchr5sf5s3rwz7djpr5a25f7xw4mceq", + "cosmosvalcons1nx7n5uh0ztxsynn4sje6eyq2ud6rc6klc96w39", }, }, + State: State{}, }, { Action: StartConsumerChainAction{ @@ -1719,35 +1643,16 @@ func stepsValidatorsDenylistedChain() []Step { }, }, { - Action: SubmitConsumerAdditionProposalAction{ - Chain: ChainID("provi"), - From: ValidatorID("alice"), - Deposit: 10000001, - ConsumerChain: ChainID("consu"), - SpawnTime: 0, - InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, - TopN: 0, - // only "bob" is denylisted (see `getDefaultValidators` in `tests/e2e/config.go`) - Denylist: []string{"cosmosvalcons1nx7n5uh0ztxsynn4sje6eyq2ud6rc6klc96w39"}, - }, - State: State{ - ChainID("provi"): ChainState{ - Proposals: &map[uint]Proposal{ - 1: ConsumerAdditionProposal{ - Deposit: 10000001, - Chain: ChainID("consu"), - SpawnTime: 0, - InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD)), - }, - }, - HasToValidate: &map[ValidatorID][]ChainID{ - ValidatorID("alice"): {}, - ValidatorID("bob"): {}, - ValidatorID("carol"): {}, - }, - }, + Action: InitializeConsumerChainAction{ + Chain: ChainID("provi"), + From: ValidatorID("alice"), + ConsumerChain: ChainID("consu"), + SpawnTime: uint(time.Minute * 10), // set spawn-time far in the future + InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, + TopN: 0, + ValidatorSetCap: 2, }, + State: State{}, }, // Οpt in "alice", "bob", and "carol." Note, that "alice" and "bob" use the provider's public key // (see `UseConsumerKey` is set to `false` in `getDefaultValidators`) and hence do not need a consumer-key assignment. @@ -1809,25 +1714,17 @@ func stepsValidatorsDenylistedChain() []Step { State: State{}, }, { - Action: VoteGovProposalAction{ - Chain: ChainID("provi"), - From: []ValidatorID{ValidatorID("alice"), ValidatorID("bob")}, - Vote: []string{"yes", "yes"}, - PropNumber: 1, - }, - State: State{ - ChainID("provi"): ChainState{ - Proposals: &map[uint]Proposal{ - 1: ConsumerAdditionProposal{ - Deposit: 10000001, - Chain: ChainID("consu"), - SpawnTime: 0, - InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_PASSED)), - }, - }, - }, + // Update with SpawnTime 0 will trigger launch of consumer chain + Action: UpdateConsumerChainAction{ + Chain: ChainID("provi"), + From: ValidatorID("alice"), + ConsumerChain: ChainID("consu"), + SpawnTime: 0, // launch now + InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, + TopN: 0, + Denylist: []string{"cosmosvalcons1nx7n5uh0ztxsynn4sje6eyq2ud6rc6klc96w39"}, }, + State: State{}, }, { Action: StartConsumerChainAction{ @@ -1923,33 +1820,15 @@ func stepsModifyChain() []Step { }, }, { - Action: SubmitConsumerAdditionProposalAction{ + Action: InitializeConsumerChainAction{ Chain: ChainID("provi"), From: ValidatorID("alice"), - Deposit: 10000001, ConsumerChain: ChainID("consu"), - SpawnTime: 0, + SpawnTime: uint(time.Minute * 10), // set spawn-time far in the future InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, TopN: 0, }, - State: State{ - ChainID("provi"): ChainState{ - Proposals: &map[uint]Proposal{ - 1: ConsumerAdditionProposal{ - Deposit: 10000001, - Chain: ChainID("consu"), - SpawnTime: 0, - InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD)), - }, - }, - HasToValidate: &map[ValidatorID][]ChainID{ - ValidatorID("alice"): {}, - ValidatorID("bob"): {}, - ValidatorID("carol"): {}, - }, - }, - }, + State: State{}, }, // Οpt in "alice", "bob", and "carol." Note, that "alice" and "bob" use the provider's public key // (see `UseConsumerKey` is set to `false` in `getDefaultValidators`) and hence do not need a consumer-key assignment. @@ -2011,25 +1890,16 @@ func stepsModifyChain() []Step { State: State{}, }, { - Action: VoteGovProposalAction{ - Chain: ChainID("provi"), - From: []ValidatorID{ValidatorID("alice"), ValidatorID("bob"), ValidatorID("carol")}, - Vote: []string{"yes", "yes", "yes"}, - PropNumber: 1, - }, - State: State{ - ChainID("provi"): ChainState{ - Proposals: &map[uint]Proposal{ - 1: ConsumerAdditionProposal{ - Deposit: 10000001, - Chain: ChainID("consu"), - SpawnTime: 0, - InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_PASSED)), - }, - }, - }, + // Update with SpawnTime 0 will trigger launch of consumer chain + Action: UpdateConsumerChainAction{ + Chain: ChainID("provi"), + From: ValidatorID("alice"), + ConsumerChain: ChainID("consu"), + SpawnTime: 0, // launch now + InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, + TopN: 0, }, + State: State{}, }, { Action: StartConsumerChainAction{ @@ -2105,43 +1975,16 @@ func stepsModifyChain() []Step { // 1. set `ValidatorsPowerCap` to 40% { - Action: SubmitConsumerModificationProposalAction{ + Action: UpdateConsumerChainAction{ Chain: ChainID("provi"), From: ValidatorID("alice"), - Deposit: 10000001, ConsumerChain: ChainID("consu"), + SpawnTime: 0, + InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, + TopN: 0, ValidatorsPowerCap: 40, }, - State: State{ - ChainID("provi"): ChainState{ - Proposals: &map[uint]Proposal{ - 2: ConsumerModificationProposal{ - Deposit: 10000001, - Chain: ChainID("consu"), - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD)), - }, - }, - }, - }, - }, - { - Action: VoteGovProposalAction{ - Chain: ChainID("provi"), - From: []ValidatorID{ValidatorID("alice"), ValidatorID("bob"), ValidatorID("carol")}, - Vote: []string{"yes", "yes", "yes"}, - PropNumber: 2, - }, - State: State{ - ChainID("provi"): ChainState{ - Proposals: &map[uint]Proposal{ - 2: ConsumerModificationProposal{ - Deposit: 10000001, - Chain: ChainID("consu"), - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_PASSED)), - }, - }, - }, - }, + State: State{}, }, { Action: RelayPacketsAction{ @@ -2171,43 +2014,17 @@ func stepsModifyChain() []Step { // 2. set the `ValidatorSetCap` to a maximum of 2 validators { - Action: SubmitConsumerModificationProposalAction{ - Chain: ChainID("provi"), - From: ValidatorID("alice"), - Deposit: 10000001, - ConsumerChain: ChainID("consu"), - ValidatorSetCap: 2, - }, - State: State{ - ChainID("provi"): ChainState{ - Proposals: &map[uint]Proposal{ - 3: ConsumerModificationProposal{ - Deposit: 10000001, - Chain: ChainID("consu"), - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD)), - }, - }, - }, - }, - }, - { - Action: VoteGovProposalAction{ - Chain: ChainID("provi"), - From: []ValidatorID{ValidatorID("alice"), ValidatorID("bob"), ValidatorID("carol")}, - Vote: []string{"yes", "yes", "yes"}, - PropNumber: 3, - }, - State: State{ - ChainID("provi"): ChainState{ - Proposals: &map[uint]Proposal{ - 3: ConsumerModificationProposal{ - Deposit: 10000001, - Chain: ChainID("consu"), - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_PASSED)), - }, - }, - }, + Action: UpdateConsumerChainAction{ + Chain: ChainID("provi"), + From: ValidatorID("alice"), + ConsumerChain: ChainID("consu"), + SpawnTime: 0, + InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, + TopN: 0, + ValidatorsPowerCap: 40, + ValidatorSetCap: 2, }, + State: State{}, }, { Action: RelayPacketsAction{ @@ -2238,47 +2055,21 @@ func stepsModifyChain() []Step { // 3. set an allowlist with 2 validators { - Action: SubmitConsumerModificationProposalAction{ - Chain: ChainID("provi"), - From: ValidatorID("alice"), - Deposit: 10000001, - ConsumerChain: ChainID("consu"), - // only "alice" and "carol" are allowlisted (see `getDefaultValidators` in `tests/e2e/config.go`) + Action: UpdateConsumerChainAction{ + Chain: ChainID("provi"), + From: ValidatorID("alice"), + ConsumerChain: ChainID("consu"), + SpawnTime: 0, + InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, + TopN: 0, + ValidatorsPowerCap: 40, + ValidatorSetCap: 2, Allowlist: []string{ "cosmosvalcons1qmq08eruchr5sf5s3rwz7djpr5a25f7xw4mceq", "cosmosvalcons1ezyrq65s3gshhx5585w6mpusq3xsj3ayzf4uv6", }, }, - State: State{ - ChainID("provi"): ChainState{ - Proposals: &map[uint]Proposal{ - 4: ConsumerModificationProposal{ - Deposit: 10000001, - Chain: ChainID("consu"), - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD)), - }, - }, - }, - }, - }, - { - Action: VoteGovProposalAction{ - Chain: ChainID("provi"), - From: []ValidatorID{ValidatorID("alice"), ValidatorID("bob"), ValidatorID("carol")}, - Vote: []string{"yes", "yes", "yes"}, - PropNumber: 4, - }, - State: State{ - ChainID("provi"): ChainState{ - Proposals: &map[uint]Proposal{ - 4: ConsumerModificationProposal{ - Deposit: 10000001, - Chain: ChainID("consu"), - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_PASSED)), - }, - }, - }, - }, + State: State{}, }, { Action: RelayPacketsAction{ @@ -2307,44 +2098,23 @@ func stepsModifyChain() []Step { // 4. set a denylist with 1 validator { - Action: SubmitConsumerModificationProposalAction{ - Chain: ChainID("provi"), - From: ValidatorID("alice"), - Deposit: 10000001, - ConsumerChain: ChainID("consu"), + Action: UpdateConsumerChainAction{ + Chain: ChainID("provi"), + From: ValidatorID("alice"), + ConsumerChain: ChainID("consu"), + SpawnTime: 0, + InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, + TopN: 0, + ValidatorsPowerCap: 40, + ValidatorSetCap: 2, + Allowlist: []string{ + "cosmosvalcons1qmq08eruchr5sf5s3rwz7djpr5a25f7xw4mceq", + "cosmosvalcons1ezyrq65s3gshhx5585w6mpusq3xsj3ayzf4uv6", + }, // only "alice" is denylisted (see `getDefaultValidators` in `tests/e2e/config.go`) Denylist: []string{"cosmosvalcons1qmq08eruchr5sf5s3rwz7djpr5a25f7xw4mceq"}, }, - State: State{ - ChainID("provi"): ChainState{ - Proposals: &map[uint]Proposal{ - 5: ConsumerModificationProposal{ - Deposit: 10000001, - Chain: ChainID("consu"), - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD)), - }, - }, - }, - }, - }, - { - Action: VoteGovProposalAction{ - Chain: ChainID("provi"), - From: []ValidatorID{ValidatorID("alice"), ValidatorID("bob"), ValidatorID("carol")}, - Vote: []string{"yes", "yes", "yes"}, - PropNumber: 5, - }, - State: State{ - ChainID("provi"): ChainState{ - Proposals: &map[uint]Proposal{ - 5: ConsumerModificationProposal{ - Deposit: 10000001, - Chain: ChainID("consu"), - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_PASSED)), - }, - }, - }, - }, + State: State{}, }, { Action: RelayPacketsAction{ @@ -2372,45 +2142,47 @@ func stepsModifyChain() []Step { }, // 5. modify the chain from Opt In to Top 100% - { - Action: SubmitConsumerModificationProposalAction{ - Chain: ChainID("provi"), - From: ValidatorID("alice"), - Deposit: 10000001, - ConsumerChain: ChainID("consu"), - TopN: 100, - }, - State: State{ - ChainID("provi"): ChainState{ - Proposals: &map[uint]Proposal{ - 6: ConsumerModificationProposal{ - Deposit: 10000001, - Chain: ChainID("consu"), - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD)), - }, - }, - }, - }, - }, - { - Action: VoteGovProposalAction{ - Chain: ChainID("provi"), - From: []ValidatorID{ValidatorID("alice"), ValidatorID("bob"), ValidatorID("carol")}, - Vote: []string{"yes", "yes", "yes"}, - PropNumber: 6, - }, - State: State{ - ChainID("provi"): ChainState{ - Proposals: &map[uint]Proposal{ - 6: ConsumerModificationProposal{ - Deposit: 10000001, - Chain: ChainID("consu"), - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_PASSED)), - }, - }, - }, - }, - }, + // PERMISSIONLESS: Opt-In ---> TopN IS NOT SUPPORTED AT THE CURRENT STATE OF WORK !!! + /* { + Action: SubmitConsumerModificationProposalAction{ + Chain: ChainID("provi"), + From: ValidatorID("alice"), + Deposit: 10000001, + ConsumerChain: ChainID("consu"), + TopN: 100, + }, + State: State{ + ChainID("provi"): ChainState{ + Proposals: &map[uint]Proposal{ + 6: ConsumerModificationProposal{ + Deposit: 10000001, + Chain: ChainID("consu"), + Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD)), + }, + }, + }, + }, + }, + { + Action: VoteGovProposalAction{ + Chain: ChainID("provi"), + From: []ValidatorID{ValidatorID("alice"), ValidatorID("bob"), ValidatorID("carol")}, + Vote: []string{"yes", "yes", "yes"}, + PropNumber: 6, + }, + State: State{ + ChainID("provi"): ChainState{ + Proposals: &map[uint]Proposal{ + 6: ConsumerModificationProposal{ + Deposit: 10000001, + Chain: ChainID("consu"), + Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_PASSED)), + }, + }, + }, + }, + }, + */ { Action: OptOutAction{ Chain: ChainID("consu"), diff --git a/tests/e2e/test_driver.go b/tests/e2e/test_driver.go index f65ddfe6ab..a7255c2231 100644 --- a/tests/e2e/test_driver.go +++ b/tests/e2e/test_driver.go @@ -79,7 +79,7 @@ func (td *DefaultDriver) getIcsVersion(chainID ChainID) string { func (td *DefaultDriver) getTargetDriver(chainID ChainID) Chain { target := Chain{ - testConfig: td.testCfg, + testConfig: &td.testCfg, } icsVersion := td.getIcsVersion(chainID) switch icsVersion { @@ -95,7 +95,7 @@ func (td *DefaultDriver) getTargetDriver(chainID ChainID) Chain { } default: target.target = Commands{ - containerConfig: td.testCfg.containerConfig, + containerConfig: &td.testCfg.containerConfig, validatorConfigs: td.testCfg.validatorConfigs, chainConfigs: td.testCfg.chainConfigs, target: td.target, @@ -227,12 +227,16 @@ func (td *DefaultDriver) runAction(action interface{}) error { } else { target.submitChangeRewardDenomsProposal(action, td.verbose) } + case InitializeConsumerChainAction: + target.initializeConsumerChain(action, td.verbose) + case UpdateConsumerChainAction: + target.updateConsumerChain(action, td.verbose) case OptInAction: - target.optIn(action, td.target, td.verbose) + target.optIn(action, td.verbose) case OptOutAction: - target.optOut(action, td.target, td.verbose) + target.optOut(action, td.verbose) case SetConsumerCommissionRateAction: - target.setConsumerCommissionRate(action, td.target, td.verbose) + target.setConsumerCommissionRate(action, td.verbose) default: log.Fatalf("unknown action in testRun %s: %#v", td.testCfg.name, action) } diff --git a/tests/e2e/testlib/types.go b/tests/e2e/testlib/types.go index bd7996b988..8694e7185d 100644 --- a/tests/e2e/testlib/types.go +++ b/tests/e2e/testlib/types.go @@ -12,6 +12,7 @@ import ( type ( ChainID string + ConsumerID string ValidatorID string ) @@ -124,7 +125,8 @@ type ValidatorConfig struct { // Attributes that are unique to a chain. Allows us to map (part of) // the set of strings defined above to a set of viable chains type ChainConfig struct { - ChainId ChainID + ChainId ChainID + ConsumerId ConsumerID // The account prefix configured on the chain. For example, on the Hub, this is "cosmos" AccountPrefix string // Must be unique per chain diff --git a/tests/e2e/testlib/utils.go b/tests/e2e/testlib/utils.go index 08f410269f..c9d663a3f5 100644 --- a/tests/e2e/testlib/utils.go +++ b/tests/e2e/testlib/utils.go @@ -2,11 +2,60 @@ package e2e import ( "bufio" + "encoding/json" "fmt" "log" "os/exec" + + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" ) +// GovernanceProposal is used to generate content to be used for `gov submit-proposal` command +type GovernanceProposal struct { + // Msgs defines an array of sdk.Msgs proto-JSON-encoded as Anys. + Messages []json.RawMessage `json:"messages,omitempty"` + Metadata string `json:"metadata"` + Deposit string `json:"deposit"` + Title string `json:"title"` + Summary string `json:"summary"` + Expedited bool `json:"expedited"` +} + +// GenerateGovProposalContent creates proposal content ready to be used by `gov submit-proposal` command +func GenerateGovProposalContent(title, summary, metadata, deposit, description string, expedited bool, msgs ...sdk.Msg) string { + + // Register the messages. Needed for correct type annotation in the resulting json + modcodec := codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) + modcodec.InterfaceRegistry().RegisterImplementations( + (*sdk.Msg)(nil), + msgs..., + ) + + proposal := GovernanceProposal{ + Metadata: metadata, + Deposit: deposit, + Title: title, + Summary: summary, + Expedited: expedited, + } + + for _, msg := range msgs { + msgJson, err := modcodec.MarshalInterfaceJSON(msg) + if err != nil { + panic(fmt.Errorf("failed marshalling message '%v' for gov proposal: err=%s", msg, err)) + } + proposal.Messages = append(proposal.Messages, msgJson) + } + raw, err := json.MarshalIndent(proposal, "", " ") + if err != nil { + panic(fmt.Errorf("failed to marshal proposal: %w", err)) + } + + return string(raw) +} + func ExecuteCommand(cmd *exec.Cmd, cmdName string, verbose bool) { if verbose { fmt.Println(cmdName+" cmd:", cmd.String()) From 23b092945862d64ef506036a4303db3b711d4917 Mon Sep 17 00:00:00 2001 From: Bernd Mueller Date: Fri, 30 Aug 2024 09:55:33 +0200 Subject: [PATCH 2/9] cleanup --- tests/e2e/actions.go | 26 +++++++++---------- tests/e2e/steps_partial_set_security.go | 34 ++++++++++++++++++------- tests/e2e/test_driver.go | 4 +-- 3 files changed, 39 insertions(+), 25 deletions(-) diff --git a/tests/e2e/actions.go b/tests/e2e/actions.go index 17e3525cc8..ec970771a6 100644 --- a/tests/e2e/actions.go +++ b/tests/e2e/actions.go @@ -314,7 +314,7 @@ func (tr Chain) updateConsumerChain(action UpdateConsumerChainAction, verbose bo tr.UpdateConsumer(action.Chain, action.From, update) } -type InitializeConsumerChainAction struct { +type CreateConsumerChainAction struct { Chain ChainID From ValidatorID ConsumerChain ChainID @@ -330,8 +330,8 @@ type InitializeConsumerChainAction struct { AllowInactiveVals bool } -// initializeConsumerChain creates and initializes a consumer chain -func (tr Chain) initializeConsumerChain(action InitializeConsumerChainAction, verbose bool) { +// createConsumerChain creates and initializes a consumer chain +func (tr Chain) createConsumerChain(action CreateConsumerChainAction, verbose bool) { spawn_time := tr.testConfig.containerConfig.Now.Add(time.Duration(action.SpawnTime) * time.Millisecond) params := ccvtypes.DefaultParams() @@ -366,14 +366,11 @@ func (tr Chain) initializeConsumerChain(action InitializeConsumerChainAction, ve Metadata: "no metadata", } - // create consumer - consumerID := tr.CreateConsumer(action.Chain, action.ConsumerChain, action.From, metadata, &initParams, nil) - - update := types.MsgUpdateConsumer{ - ConsumerId: consumerID, - PowerShapingParameters: &powerShapingParams, + // create consumer to get a consumer-id + consumerID := tr.CreateConsumer(action.Chain, action.ConsumerChain, action.From, metadata, &initParams, &powerShapingParams) + if verbose { + fmt.Println("Create consumer chain", string(action.ConsumerChain), " with consumer-id", consumerID) } - tr.UpdateConsumer(action.Chain, action.From, update) } type SubmitConsumerAdditionProposalAction struct { @@ -458,7 +455,7 @@ func (tr Chain) CreateConsumer(providerChain, consumerChain ChainID, validator V content, err := json.Marshal(rec) if err != nil { - log.Fatalf("failed marshalling ConsumerRegistrationRecord", err.Error()) + log.Fatalf("failed marshalling ConsumerRegistrationRecord: %s", err.Error()) } jsonFile := "/create_consumer.json" bz, err := tr.target.ExecCommand( @@ -505,7 +502,7 @@ func (tr Chain) CreateConsumer(providerChain, consumerChain ChainID, validator V // TODO: introduce waitForTx tr.waitBlocks(providerChain, 2, 10*time.Second) - // Get Consumer ID from tx + // Get Consumer ID from transaction cmd = tr.target.ExecCommand( tr.testConfig.chainConfigs[providerChain].BinaryName, "query", "tx", txResponse.TxHash, @@ -545,13 +542,14 @@ func (tr Chain) CreateConsumer(providerChain, consumerChain ChainID, validator V log.Fatal("chain ", chainID, " registered already with a different consumer ID", consumer_id) } - // Set the new created consumer-id on the chain's config + // Set the new created consumer-id on the chain's config cfg.ConsumerId = e2e.ConsumerID(consumer_id) tr.testConfig.chainConfigs[e2e.ChainID(chainID)] = cfg return consumer_id } +// submitConsumerAdditionProposal initializes a consumer chain and submits a governance proposal func (tr Chain) submitConsumerAdditionProposal( action SubmitConsumerAdditionProposalAction, verbose bool, @@ -588,7 +586,7 @@ func (tr Chain) submitConsumerAdditionProposal( ConsumerId: consumer_id, NewOwnerAddress: authority, } - // For the MsgUpdateConsumer sen in the proposal + // For the MsgUpdateConsumer sent in the proposal PowerShapingParameters := types.PowerShapingParameters{ Top_N: 0, ValidatorsPowerCap: action.ValidatorsPowerCap, diff --git a/tests/e2e/steps_partial_set_security.go b/tests/e2e/steps_partial_set_security.go index 4c2a5c457c..614f093c57 100644 --- a/tests/e2e/steps_partial_set_security.go +++ b/tests/e2e/steps_partial_set_security.go @@ -42,7 +42,7 @@ func stepsOptInChain() []Step { State: State{}, }, { - Action: InitializeConsumerChainAction{ + Action: CreateConsumerChainAction{ Chain: ChainID("provi"), From: ValidatorID("alice"), ConsumerChain: ChainID("consu"), @@ -1030,7 +1030,7 @@ func stepsValidatorSetCappedChain() []Step { }, }, { - Action: InitializeConsumerChainAction{ + Action: CreateConsumerChainAction{ Chain: ChainID("provi"), From: ValidatorID("alice"), ConsumerChain: ChainID("consu"), @@ -1039,7 +1039,11 @@ func stepsValidatorSetCappedChain() []Step { TopN: 0, ValidatorSetCap: 2, }, - State: State{}, + State: State{ + ChainID("provi"): ChainState{ + ProposedConsumerChains: &[]string{"consu"}, + }, + }, }, // Οpt in "alice", "bob", and "carol." Note, that "alice" and "bob" use the provider's public key // (see `UseConsumerKey` is set to `false` in `getDefaultValidators`) and hence do not need a consumer-key assignment. @@ -1464,7 +1468,7 @@ func stepsValidatorsAllowlistedChain() []Step { }, }, { - Action: InitializeConsumerChainAction{ + Action: CreateConsumerChainAction{ Chain: ChainID("provi"), From: ValidatorID("alice"), ConsumerChain: ChainID("consu"), @@ -1472,7 +1476,11 @@ func stepsValidatorsAllowlistedChain() []Step { InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, TopN: 0, }, - State: State{}, + State: State{ + ChainID("provi"): ChainState{ + ProposedConsumerChains: &[]string{"consu"}, + }, + }, }, // Οpt in "alice", "bob", and "carol." Note, that "alice" and "bob" use the provider's public key // (see `UseConsumerKey` is set to `false` in `getDefaultValidators`) and hence do not need a consumer-key assignment. @@ -1643,7 +1651,7 @@ func stepsValidatorsDenylistedChain() []Step { }, }, { - Action: InitializeConsumerChainAction{ + Action: CreateConsumerChainAction{ Chain: ChainID("provi"), From: ValidatorID("alice"), ConsumerChain: ChainID("consu"), @@ -1652,7 +1660,11 @@ func stepsValidatorsDenylistedChain() []Step { TopN: 0, ValidatorSetCap: 2, }, - State: State{}, + State: State{ + ChainID("provi"): ChainState{ + ProposedConsumerChains: &[]string{"consu"}, + }, + }, }, // Οpt in "alice", "bob", and "carol." Note, that "alice" and "bob" use the provider's public key // (see `UseConsumerKey` is set to `false` in `getDefaultValidators`) and hence do not need a consumer-key assignment. @@ -1820,7 +1832,7 @@ func stepsModifyChain() []Step { }, }, { - Action: InitializeConsumerChainAction{ + Action: CreateConsumerChainAction{ Chain: ChainID("provi"), From: ValidatorID("alice"), ConsumerChain: ChainID("consu"), @@ -1828,7 +1840,11 @@ func stepsModifyChain() []Step { InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, TopN: 0, }, - State: State{}, + State: State{ + ChainID("provi"): ChainState{ + ProposedConsumerChains: &[]string{"consu"}, + }, + }, }, // Οpt in "alice", "bob", and "carol." Note, that "alice" and "bob" use the provider's public key // (see `UseConsumerKey` is set to `false` in `getDefaultValidators`) and hence do not need a consumer-key assignment. diff --git a/tests/e2e/test_driver.go b/tests/e2e/test_driver.go index a7255c2231..6c2bc35d77 100644 --- a/tests/e2e/test_driver.go +++ b/tests/e2e/test_driver.go @@ -227,8 +227,8 @@ func (td *DefaultDriver) runAction(action interface{}) error { } else { target.submitChangeRewardDenomsProposal(action, td.verbose) } - case InitializeConsumerChainAction: - target.initializeConsumerChain(action, td.verbose) + case CreateConsumerChainAction: + target.createConsumerChain(action, td.verbose) case UpdateConsumerChainAction: target.updateConsumerChain(action, td.verbose) case OptInAction: From 904c087a7ab26c5eb297b6107face33dbcbaf6e2 Mon Sep 17 00:00:00 2001 From: Bernd Mueller Date: Fri, 30 Aug 2024 11:13:10 +0200 Subject: [PATCH 3/9] addressed comments --- tests/e2e/actions.go | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/tests/e2e/actions.go b/tests/e2e/actions.go index ec970771a6..e6207fd771 100644 --- a/tests/e2e/actions.go +++ b/tests/e2e/actions.go @@ -262,6 +262,7 @@ type UpdateConsumerChainAction struct { Chain ChainID From ValidatorID ConsumerChain ChainID + NewOwner string SpawnTime uint InitialHeight clienttypes.Height DistributionChannel string @@ -272,18 +273,17 @@ type UpdateConsumerChainAction struct { Denylist []string MinStake uint64 AllowInactiveVals bool - NewOwner string } func (tr Chain) updateConsumerChain(action UpdateConsumerChainAction, verbose bool) { - spawn_time := tr.testConfig.containerConfig.Now.Add(time.Duration(action.SpawnTime) * time.Millisecond) + spawnTime := tr.testConfig.containerConfig.Now.Add(time.Duration(action.SpawnTime) * time.Millisecond) params := ccvtypes.DefaultParams() initParams := types.ConsumerInitializationParameters{ InitialHeight: action.InitialHeight, GenesisHash: []byte("gen_hash"), BinaryHash: []byte("bin_hash"), - SpawnTime: spawn_time, + SpawnTime: spawnTime, UnbondingPeriod: params.UnbondingPeriod, CcvTimeoutPeriod: params.CcvTimeoutPeriod, @@ -304,9 +304,9 @@ func (tr Chain) updateConsumerChain(action UpdateConsumerChainAction, verbose bo AllowInactiveVals: action.AllowInactiveVals, } - consumerID := tr.testConfig.chainConfigs[action.ConsumerChain].ConsumerId + consumerId := tr.testConfig.chainConfigs[action.ConsumerChain].ConsumerId update := types.MsgUpdateConsumer{ - ConsumerId: string(consumerID), + ConsumerId: string(consumerId), NewOwnerAddress: action.NewOwner, InitializationParameters: &initParams, PowerShapingParameters: &powerShapingParams, @@ -318,8 +318,8 @@ type CreateConsumerChainAction struct { Chain ChainID From ValidatorID ConsumerChain ChainID - SpawnTime uint InitialHeight clienttypes.Height + SpawnTime uint DistributionChannel string TopN uint32 ValidatorsPowerCap uint32 @@ -392,8 +392,6 @@ type SubmitConsumerAdditionProposalAction struct { } func (tr Chain) UpdateConsumer(providerChain ChainID, validator ValidatorID, update types.MsgUpdateConsumer) { - - fmt.Println("Update proposal for consumer_id=", update.ConsumerId) content, err := json.Marshal(update) if err != nil { log.Fatalf("failed marshalling MsgUpdate", err.Error()) @@ -420,15 +418,11 @@ func (tr Chain) UpdateConsumer(providerChain ChainID, validator ValidatorID, upd `-y`, ) - fmt.Println("Update Consumer", "cmd:", cmd.String(), "content:\n", string(content)) - bz, err = cmd.CombinedOutput() if err != nil { log.Fatal("update consumer failed ", "error: ", err, "output: ", string(bz)) } - fmt.Println("update consumer", "output", string(bz)) - // Check transaction txResponse := &TxResponse{} err = json.Unmarshal(bz, txResponse) From 72510bf0515ea3242370dd40251c9690cfb4bf7c Mon Sep 17 00:00:00 2001 From: Bernd Mueller Date: Fri, 30 Aug 2024 16:59:03 +0200 Subject: [PATCH 4/9] address more comments --- tests/e2e/actions.go | 59 ++++++++++++++++++++------------------------ tests/e2e/main.go | 19 +++----------- tests/e2e/state.go | 6 ++--- 3 files changed, 33 insertions(+), 51 deletions(-) diff --git a/tests/e2e/actions.go b/tests/e2e/actions.go index e6207fd771..657bc6c9a9 100644 --- a/tests/e2e/actions.go +++ b/tests/e2e/actions.go @@ -263,8 +263,8 @@ type UpdateConsumerChainAction struct { From ValidatorID ConsumerChain ChainID NewOwner string - SpawnTime uint InitialHeight clienttypes.Height + SpawnTime uint DistributionChannel string TopN uint32 ValidatorsPowerCap uint32 @@ -333,13 +333,13 @@ type CreateConsumerChainAction struct { // createConsumerChain creates and initializes a consumer chain func (tr Chain) createConsumerChain(action CreateConsumerChainAction, verbose bool) { - spawn_time := tr.testConfig.containerConfig.Now.Add(time.Duration(action.SpawnTime) * time.Millisecond) + spawnTime := tr.testConfig.containerConfig.Now.Add(time.Duration(action.SpawnTime) * time.Millisecond) params := ccvtypes.DefaultParams() initParams := types.ConsumerInitializationParameters{ InitialHeight: action.InitialHeight, GenesisHash: []byte("gen_hash"), BinaryHash: []byte("bin_hash"), - SpawnTime: spawn_time, + SpawnTime: spawnTime, UnbondingPeriod: params.UnbondingPeriod, CcvTimeoutPeriod: params.CcvTimeoutPeriod, @@ -367,9 +367,9 @@ func (tr Chain) createConsumerChain(action CreateConsumerChainAction, verbose bo } // create consumer to get a consumer-id - consumerID := tr.CreateConsumer(action.Chain, action.ConsumerChain, action.From, metadata, &initParams, &powerShapingParams) + consumerId := tr.CreateConsumer(action.Chain, action.ConsumerChain, action.From, metadata, &initParams, &powerShapingParams) if verbose { - fmt.Println("Create consumer chain", string(action.ConsumerChain), " with consumer-id", consumerID) + fmt.Println("Create consumer chain", string(action.ConsumerChain), " with consumer-id", string(consumerId)) } } @@ -437,19 +437,19 @@ func (tr Chain) UpdateConsumer(providerChain ChainID, validator ValidatorID, upd } // CreateConsumer creates a consumer chain and returns its consumer-id -func (tr Chain) CreateConsumer(providerChain, consumerChain ChainID, validator ValidatorID, metadata types.ConsumerMetadata, initParams *types.ConsumerInitializationParameters, powershaping *types.PowerShapingParameters) string { +func (tr Chain) CreateConsumer(providerChain, consumerChain ChainID, validator ValidatorID, metadata types.ConsumerMetadata, initParams *types.ConsumerInitializationParameters, powerShapingParams *types.PowerShapingParameters) ConsumerID { chainID := string(tr.testConfig.chainConfigs[consumerChain].ChainId) rec := types.MsgCreateConsumer{ ChainId: chainID, Metadata: metadata, InitializationParameters: initParams, - PowerShapingParameters: powershaping, + PowerShapingParameters: powerShapingParams, } content, err := json.Marshal(rec) if err != nil { - log.Fatalf("failed marshalling ConsumerRegistrationRecord: %s", err.Error()) + log.Fatalf("failed marshalling MsgCreateConsumer: %s", err.Error()) } jsonFile := "/create_consumer.json" bz, err := tr.target.ExecCommand( @@ -459,7 +459,7 @@ func (tr Chain) CreateConsumer(providerChain, consumerChain ChainID, validator V log.Fatal(err, "\n", string(bz)) } - // Send consumer chain registration + // Send consumer chain creation cmd := tr.target.ExecCommand( tr.testConfig.chainConfigs[providerChain].BinaryName, "tx", "provider", "create-consumer", jsonFile, @@ -473,20 +473,15 @@ func (tr Chain) CreateConsumer(providerChain, consumerChain ChainID, validator V `-y`, ) - fmt.Println("Create consumer", "cmd", cmd.String()) - fmt.Println("Create consumer", "json", string(content)) - bz, err = cmd.CombinedOutput() if err != nil { log.Fatal("create consumer failed ", "error: ", err, "output: ", string(bz)) } - fmt.Println("create consumer output=", string(bz)) - txResponse := &TxResponse{} err = json.Unmarshal(bz, txResponse) if err != nil { - log.Fatalf("unmarshalling tx response on consumer-registration: %s, json: %s", err.Error(), string(bz)) + log.Fatalf("unmarshalling tx response on create-consumer: %s, json: %s", err.Error(), string(bz)) } if txResponse.Code != 0 { @@ -505,26 +500,26 @@ func (tr Chain) CreateConsumer(providerChain, consumerChain ChainID, validator V ) bz, err = cmd.CombinedOutput() if err != nil { - log.Fatal("not able to query tx containing consumer registration: cmd:", cmd, "err:", err.Error(), "out:", string(bz)) + log.Fatal("not able to query tx containing creation-consumer: cmd:", cmd, "err:", err.Error(), "out:", string(bz)) } err = json.Unmarshal(bz, txResponse) if err != nil { - log.Fatalf("unmarshalling tx containing consumer registration: %s, json: %s", err.Error(), string(bz)) + log.Fatalf("unmarshalling tx containing create-consumer: %s, json: %s", err.Error(), string(bz)) } - consumer_id := "" + consumerId := "" for _, event := range txResponse.Events { if event.Type != "consumer_creation" { continue } attr, exists := event.GetAttribute("consumer_id") if !exists { - log.Fatalf("no event with consumer_id found in tx content of consumer-registration: %v", event) + log.Fatalf("no event with consumer_id found in tx content of create-consumer: %v", event) } - consumer_id = attr.Value + consumerId = attr.Value } - if consumer_id == "" { + if consumerId == "" { log.Fatalf("no consumer-id found in consumer creation transaction events for chain '%s'. events: %v", consumerChain, txResponse.Events) } @@ -532,15 +527,15 @@ func (tr Chain) CreateConsumer(providerChain, consumerChain ChainID, validator V if !exists { log.Fatal("no chain config found for consumer chain", chainID) } - if cfg.ConsumerId != "" && cfg.ConsumerId != e2e.ConsumerID(consumer_id) { - log.Fatal("chain ", chainID, " registered already with a different consumer ID", consumer_id) + if cfg.ConsumerId != "" && cfg.ConsumerId != e2e.ConsumerID(consumerId) { + log.Fatal("chain ", chainID, " registered already with a different consumer ID", consumerId) } // Set the new created consumer-id on the chain's config - cfg.ConsumerId = e2e.ConsumerID(consumer_id) + cfg.ConsumerId = e2e.ConsumerID(consumerId) tr.testConfig.chainConfigs[e2e.ChainID(chainID)] = cfg - return consumer_id + return e2e.ConsumerID(consumerId) } // submitConsumerAdditionProposal initializes a consumer chain and submits a governance proposal @@ -549,7 +544,7 @@ func (tr Chain) submitConsumerAdditionProposal( verbose bool, ) { params := ccvtypes.DefaultParams() - spawn_time := tr.testConfig.containerConfig.Now.Add(time.Duration(action.SpawnTime) * time.Millisecond) + spawnTime := tr.testConfig.containerConfig.Now.Add(time.Duration(action.SpawnTime) * time.Millisecond) Metadata := types.ConsumerMetadata{ Name: "chain " + string(action.Chain), @@ -561,7 +556,7 @@ func (tr Chain) submitConsumerAdditionProposal( InitialHeight: action.InitialHeight, GenesisHash: []byte("gen_hash"), BinaryHash: []byte("bin_hash"), - SpawnTime: spawn_time, + SpawnTime: spawnTime, UnbondingPeriod: params.UnbondingPeriod, CcvTimeoutPeriod: params.CcvTimeoutPeriod, @@ -572,12 +567,12 @@ func (tr Chain) submitConsumerAdditionProposal( DistributionTransmissionChannel: action.DistributionChannel, } - consumer_id := tr.CreateConsumer(action.Chain, action.ConsumerChain, action.From, Metadata, nil, nil) + consumerId := tr.CreateConsumer(action.Chain, action.ConsumerChain, action.From, Metadata, nil, nil) authority := "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn" // Update consumer to change owner to governance before submitting the proposal update := &types.MsgUpdateConsumer{ - ConsumerId: consumer_id, + ConsumerId: string(consumerId), NewOwnerAddress: authority, } // For the MsgUpdateConsumer sent in the proposal @@ -597,7 +592,7 @@ func (tr Chain) submitConsumerAdditionProposal( update.PowerShapingParameters.Top_N = action.TopN update.Signer = authority update.InitializationParameters = &InitializationParameters - update.InitializationParameters.SpawnTime = spawn_time + update.InitializationParameters.SpawnTime = spawnTime update.Metadata = &Metadata // Generate proposal content @@ -878,7 +873,7 @@ func (tr Chain) submitConsumerModificationProposal( verbose bool, ) { - consumerID := string(tr.testConfig.chainConfigs[action.ConsumerChain].ConsumerId) + consumerId := string(tr.testConfig.chainConfigs[action.ConsumerChain].ConsumerId) title := "Propose the modification of the PSS parameters of a chain" description := "description of the consumer modification proposal" summary := "summary of a modification proposal" @@ -889,7 +884,7 @@ func (tr Chain) submitConsumerModificationProposal( msgConsMod := types.MsgUpdateConsumer{ Signer: authority, - ConsumerId: consumerID, + ConsumerId: consumerId, PowerShapingParameters: &types.PowerShapingParameters{ Top_N: action.TopN, ValidatorsPowerCap: action.ValidatorsPowerCap, diff --git a/tests/e2e/main.go b/tests/e2e/main.go index bb8480a049..7b86bf9bb1 100644 --- a/tests/e2e/main.go +++ b/tests/e2e/main.go @@ -4,8 +4,6 @@ import ( "flag" "fmt" "log" - "log/slog" - "os" "strings" "sync" "time" @@ -248,12 +246,13 @@ var stepChoices = map[string]StepChoice{ description: "test minting without inactive validators as a sanity check", testConfig: MintTestCfg, }, - "permissionless-ics": { + // TODO PERMISSIONLESS: ADD NEW E2E TEST + /* "permissionless-ics": { name: "permissionless-ics", steps: stepsPermissionlessICS(), description: "test permissionless ics", testConfig: DefaultTestCfg, - }, + }, */ "inactive-vals-outside-max-validators": { name: "inactive-vals-outside-max-validators", steps: stepsInactiveValsTopNReproduce(), @@ -491,18 +490,6 @@ func createTestRunners(testCases []testStepsWithConfig) []TestRunner { return runners } -func SetupLogger() { - opts := &slog.HandlerOptions{ - AddSource: false, - Level: slog.LevelInfo, - } - if *verbose { - opts.Level = slog.LevelDebug - } - logger := slog.New(slog.NewTextHandler(os.Stdout, opts)) - slog.SetDefault(logger) -} - func executeTests(runners []TestRunner) error { if parallel != nil && *parallel { fmt.Println("=============== running all tests in parallel ===============") diff --git a/tests/e2e/state.go b/tests/e2e/state.go index e6cd3c0256..9f561b7fc1 100644 --- a/tests/e2e/state.go +++ b/tests/e2e/state.go @@ -473,15 +473,15 @@ func (tr Commands) GetProposal(chain ChainID, proposal uint) Proposal { case "/interchain_security.ccv.provider.v1.MsgUpdateConsumer": spawnTime := rawContent.Get("initialization_parameters.spawn_time").Time().Sub(tr.containerConfig.Now) consumerId := rawContent.Get("consumer_id").String() - consumer_chain_id := ChainID("") + consumerChainId := ChainID("") for _, chainCfg := range tr.chainConfigs { if chainCfg.ConsumerId == e2e.ConsumerID(consumerId) { - consumer_chain_id = chainCfg.ChainId + consumerChainId = chainCfg.ChainId } } return e2e.ConsumerAdditionProposal{ Deposit: uint(deposit), - Chain: consumer_chain_id, + Chain: consumerChainId, Status: status, SpawnTime: int(spawnTime.Milliseconds()), InitialHeight: clienttypes.Height{ From 0ea4988ae9100bb4bd1bbef071b386f4ed30f232 Mon Sep 17 00:00:00 2001 From: Bernd Mueller Date: Mon, 2 Sep 2024 09:25:33 +0200 Subject: [PATCH 5/9] cleanup --- tests/e2e/actions.go | 2 +- tests/e2e/main.go | 42 +++++++++++++++++++++--------------------- tests/e2e/state.go | 4 ---- 3 files changed, 22 insertions(+), 26 deletions(-) diff --git a/tests/e2e/actions.go b/tests/e2e/actions.go index 657bc6c9a9..05abc088b5 100644 --- a/tests/e2e/actions.go +++ b/tests/e2e/actions.go @@ -394,7 +394,7 @@ type SubmitConsumerAdditionProposalAction struct { func (tr Chain) UpdateConsumer(providerChain ChainID, validator ValidatorID, update types.MsgUpdateConsumer) { content, err := json.Marshal(update) if err != nil { - log.Fatalf("failed marshalling MsgUpdate", err.Error()) + log.Fatal("failed marshalling MsgUpdate: ", err.Error()) } jsonFile := "/update_consumer.json" bz, err := tr.target.ExecCommand( diff --git a/tests/e2e/main.go b/tests/e2e/main.go index 7b86bf9bb1..535ab1a283 100644 --- a/tests/e2e/main.go +++ b/tests/e2e/main.go @@ -341,27 +341,27 @@ func getTestCases(selectedPredefinedTests, selectedTestFiles TestSet, providerVe // Run default tests if no test cases were selected if len(selectedPredefinedTests) == 0 && len(selectedTestFiles) == 0 { selectedPredefinedTests = TestSet{ - "changeover", // PASSED - "happy-path", // PASSED - "democracy-reward", // PASSED - "democracy", // PASSED - "slash-throttle", // PASSED - "consumer-double-sign", // TODO PERMISSIONLESS: failing - "consumer-misbehaviour", // TODO PERMISSIONLESS: failing - "consumer-double-downtime", // PASSED - "partial-set-security-opt-in", // PASSED - "partial-set-security-top-n", // PASSED - "partial-set-security-validator-set-cap", // PASSED - "partial-set-security-validators-power-cap", // PASSED - "partial-set-security-validators-allowlisted", // PASSED - "partial-set-security-validators-denylisted", // PASSED - "partial-set-security-modification-proposal", // TODO PERMISSIONLESS: failing - "active-set-changes", // PASSED - "inactive-provider-validators-on-consumer", // PASSED - "inactive-vals-topN", // TODO PERMISSIONLESS: failing - "inactive-provider-validators-governance", // PASSED - "min-stake", // PASSED - "inactive-vals-mint", // PASSED + "changeover", + "happy-path", + "democracy-reward", + "democracy", + "slash-throttle", + "consumer-double-sign", + "consumer-misbehaviour", + "consumer-double-downtime", + "partial-set-security-opt-in", + "partial-set-security-top-n", + "partial-set-security-validator-set-cap", + "partial-set-security-validators-power-cap", + "partial-set-security-validators-allowlisted", + "partial-set-security-validators-denylisted", + "partial-set-security-modification-proposal", + "active-set-changes", + "inactive-provider-validators-on-consumer", + "inactive-vals-topN", + "inactive-provider-validators-governance", + "min-stake", + "inactive-vals-mint", } if includeMultiConsumer != nil && *includeMultiConsumer { selectedPredefinedTests = append(selectedPredefinedTests, "multiconsumer") diff --git a/tests/e2e/state.go b/tests/e2e/state.go index 9f561b7fc1..d614682bb2 100644 --- a/tests/e2e/state.go +++ b/tests/e2e/state.go @@ -441,10 +441,6 @@ func (tr Commands) GetProposal(chain ChainID, proposal uint) Proposal { log.Fatal(err, "\n", propRaw) } - messages := gjson.Get(propRaw, `proposal.messages`) - for _, msg := range messages.Array() { - fmt.Println("msg val", msg) - } // for legacy proposal types submitted using "tx submit-legacyproposal" (cosmos-sdk/v1/MsgExecLegacyContent) propType := gjson.Get(propRaw, `proposal.messages.0.value.content.type`).String() rawContent := gjson.Get(propRaw, `proposal.messages.0.value.content.value`) From c3cb9a94586fb680cc7d0658e1d283a83ca2233f Mon Sep 17 00:00:00 2001 From: Bernd Mueller Date: Mon, 2 Sep 2024 15:47:53 +0200 Subject: [PATCH 6/9] adapt PSS modify tests --- tests/e2e/actions.go | 2 +- tests/e2e/state.go | 22 ++-- tests/e2e/steps_partial_set_security.go | 143 ++++++++++++------------ tests/e2e/testlib/types.go | 10 ++ 4 files changed, 95 insertions(+), 82 deletions(-) diff --git a/tests/e2e/actions.go b/tests/e2e/actions.go index 05abc088b5..c3b4a31e55 100644 --- a/tests/e2e/actions.go +++ b/tests/e2e/actions.go @@ -394,7 +394,7 @@ type SubmitConsumerAdditionProposalAction struct { func (tr Chain) UpdateConsumer(providerChain ChainID, validator ValidatorID, update types.MsgUpdateConsumer) { content, err := json.Marshal(update) if err != nil { - log.Fatal("failed marshalling MsgUpdate: ", err.Error()) + log.Fatal("failed marshalling MsgUpdateConsumer: ", err.Error()) } jsonFile := "/update_consumer.json" bz, err := tr.target.ExecCommand( diff --git a/tests/e2e/state.go b/tests/e2e/state.go index d614682bb2..25f574a2f6 100644 --- a/tests/e2e/state.go +++ b/tests/e2e/state.go @@ -25,6 +25,7 @@ type ( Rewards = e2e.Rewards TextProposal = e2e.TextProposal UpgradeProposal = e2e.UpgradeProposal + ConsumerUpdateProposal = e2e.ConsumerUpdateProposal ConsumerAdditionProposal = e2e.ConsumerAdditionProposal ConsumerRemovalProposal = e2e.ConsumerRemovalProposal ConsumerModificationProposal = e2e.ConsumerModificationProposal @@ -467,7 +468,6 @@ func (tr Commands) GetProposal(chain ChainID, proposal uint) Proposal { Description: description, } case "/interchain_security.ccv.provider.v1.MsgUpdateConsumer": - spawnTime := rawContent.Get("initialization_parameters.spawn_time").Time().Sub(tr.containerConfig.Now) consumerId := rawContent.Get("consumer_id").String() consumerChainId := ChainID("") for _, chainCfg := range tr.chainConfigs { @@ -475,17 +475,21 @@ func (tr Commands) GetProposal(chain ChainID, proposal uint) Proposal { consumerChainId = chainCfg.ChainId } } - return e2e.ConsumerAdditionProposal{ - Deposit: uint(deposit), - Chain: consumerChainId, - Status: status, - SpawnTime: int(spawnTime.Milliseconds()), - InitialHeight: clienttypes.Height{ + + updateProposal := e2e.ConsumerUpdateProposal{ + Deposit: uint(deposit), + Chain: consumerChainId, + Status: status, + } + if rawContent.Get("initialization_parameter").Exists() { + spawnTime := rawContent.Get("initialization_parameters.spawn_time").Time().Sub(tr.containerConfig.Now) + updateProposal.SpawnTime = int(spawnTime.Milliseconds()) + updateProposal.InitialHeight = clienttypes.Height{ RevisionNumber: rawContent.Get("initialization_parameters.initial_height.revision_number").Uint(), RevisionHeight: rawContent.Get("initialization_parameters.initial_height.revision_height").Uint(), - }, + } } - + return updateProposal case "/interchain_security.ccv.provider.v1.MsgConsumerAddition": chainId := rawContent.Get("chain_id").String() spawnTime := rawContent.Get("spawn_time").Time().Sub(tr.containerConfig.Now) diff --git a/tests/e2e/steps_partial_set_security.go b/tests/e2e/steps_partial_set_security.go index 614f093c57..9638e675f5 100644 --- a/tests/e2e/steps_partial_set_security.go +++ b/tests/e2e/steps_partial_set_security.go @@ -2031,14 +2031,13 @@ func stepsModifyChain() []Step { // 2. set the `ValidatorSetCap` to a maximum of 2 validators { Action: UpdateConsumerChainAction{ - Chain: ChainID("provi"), - From: ValidatorID("alice"), - ConsumerChain: ChainID("consu"), - SpawnTime: 0, - InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, - TopN: 0, - ValidatorsPowerCap: 40, - ValidatorSetCap: 2, + Chain: ChainID("provi"), + From: ValidatorID("alice"), + ConsumerChain: ChainID("consu"), + SpawnTime: 0, + InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, + TopN: 0, + ValidatorSetCap: 2, }, State: State{}, }, @@ -2068,18 +2067,15 @@ func stepsModifyChain() []Step { }, }, }, - // 3. set an allowlist with 2 validators { Action: UpdateConsumerChainAction{ - Chain: ChainID("provi"), - From: ValidatorID("alice"), - ConsumerChain: ChainID("consu"), - SpawnTime: 0, - InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, - TopN: 0, - ValidatorsPowerCap: 40, - ValidatorSetCap: 2, + Chain: ChainID("provi"), + From: ValidatorID("alice"), + ConsumerChain: ChainID("consu"), + SpawnTime: 0, + InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, + TopN: 0, Allowlist: []string{ "cosmosvalcons1qmq08eruchr5sf5s3rwz7djpr5a25f7xw4mceq", "cosmosvalcons1ezyrq65s3gshhx5585w6mpusq3xsj3ayzf4uv6", @@ -2111,22 +2107,15 @@ func stepsModifyChain() []Step { }, }, }, - // 4. set a denylist with 1 validator { Action: UpdateConsumerChainAction{ - Chain: ChainID("provi"), - From: ValidatorID("alice"), - ConsumerChain: ChainID("consu"), - SpawnTime: 0, - InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, - TopN: 0, - ValidatorsPowerCap: 40, - ValidatorSetCap: 2, - Allowlist: []string{ - "cosmosvalcons1qmq08eruchr5sf5s3rwz7djpr5a25f7xw4mceq", - "cosmosvalcons1ezyrq65s3gshhx5585w6mpusq3xsj3ayzf4uv6", - }, + Chain: ChainID("provi"), + From: ValidatorID("alice"), + ConsumerChain: ChainID("consu"), + SpawnTime: 0, + InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, + TopN: 0, // only "alice" is denylisted (see `getDefaultValidators` in `tests/e2e/config.go`) Denylist: []string{"cosmosvalcons1qmq08eruchr5sf5s3rwz7djpr5a25f7xw4mceq"}, }, @@ -2156,49 +2145,59 @@ func stepsModifyChain() []Step { }, }, }, - // 5. modify the chain from Opt In to Top 100% - // PERMISSIONLESS: Opt-In ---> TopN IS NOT SUPPORTED AT THE CURRENT STATE OF WORK !!! - /* { - Action: SubmitConsumerModificationProposalAction{ - Chain: ChainID("provi"), - From: ValidatorID("alice"), - Deposit: 10000001, - ConsumerChain: ChainID("consu"), - TopN: 100, - }, - State: State{ - ChainID("provi"): ChainState{ - Proposals: &map[uint]Proposal{ - 6: ConsumerModificationProposal{ - Deposit: 10000001, - Chain: ChainID("consu"), - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD)), - }, - }, - }, - }, - }, - { - Action: VoteGovProposalAction{ - Chain: ChainID("provi"), - From: []ValidatorID{ValidatorID("alice"), ValidatorID("bob"), ValidatorID("carol")}, - Vote: []string{"yes", "yes", "yes"}, - PropNumber: 6, - }, - State: State{ - ChainID("provi"): ChainState{ - Proposals: &map[uint]Proposal{ - 6: ConsumerModificationProposal{ - Deposit: 10000001, - Chain: ChainID("consu"), - Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_PASSED)), - }, - }, - }, - }, - }, - */ + // -- Change the owner to governance authority + { + Action: UpdateConsumerChainAction{ + Chain: ChainID("provi"), + From: ValidatorID("alice"), + ConsumerChain: ChainID("consu"), + NewOwner: "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn", + SpawnTime: 0, + InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1}, + TopN: 0, + }, + State: State{}, + }, + { + Action: SubmitConsumerModificationProposalAction{ + Chain: ChainID("provi"), + From: ValidatorID("alice"), + Deposit: 10000001, + ConsumerChain: ChainID("consu"), + TopN: 100, + }, + State: State{ + ChainID("provi"): ChainState{ + Proposals: &map[uint]Proposal{ + 1: ConsumerUpdateProposal{ + Deposit: 10000001, + Chain: ChainID("consu"), + Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD)), + }, + }, + }, + }, + }, + { + Action: VoteGovProposalAction{ + Chain: ChainID("provi"), + From: []ValidatorID{ValidatorID("alice"), ValidatorID("bob"), ValidatorID("carol")}, + Vote: []string{"yes", "yes", "yes"}, + PropNumber: 1, + }, + State: State{ + ChainID("provi"): ChainState{ + Proposals: &map[uint]Proposal{ + 1: ConsumerUpdateProposal{ + Deposit: 10000001, + Chain: ChainID("consu"), + Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_PASSED)), + }, + }, + }, + }, + }, { Action: OptOutAction{ Chain: ChainID("consu"), diff --git a/tests/e2e/testlib/types.go b/tests/e2e/testlib/types.go index 8694e7185d..739a38f582 100644 --- a/tests/e2e/testlib/types.go +++ b/tests/e2e/testlib/types.go @@ -292,6 +292,14 @@ type ConsumerAdditionProposal struct { Status string } +type ConsumerUpdateProposal struct { + Deposit uint + Chain ChainID + SpawnTime int + InitialHeight clienttypes.Height + Status string +} + type UpgradeProposal struct { Title string Description string @@ -305,6 +313,8 @@ func (p UpgradeProposal) isProposal() {} func (p ConsumerAdditionProposal) isProposal() {} +func (p ConsumerUpdateProposal) isProposal() {} + type ConsumerRemovalProposal struct { Deposit uint Chain ChainID From bc8b6f0b8f5dc4a5fab829778a88e11d93ad96a6 Mon Sep 17 00:00:00 2001 From: Bernd Mueller Date: Mon, 2 Sep 2024 17:13:03 +0200 Subject: [PATCH 7/9] address new comments --- tests/e2e/actions.go | 47 ++++++++++++++++++++++---------------------- tests/e2e/main.go | 1 - tests/e2e/state.go | 20 ++++++++++--------- 3 files changed, 35 insertions(+), 33 deletions(-) diff --git a/tests/e2e/actions.go b/tests/e2e/actions.go index c3b4a31e55..bd6af3f604 100644 --- a/tests/e2e/actions.go +++ b/tests/e2e/actions.go @@ -305,13 +305,13 @@ func (tr Chain) updateConsumerChain(action UpdateConsumerChainAction, verbose bo } consumerId := tr.testConfig.chainConfigs[action.ConsumerChain].ConsumerId - update := types.MsgUpdateConsumer{ + msg := types.MsgUpdateConsumer{ ConsumerId: string(consumerId), NewOwnerAddress: action.NewOwner, InitializationParameters: &initParams, PowerShapingParameters: &powerShapingParams, } - tr.UpdateConsumer(action.Chain, action.From, update) + tr.UpdateConsumer(action.Chain, action.From, msg) } type CreateConsumerChainAction struct { @@ -396,7 +396,7 @@ func (tr Chain) UpdateConsumer(providerChain ChainID, validator ValidatorID, upd if err != nil { log.Fatal("failed marshalling MsgUpdateConsumer: ", err.Error()) } - jsonFile := "/update_consumer.json" + jsonFile := "/update-consumer.json" bz, err := tr.target.ExecCommand( "/bin/bash", "-c", fmt.Sprintf(`echo '%s' > %s`, content, jsonFile), ).CombinedOutput() @@ -440,18 +440,18 @@ func (tr Chain) UpdateConsumer(providerChain ChainID, validator ValidatorID, upd func (tr Chain) CreateConsumer(providerChain, consumerChain ChainID, validator ValidatorID, metadata types.ConsumerMetadata, initParams *types.ConsumerInitializationParameters, powerShapingParams *types.PowerShapingParameters) ConsumerID { chainID := string(tr.testConfig.chainConfigs[consumerChain].ChainId) - rec := types.MsgCreateConsumer{ + msg := types.MsgCreateConsumer{ ChainId: chainID, Metadata: metadata, InitializationParameters: initParams, PowerShapingParameters: powerShapingParams, } - content, err := json.Marshal(rec) + content, err := json.Marshal(msg) if err != nil { log.Fatalf("failed marshalling MsgCreateConsumer: %s", err.Error()) } - jsonFile := "/create_consumer.json" + jsonFile := "/create-consumer.json" bz, err := tr.target.ExecCommand( "/bin/bash", "-c", fmt.Sprintf(`echo '%s' > %s`, content, jsonFile), ).CombinedOutput() @@ -500,7 +500,8 @@ func (tr Chain) CreateConsumer(providerChain, consumerChain ChainID, validator V ) bz, err = cmd.CombinedOutput() if err != nil { - log.Fatal("not able to query tx containing creation-consumer: cmd:", cmd, "err:", err.Error(), "out:", string(bz)) + log.Fatalf("not able to query tx containing creation-consumer: tx: %s, err: %s, out: %s", + txResponse.TxHash, err.Error(), string(bz)) } err = json.Unmarshal(bz, txResponse) @@ -528,7 +529,7 @@ func (tr Chain) CreateConsumer(providerChain, consumerChain ChainID, validator V log.Fatal("no chain config found for consumer chain", chainID) } if cfg.ConsumerId != "" && cfg.ConsumerId != e2e.ConsumerID(consumerId) { - log.Fatal("chain ", chainID, " registered already with a different consumer ID", consumerId) + log.Fatalf("chain '%s'registered already with a different consumer ID '%s'", chainID, consumerId) } // Set the new created consumer-id on the chain's config @@ -605,7 +606,7 @@ func (tr Chain) submitConsumerAdditionProposal( jsonStr := e2e.GenerateGovProposalContent(title, summary, metadata, deposit, description, expedited, update) // #nosec G204 -- bypass unsafe quoting warning (no production code) - proposalFile := "/consumer-addition.proposal" + proposalFile := "/update-consumer-proposal.json" bz, err := tr.target.ExecCommand( "/bin/bash", "-c", fmt.Sprintf(`echo '%s' > %s`, jsonStr, proposalFile), ).CombinedOutput() @@ -749,7 +750,7 @@ func (tr Chain) submitConsumerRemovalProposal( action SubmitConsumerRemovalProposalAction, verbose bool, ) { - consumerID := string(tr.testConfig.chainConfigs[action.ConsumerChain].ConsumerId) + consumerId := string(tr.testConfig.chainConfigs[action.ConsumerChain].ConsumerId) title := fmt.Sprintf("Stop the %v chain", action.ConsumerChain) description := "stop consumer chain" summary := "It was a great chain" @@ -758,16 +759,16 @@ func (tr Chain) submitConsumerRemovalProposal( deposit := fmt.Sprintf("%dstake", action.Deposit) authority := "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn" - msgRemoveConsumer := types.MsgRemoveConsumer{ - ConsumerId: consumerID, + msg := types.MsgRemoveConsumer{ + ConsumerId: consumerId, StopTime: tr.testConfig.containerConfig.Now.Add(action.StopTimeOffset), Signer: authority, } - jsonStr := e2e.GenerateGovProposalContent(title, summary, metadata, deposit, description, expedited, &msgRemoveConsumer) + jsonStr := e2e.GenerateGovProposalContent(title, summary, metadata, deposit, description, expedited, &msg) // #nosec G204 -- bypass unsafe quoting warning (no production code) - proposalFile := "/consumer-removal.proposal" + proposalFile := "/remove-consumer-proposal.json" bz, err := tr.target.ExecCommand( "/bin/bash", "-c", fmt.Sprintf(`echo '%s' > %s`, jsonStr, proposalFile), ).CombinedOutput() @@ -882,7 +883,7 @@ func (tr Chain) submitConsumerModificationProposal( deposit := fmt.Sprintf("%dstake", action.Deposit) authority := "cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn" - msgConsMod := types.MsgUpdateConsumer{ + msg := types.MsgUpdateConsumer{ Signer: authority, ConsumerId: consumerId, PowerShapingParameters: &types.PowerShapingParameters{ @@ -894,9 +895,9 @@ func (tr Chain) submitConsumerModificationProposal( }, } - jsonStr := e2e.GenerateGovProposalContent(title, summary, metadata, deposit, description, expedited, &msgConsMod) + jsonStr := e2e.GenerateGovProposalContent(title, summary, metadata, deposit, description, expedited, &msg) // #nosec G204 -- bypass unsafe quoting warning (no production code) - proposalFile := "/consumer-mod.proposal" + proposalFile := "/update-consumer-proposal.json" bz, err := tr.target.ExecCommand( "/bin/bash", "-c", fmt.Sprintf(`echo '%s' > %s`, jsonStr, proposalFile), ).CombinedOutput() @@ -1132,7 +1133,7 @@ func (tr *Chain) startConsumerChain( func (tr *Chain) getConsumerGenesis(providerChain, consumerChain ChainID) string { fmt.Println("Exporting consumer genesis from provider") providerBinaryName := tr.testConfig.chainConfigs[providerChain].BinaryName - consumerID := string(tr.testConfig.chainConfigs[consumerChain].ConsumerId) + consumerId := string(tr.testConfig.chainConfigs[consumerChain].ConsumerId) now := time.Now() timeout := now.Add(30 * time.Second) @@ -1142,7 +1143,7 @@ func (tr *Chain) getConsumerGenesis(providerChain, consumerChain ChainID) string cmd := tr.target.ExecCommand( providerBinaryName, - "query", "provider", "consumer-genesis", consumerID, + "query", "provider", "consumer-genesis", consumerId, `--node`, tr.target.GetQueryNode(providerChain), `-o`, `json`, @@ -2490,7 +2491,7 @@ func (tr Chain) submitChangeRewardDenomsProposal(action SubmitChangeRewardDenoms jsonStr := e2e.GenerateGovProposalContent(title, summary, metadata, deposit, description, expedited, &changeRewMsg) //#nosec G204 -- bypass unsafe quoting warning (no production code) - proposalFile := "/change-rewards.proposal" + proposalFile := "/change-rewards-proposal.json" bz, err := tr.target.ExecCommand( "/bin/bash", "-c", fmt.Sprintf(`echo '%s' > %s`, jsonStr, proposalFile), ).CombinedOutput() @@ -3013,16 +3014,16 @@ func (tr Chain) setConsumerCommissionRate(action SetConsumerCommissionRateAction gas = "9000000" } - consumerID := string(tr.testConfig.chainConfigs[action.Chain].ConsumerId) + consumerId := string(tr.testConfig.chainConfigs[action.Chain].ConsumerId) if action.ConsumerID != "" { - consumerID = string(action.ConsumerID) + consumerId = string(action.ConsumerID) } // Use: "set-consumer-commission-rate [consumer-chain-id] [commission-rate]" setCommissionRate := fmt.Sprintf( `%s tx provider set-consumer-commission-rate %s %f --from validator%s --chain-id %s --home %s --node %s --gas %s --keyring-backend test -y -o json`, tr.testConfig.chainConfigs[ChainID("provi")].BinaryName, - consumerID, + consumerId, action.CommissionRate, action.Validator, tr.testConfig.chainConfigs[ChainID("provi")].ChainId, diff --git a/tests/e2e/main.go b/tests/e2e/main.go index 535ab1a283..e8ae6b2166 100644 --- a/tests/e2e/main.go +++ b/tests/e2e/main.go @@ -603,7 +603,6 @@ func main() { log.Fatalf("Error parsing command arguments %s\n", err) } - //SetupLogger() testCases := getTestCases(selectedTests, selectedTestfiles, providerVersions, consumerVersions) testRunners := createTestRunners(testCases) defer deleteTargets(testRunners) diff --git a/tests/e2e/state.go b/tests/e2e/state.go index 25f574a2f6..efc3d83569 100644 --- a/tests/e2e/state.go +++ b/tests/e2e/state.go @@ -473,6 +473,7 @@ func (tr Commands) GetProposal(chain ChainID, proposal uint) Proposal { for _, chainCfg := range tr.chainConfigs { if chainCfg.ConsumerId == e2e.ConsumerID(consumerId) { consumerChainId = chainCfg.ChainId + break } } @@ -481,7 +482,7 @@ func (tr Commands) GetProposal(chain ChainID, proposal uint) Proposal { Chain: consumerChainId, Status: status, } - if rawContent.Get("initialization_parameter").Exists() { + if rawContent.Get("initialization_parameters").Exists() { spawnTime := rawContent.Get("initialization_parameters.spawn_time").Time().Sub(tr.containerConfig.Now) updateProposal.SpawnTime = int(spawnTime.Milliseconds()) updateProposal.InitialHeight = clienttypes.Height{ @@ -524,12 +525,12 @@ func (tr Commands) GetProposal(chain ChainID, proposal uint) Proposal { Type: "/cosmos.upgrade.v1beta1.SoftwareUpgradeProposal", } case "/interchain_security.ccv.provider.v1.MsgRemoveConsumer": - consumerID := rawContent.Get("consumer_id").String() + consumerId := rawContent.Get("consumer_id").String() stopTime := rawContent.Get("stop_time").Time().Sub(tr.containerConfig.Now) var chain ChainID for i, conf := range tr.chainConfigs { - if string(conf.ConsumerId) == consumerID { + if string(conf.ConsumerId) == consumerId { chain = i break } @@ -785,11 +786,11 @@ func (tr Commands) GetConsumerChains(chain ChainID) map[ChainID]bool { func (tr Commands) GetConsumerAddress(consumerChain ChainID, validator ValidatorID) string { binaryName := tr.chainConfigs[ChainID("provi")].BinaryName - consumer_id := tr.chainConfigs[ChainID(consumerChain)].ConsumerId + consumerId := tr.chainConfigs[ChainID(consumerChain)].ConsumerId cmd := tr.target.ExecCommand(binaryName, "query", "provider", "validator-consumer-key", - string(consumer_id), tr.validatorConfigs[validator].ValconsAddress, + string(consumerId), tr.validatorConfigs[validator].ValconsAddress, `--node`, tr.GetQueryNode(ChainID("provi")), `-o`, `json`, ) @@ -804,12 +805,12 @@ func (tr Commands) GetConsumerAddress(consumerChain ChainID, validator Validator func (tr Commands) GetProviderAddressFromConsumer(consumerChain ChainID, validator ValidatorID) string { binaryName := tr.chainConfigs[ChainID("provi")].BinaryName - consumer_id := tr.chainConfigs[ChainID(consumerChain)].ConsumerId + consumerId := tr.chainConfigs[ChainID(consumerChain)].ConsumerId cmd := tr.target.ExecCommand(binaryName, "query", "provider", "validator-provider-key", - string(consumer_id), tr.validatorConfigs[validator].ConsumerValconsAddressOnProvider, + string(consumerId), tr.validatorConfigs[validator].ConsumerValconsAddressOnProvider, `--node`, tr.GetQueryNode(ChainID("provi")), `-o`, `json`, ) @@ -934,6 +935,7 @@ func (tr Commands) GetHasToValidate( for _, chain := range tr.chainConfigs { if chain.ConsumerId == ConsumerID(c.String()) { chains = append(chains, chain.ChainId) + break } } } @@ -1055,11 +1057,11 @@ func (tr Commands) GetQueryNodeIP(chain ChainID) string { // GetConsumerCommissionRate returns the commission rate of the given validator on the given consumerChain func (tr Commands) GetConsumerCommissionRate(consumerChain ChainID, validator ValidatorID) float64 { binaryName := tr.chainConfigs[ChainID("provi")].BinaryName - consumerID := tr.chainConfigs[consumerChain].ConsumerId + consumerId := tr.chainConfigs[consumerChain].ConsumerId cmd := tr.target.ExecCommand(binaryName, "query", "provider", "validator-consumer-commission-rate", - string(consumerID), tr.validatorConfigs[validator].ValconsAddress, + string(consumerId), tr.validatorConfigs[validator].ValconsAddress, `--node`, tr.GetQueryNode(ChainID("provi")), `-o`, `json`, ) From 61c853e4e036387e6899845e74b1d585a3ef107f Mon Sep 17 00:00:00 2001 From: Bernd Mueller Date: Tue, 3 Sep 2024 09:13:22 +0200 Subject: [PATCH 8/9] removed ConsumerUpdateProposal --- tests/e2e/actions.go | 4 +++- tests/e2e/config.go | 1 - tests/e2e/state.go | 3 +-- tests/e2e/steps_partial_set_security.go | 4 ++-- tests/e2e/testlib/types.go | 10 ---------- 5 files changed, 6 insertions(+), 16 deletions(-) diff --git a/tests/e2e/actions.go b/tests/e2e/actions.go index bd6af3f604..bcf36ed78e 100644 --- a/tests/e2e/actions.go +++ b/tests/e2e/actions.go @@ -433,7 +433,7 @@ func (tr Chain) UpdateConsumer(providerChain ChainID, validator ValidatorID, upd if txResponse.Code != 0 { log.Fatalf("sending update-consumer transaction failed with error code %d, Log:'%s'", txResponse.Code, txResponse.RawLog) } - tr.waitBlocks(ChainID("provi"), 2, 10*time.Second) + tr.waitBlocks(providerChain, 2, 10*time.Second) } // CreateConsumer creates a consumer chain and returns its consumer-id @@ -503,6 +503,7 @@ func (tr Chain) CreateConsumer(providerChain, consumerChain ChainID, validator V log.Fatalf("not able to query tx containing creation-consumer: tx: %s, err: %s, out: %s", txResponse.TxHash, err.Error(), string(bz)) } + fmt.Println("@@@@ created consumer chain tx=", txResponse.TxHash) err = json.Unmarshal(bz, txResponse) if err != nil { @@ -592,6 +593,7 @@ func (tr Chain) submitConsumerAdditionProposal( // - set PowerShaping params TopN > 0 for consumer chain update.PowerShapingParameters.Top_N = action.TopN update.Signer = authority + update.NewOwnerAddress = "" update.InitializationParameters = &InitializationParameters update.InitializationParameters.SpawnTime = spawnTime update.Metadata = &Metadata diff --git a/tests/e2e/config.go b/tests/e2e/config.go index ef5ed75d42..c3f8f712b1 100644 --- a/tests/e2e/config.go +++ b/tests/e2e/config.go @@ -123,7 +123,6 @@ type TestConfig struct { timeOffset time.Duration transformGenesis bool name string - Consumer2ChainID map[ConsumerID]ChainID // dynamic mapping of } // Initialize initializes the TestConfig instance by setting the runningChains field to an empty map. diff --git a/tests/e2e/state.go b/tests/e2e/state.go index efc3d83569..676d8dcfc5 100644 --- a/tests/e2e/state.go +++ b/tests/e2e/state.go @@ -25,7 +25,6 @@ type ( Rewards = e2e.Rewards TextProposal = e2e.TextProposal UpgradeProposal = e2e.UpgradeProposal - ConsumerUpdateProposal = e2e.ConsumerUpdateProposal ConsumerAdditionProposal = e2e.ConsumerAdditionProposal ConsumerRemovalProposal = e2e.ConsumerRemovalProposal ConsumerModificationProposal = e2e.ConsumerModificationProposal @@ -477,7 +476,7 @@ func (tr Commands) GetProposal(chain ChainID, proposal uint) Proposal { } } - updateProposal := e2e.ConsumerUpdateProposal{ + updateProposal := ConsumerAdditionProposal{ Deposit: uint(deposit), Chain: consumerChainId, Status: status, diff --git a/tests/e2e/steps_partial_set_security.go b/tests/e2e/steps_partial_set_security.go index 9638e675f5..156457769b 100644 --- a/tests/e2e/steps_partial_set_security.go +++ b/tests/e2e/steps_partial_set_security.go @@ -2170,7 +2170,7 @@ func stepsModifyChain() []Step { State: State{ ChainID("provi"): ChainState{ Proposals: &map[uint]Proposal{ - 1: ConsumerUpdateProposal{ + 1: ConsumerAdditionProposal{ Deposit: 10000001, Chain: ChainID("consu"), Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD)), @@ -2189,7 +2189,7 @@ func stepsModifyChain() []Step { State: State{ ChainID("provi"): ChainState{ Proposals: &map[uint]Proposal{ - 1: ConsumerUpdateProposal{ + 1: ConsumerAdditionProposal{ Deposit: 10000001, Chain: ChainID("consu"), Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_PASSED)), diff --git a/tests/e2e/testlib/types.go b/tests/e2e/testlib/types.go index 739a38f582..8694e7185d 100644 --- a/tests/e2e/testlib/types.go +++ b/tests/e2e/testlib/types.go @@ -292,14 +292,6 @@ type ConsumerAdditionProposal struct { Status string } -type ConsumerUpdateProposal struct { - Deposit uint - Chain ChainID - SpawnTime int - InitialHeight clienttypes.Height - Status string -} - type UpgradeProposal struct { Title string Description string @@ -313,8 +305,6 @@ func (p UpgradeProposal) isProposal() {} func (p ConsumerAdditionProposal) isProposal() {} -func (p ConsumerUpdateProposal) isProposal() {} - type ConsumerRemovalProposal struct { Deposit uint Chain ChainID From d10b610a2b310890846d3da63949369ee835e86b Mon Sep 17 00:00:00 2001 From: Bernd Mueller Date: Tue, 3 Sep 2024 09:58:39 +0200 Subject: [PATCH 9/9] addressed more review comments --- tests/e2e/actions.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/e2e/actions.go b/tests/e2e/actions.go index bcf36ed78e..22e1842050 100644 --- a/tests/e2e/actions.go +++ b/tests/e2e/actions.go @@ -488,7 +488,7 @@ func (tr Chain) CreateConsumer(providerChain, consumerChain ChainID, validator V log.Fatalf("sending transaction failed with error code %d, Log:'%s'", txResponse.Code, txResponse.RawLog) } - // TODO: introduce waitForTx + // TODO: introduce waitForTx (see issue #2198) tr.waitBlocks(providerChain, 2, 10*time.Second) // Get Consumer ID from transaction @@ -503,7 +503,6 @@ func (tr Chain) CreateConsumer(providerChain, consumerChain ChainID, validator V log.Fatalf("not able to query tx containing creation-consumer: tx: %s, err: %s, out: %s", txResponse.TxHash, err.Error(), string(bz)) } - fmt.Println("@@@@ created consumer chain tx=", txResponse.TxHash) err = json.Unmarshal(bz, txResponse) if err != nil { @@ -554,7 +553,7 @@ func (tr Chain) submitConsumerAdditionProposal( Metadata: "no metadata", } - InitializationParameters := types.ConsumerInitializationParameters{ + initializationParameters := types.ConsumerInitializationParameters{ InitialHeight: action.InitialHeight, GenesisHash: []byte("gen_hash"), BinaryHash: []byte("bin_hash"), @@ -578,7 +577,7 @@ func (tr Chain) submitConsumerAdditionProposal( NewOwnerAddress: authority, } // For the MsgUpdateConsumer sent in the proposal - PowerShapingParameters := types.PowerShapingParameters{ + powerShapingParameters := types.PowerShapingParameters{ Top_N: 0, ValidatorsPowerCap: action.ValidatorsPowerCap, ValidatorSetCap: action.ValidatorSetCap, @@ -587,14 +586,14 @@ func (tr Chain) submitConsumerAdditionProposal( MinStake: action.MinStake, AllowInactiveVals: action.AllowInactiveVals, } - update.PowerShapingParameters = &PowerShapingParameters + update.PowerShapingParameters = &powerShapingParameters tr.UpdateConsumer(action.Chain, action.From, *update) // - set PowerShaping params TopN > 0 for consumer chain update.PowerShapingParameters.Top_N = action.TopN update.Signer = authority update.NewOwnerAddress = "" - update.InitializationParameters = &InitializationParameters + update.InitializationParameters = &initializationParameters update.InitializationParameters.SpawnTime = spawnTime update.Metadata = &Metadata