diff --git a/tests/e2e/e2e_gov_test.go b/tests/e2e/e2e_gov_test.go new file mode 100644 index 0000000000000..23b5e52ba0670 --- /dev/null +++ b/tests/e2e/e2e_gov_test.go @@ -0,0 +1,296 @@ +package e2e + +import ( + "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" + "time" + + govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" +) + +/* +SendTokensFromNewGovAccount tests passing a gov proposal that sends tokens on behalf of the gov module to a recipient. +Test Benchmarks: +1. Subtest to fund the community pool via the distribution module +2. Submission, deposit and vote of legacy proposal to fund the gov account from the community pool +3. Validation that funds have been deposited to gov account +4. Submission, deposit and vote of message based proposal to send funds from the gov account to a recipient account +5. Validation that funds have been deposited to recipient account +*/ +func (s *IntegrationTestSuite) SendTokensFromNewGovAccount() { + s.writeGovProposals(s.chainA) + chainAAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainA.id][0].GetHostPort("1317/tcp")) + senderAddress, err := s.chainA.validators[0].keyInfo.GetAddress() + s.Require().NoError(err) + sender := senderAddress.String() + // Gov tests may be run in arbitrary order, each test must increment proposalCounter to have the correct proposal id to submit and query + proposalCounter++ + s.T().Logf("Proposal number: %d", proposalCounter) + + s.fundCommunityPool(chainAAPIEndpoint, sender) + + s.T().Logf("Submitting Legacy Gov Proposal: Community Spend Funding Gov Module") + s.submitLegacyGovProposal(chainAAPIEndpoint, sender, fees.String(), "community-pool-spend", proposalCounter, configFile("proposal.json")) + s.T().Logf("Depositing Legacy Gov Proposal: Community Spend Funding Gov Module") + s.depositGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter) + s.T().Logf("Voting Legacy Gov Proposal: Community Spend Funding Gov Module") + s.voteGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter, "yes", false) + + initialGovBalance, err := getSpecificBalance(chainAAPIEndpoint, govModuleAddress, uatomDenom) + s.Require().NoError(err) + proposalCounter++ + + s.T().Logf("Submitting Gov Proposal: Sending Tokens from Gov Module to Recipient") + s.submitNewGovProposal(chainAAPIEndpoint, sender, proposalCounter, configFile("proposal_2.json")) + s.T().Logf("Depositing Gov Proposal: Sending Tokens from Gov Module to Recipient") + s.depositGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter) + s.T().Logf("Voting Gov Proposal: Sending Tokens from Gov Module to Recipient") + s.voteGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter, "yes", false) + s.Require().Eventually( + func() bool { + newGovBalance, err := getSpecificBalance(chainAAPIEndpoint, govModuleAddress, uatomDenom) + s.Require().NoError(err) + + recipientBalance, err := getSpecificBalance(chainAAPIEndpoint, govSendMsgRecipientAddress, uatomDenom) + s.Require().NoError(err) + return newGovBalance.IsEqual(initialGovBalance.Sub(sendGovAmount)) && recipientBalance.Equal(initialGovBalance.Sub(newGovBalance)) + }, + 15*time.Second, + 5*time.Second, + ) +} + +/* +GovSoftwareUpgrade tests passing a gov proposal to upgrade the chain at a given height. +Test Benchmarks: +1. Submission, deposit and vote of message based proposal to upgrade the chain at a height (current height + buffer) +2. Validation that chain halted at upgrade height +3. Teardown & restart chains +4. Reset proposalCounter so subsequent tests have the correct last effective proposal id for chainA +TODO: Perform upgrade in place of chain restart +*/ +func (s *IntegrationTestSuite) GovSoftwareUpgrade() { + chainAAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainA.id][0].GetHostPort("1317/tcp")) + senderAddress, err := s.chainA.validators[0].keyInfo.GetAddress() + s.Require().NoError(err) + sender := senderAddress.String() + height := s.getLatestBlockHeight(s.chainA, 0) + proposalHeight := height + govProposalBlockBuffer + // Gov tests may be run in arbitrary order, each test must increment proposalCounter to have the correct proposal id to submit and query + proposalCounter++ + + s.T().Logf("Writing proposal %d on chain %s", proposalCounter, s.chainA.id) + s.writeGovUpgradeSoftwareProposal(s.chainA, proposalHeight) + + s.T().Logf("Submitting Gov Proposal: Software Upgrade") + s.submitNewGovProposal(chainAAPIEndpoint, sender, proposalCounter, configFile("proposal_3.json")) + s.T().Logf("Depositing Gov Proposal: Software Upgrade") + s.depositGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter) + s.T().Logf("Weighted Voting Gov Proposal: Software Upgrade") + s.voteGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter, "yes=0.8,no=0.1,abstain=0.05,no_with_veto=0.05", true) + + s.verifyChainHaltedAtUpgradeHeight(s.chainA, 0, proposalHeight) + s.T().Logf("Successfully halted chain at height %d", proposalHeight) + + s.TearDownSuite() + + s.T().Logf("Restarting containers") + s.SetupSuite() + + s.Require().Eventually( + func() bool { + h := s.getLatestBlockHeight(s.chainA, 0) + s.Require().NoError(err) + + return h > 0 + }, + 30*time.Second, + 5*time.Second, + ) + + proposalCounter = 0 +} + +/* +GovCancelSoftwareUpgrade tests passing a gov proposal that cancels a pending upgrade. +Test Benchmarks: +1. Submission, deposit and vote of message based proposal to upgrade the chain at a height (current height + buffer) +2. Submission, deposit and vote of message based proposal to cancel the pending upgrade +3. Validation that the chain produced blocks past the intended upgrade height +*/ +func (s *IntegrationTestSuite) GovCancelSoftwareUpgrade() { + s.T().Skip() + + chainAAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainA.id][0].GetHostPort("1317/tcp")) + senderAddress, err := s.chainA.validators[0].keyInfo.GetAddress() + s.Require().NoError(err) + sender := senderAddress.String() + height := s.getLatestBlockHeight(s.chainA, 0) + proposalHeight := height + 50 + // Gov tests may be run in arbitrary order, each test must increment proposalCounter to have the correct proposal id to submit and query + proposalCounter++ + + s.T().Logf("Writing proposal %d on chain %s", proposalCounter, s.chainA.id) + s.writeGovCancelUpgradeSoftwareProposal(s.chainA) + + s.T().Logf("Submitting Gov Proposal: Software Upgrade") + s.submitNewGovProposal(chainAAPIEndpoint, sender, proposalCounter, configFile("proposal_3.json")) + s.depositGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter) + s.voteGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter, "yes", false) + + proposalCounter++ + + s.T().Logf("Submitting Gov Proposal: Cancel Software Upgrade") + s.submitNewGovProposal(chainAAPIEndpoint, sender, proposalCounter, configFile("proposal_4.json")) + s.depositGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter) + s.voteGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter, "yes", false) + + s.verifyChainPassesUpgradeHeight(s.chainA, 0, proposalHeight) + s.T().Logf("Successfully canceled upgrade at height %d", proposalHeight) +} + +/* +fundCommunityPool tests the funding of the community pool on behalf of the distribution module. +Test Benchmarks: +1. Validation that balance of the distribution module account before funding +2. Execution funding the community pool +3. Verification that correct funds have been deposited to distribution module account +*/ +func (s *IntegrationTestSuite) fundCommunityPool(chainAAPIEndpoint, sender string) { + s.Run("fund_community_pool", func() { + beforeDistUatomBalance, _ := getSpecificBalance(chainAAPIEndpoint, distModuleAddress, tokenAmount.Denom) + if beforeDistUatomBalance.IsNil() { + // Set balance to 0 if previous balance does not exist + beforeDistUatomBalance = sdk.NewInt64Coin(uatomDenom, 0) + } + + s.execDistributionFundCommunityPool(s.chainA, 0, sender, tokenAmount.String(), fees.String()) + + // there are still tokens being added to the community pool through block production rewards but they should be less than 500 tokens + marginOfErrorForBlockReward := sdk.NewInt64Coin(uatomDenom, 500) + + s.Require().Eventually( + func() bool { + afterDistPhotonBalance, err := getSpecificBalance(chainAAPIEndpoint, distModuleAddress, tokenAmount.Denom) + s.Require().NoErrorf(err, "Error getting balance: %s", afterDistPhotonBalance) + + return afterDistPhotonBalance.Sub(beforeDistUatomBalance.Add(tokenAmount.Add(fees))).IsLT(marginOfErrorForBlockReward) + }, + 15*time.Second, + 5*time.Second, + ) + }) +} + +func (s *IntegrationTestSuite) verifyChainHaltedAtUpgradeHeight(c *chain, valIdx, upgradeHeight int) { + s.Require().Eventually( + func() bool { + currentHeight := s.getLatestBlockHeight(c, valIdx) + + return currentHeight == upgradeHeight + }, + 30*time.Second, + 5*time.Second, + ) + + counter := 0 + s.Require().Eventually( + func() bool { + currentHeight := s.getLatestBlockHeight(c, valIdx) + + if currentHeight > upgradeHeight { + return false + } + if currentHeight == upgradeHeight { + counter++ + } + return counter >= 2 + }, + 8*time.Second, + 2*time.Second, + ) +} + +func (s *IntegrationTestSuite) verifyChainPassesUpgradeHeight(c *chain, valIdx, upgradeHeight int) { + s.Require().Eventually( + func() bool { + currentHeight := s.getLatestBlockHeight(c, valIdx) + + return currentHeight > upgradeHeight + }, + 30*time.Second, + 5*time.Second, + ) +} + +func (s *IntegrationTestSuite) submitLegacyGovProposal(chainAAPIEndpoint string, sender string, fees string, proposalTypeSubCmd string, proposalId int, proposalPath string) { + s.Run("submit_legacy_gov_proposal", func() { + s.execGovSubmitLegacyGovProposal(s.chainA, 0, sender, proposalPath, fees, proposalTypeSubCmd) + + s.Require().Eventually( + func() bool { + proposal, err := queryGovProposal(chainAAPIEndpoint, proposalId) + s.Require().NoError(err) + return proposal.GetProposal().Status == govv1beta1.StatusDepositPeriod + }, + 15*time.Second, + 5*time.Second, + ) + }) +} + +func (s *IntegrationTestSuite) submitNewGovProposal(chainAAPIEndpoint, sender string, proposalId int, proposalPath string) { + s.Run("submit_new_gov_proposal", func() { + s.execGovSubmitProposal(s.chainA, 0, sender, proposalPath, fees.String()) + + s.Require().Eventually( + func() bool { + proposal, err := queryGovProposal(chainAAPIEndpoint, proposalId) + s.T().Logf("Proposal: %s", proposal.String()) + s.Require().NoError(err) + + return proposal.GetProposal().Status == govv1beta1.StatusDepositPeriod + }, + 15*time.Second, + 5*time.Second, + ) + }) +} + +func (s *IntegrationTestSuite) depositGovProposal(chainAAPIEndpoint, sender string, fees string, proposalId int) { + s.Run("deposit_gov_proposal", func() { + s.execGovDepositProposal(s.chainA, 0, sender, proposalId, depositAmount.String(), fees) + + s.Require().Eventually( + func() bool { + proposal, err := queryGovProposal(chainAAPIEndpoint, proposalId) + s.Require().NoError(err) + + return proposal.GetProposal().Status == govv1beta1.StatusVotingPeriod + }, + 15*time.Second, + 5*time.Second, + ) + }) +} + +func (s *IntegrationTestSuite) voteGovProposal(chainAAPIEndpoint, sender string, fees string, proposalId int, vote string, weighted bool) { + s.Run("vote_gov_proposal", func() { + if weighted { + s.execGovWeightedVoteProposal(s.chainA, 0, sender, proposalId, vote, fees) + } else { + s.execGovVoteProposal(s.chainA, 0, sender, proposalId, vote, fees) + } + + s.Require().Eventually( + func() bool { + proposal, err := queryGovProposal(chainAAPIEndpoint, proposalId) + s.Require().NoError(err) + + return proposal.GetProposal().Status == govv1beta1.StatusPassed + }, + 15*time.Second, + 5*time.Second, + ) + }) +} diff --git a/tests/e2e/e2e_setup_test.go b/tests/e2e/e2e_setup_test.go index 0a42e623fd56b..5a0959e1bfdd4 100644 --- a/tests/e2e/e2e_setup_test.go +++ b/tests/e2e/e2e_setup_test.go @@ -18,11 +18,14 @@ import ( "github.com/cosmos/cosmos-sdk/server" srvconfig "github.com/cosmos/cosmos-sdk/server/config" sdk "github.com/cosmos/cosmos-sdk/types" + txtypes "github.com/cosmos/cosmos-sdk/types/tx" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + gov "github.com/cosmos/cosmos-sdk/x/gov/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" "github.com/cosmos/gaia/v8/app/params" ibcclienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types" ibcchanneltypes "github.com/cosmos/ibc-go/v5/modules/core/04-channel/types" @@ -62,28 +65,16 @@ var ( fees = sdk.NewCoin(uatomDenom, math.NewInt(330000)) // 0.33uatom depositAmount = sdk.NewCoin(uatomDenom, math.NewInt(10000000)) // 10uatom distModuleAddress = authtypes.NewModuleAddress(distrtypes.ModuleName).String() - govModuleAddress = authtypes.NewModuleAddress(govtypes.ModuleName).String() + govModuleAddress = authtypes.NewModuleAddress(gov.ModuleName).String() proposalCounter = 0 sendGovAmount = sdk.NewInt64Coin(uatomDenom, 10) + fundGovAmount = sdk.NewInt64Coin(uatomDenom, 1000) + proposalSendMsg = &govtypes.MsgSubmitProposal{ + InitialDeposit: sdk.Coins{depositAmount}, + Metadata: b64.StdEncoding.EncodeToString([]byte("Testing 1, 2, 3!")), + } ) -type UpgradePlan struct { - Name string `json:"name"` - Height int `json:"height"` - Info string `json:"info"` -} - -type SoftwareUpgrade struct { - Type string `json:"@type"` - Authority string `json:"authority"` - Plan UpgradePlan `json:"plan"` -} - -type CancelSoftwareUpgrade struct { - Type string `json:"@type"` - Authority string `json:"authority"` -} - type IntegrationTestSuite struct { suite.Suite @@ -461,100 +452,70 @@ func noRestart(config *docker.HostConfig) { } func (s *IntegrationTestSuite) writeGovProposals(c *chain) { - type GovMessageSend struct { - Type string `json:"@type"` - From string `json:"from_address"` - To string `json:"to_address"` - Amount []sdk.Coin `json:"amount"` + bankSendMsg := &banktypes.MsgSend{ + FromAddress: govModuleAddress, + ToAddress: govSendMsgRecipientAddress, + Amount: []sdk.Coin{sendGovAmount}, } - msgSendMessages := []GovMessageSend{ - { - Type: "/cosmos.bank.v1beta1.MsgSend", - From: govModuleAddress, - To: govSendMsgRecipientAddress, - Amount: []sdk.Coin{sendGovAmount}, - }, - } - - msgSendBody, err := json.MarshalIndent(struct { - Messages []GovMessageSend `json:"messages"` - Metadata string `json:"metadata"` - Deposit string `json:"deposit"` - }{ - Messages: msgSendMessages, - Metadata: b64.StdEncoding.EncodeToString([]byte("Testing 1, 2, 3!")), - Deposit: "5000uatom", - }, "", " ") - + msgs := []sdk.Msg{bankSendMsg} + protoMsgs, err := txtypes.SetMsgs(msgs) + s.Require().NoError(err) + proposalSendMsg.Messages = protoMsgs + sendMsgBody, err := cdc.MarshalJSON(proposalSendMsg) s.Require().NoError(err) - legacyCommunitySpendBody, err := json.MarshalIndent(struct { - Title string `json:"title"` - Description string `json:"description"` - Recipient string `json:"recipient"` - Amount string `json:"amount"` - Deposit string `json:"deposit"` - }{ + proposalCommSpend := &distrtypes.CommunityPoolSpendProposalWithDeposit{ Title: "Community Pool Spend", Description: "Fund Gov !", Recipient: govModuleAddress, Amount: "1000uatom", Deposit: "5000uatom", - }, "", " ") - + } + commSpendBody, err := json.MarshalIndent(proposalCommSpend, "", " ") s.Require().NoError(err) for _, val := range c.validators { - err = writeFile(filepath.Join(val.configDir(), "config", "proposal.json"), legacyCommunitySpendBody) + err = writeFile(filepath.Join(val.configDir(), "config", "proposal.json"), commSpendBody) s.Require().NoError(err) - err = writeFile(filepath.Join(val.configDir(), "config", "proposal_2.json"), msgSendBody) + err = writeFile(filepath.Join(val.configDir(), "config", "proposal_2.json"), sendMsgBody) s.Require().NoError(err) } } func (s *IntegrationTestSuite) writeGovUpgradeSoftwareProposal(c *chain, height int) { - softwareUpgradeMessages := []SoftwareUpgrade{ - { - Type: "/cosmos.upgrade.v1beta1.MsgSoftwareUpgrade", - Authority: govModuleAddress, - Plan: UpgradePlan{ - Name: "upgrade-1", - Height: height, - Info: "binary-1", - }, - }, - } - cancelSoftwareUpgradeMessages := []CancelSoftwareUpgrade{ - { - Type: "/cosmos.upgrade.v1beta1.MsgCancelUpgrade", - Authority: govModuleAddress, - }, + upgradePlan := &upgradetypes.Plan{ + Name: "upgrade-1", + Height: int64(height), + Info: "binary-1", } - upgradeProposalBody, err := json.MarshalIndent(struct { - Messages []SoftwareUpgrade `json:"messages"` - Metadata string `json:"metadata"` - Deposit string `json:"deposit"` - }{ - Messages: softwareUpgradeMessages, - Metadata: b64.StdEncoding.EncodeToString([]byte("Testing 1, 2, 3!")), - Deposit: "5000uatom", - }, "", " ") + upgradeProp := &upgradetypes.MsgSoftwareUpgrade{ + Authority: govModuleAddress, + Plan: *upgradePlan, + } - cancelUpgradeProposalBody, err := json.MarshalIndent(struct { - Messages []CancelSoftwareUpgrade `json:"messages"` - Metadata string `json:"metadata"` - Deposit string `json:"deposit"` - }{ - Messages: cancelSoftwareUpgradeMessages, - Metadata: "VGVzdGluZyAxLCAyLCAzIQ==", - Deposit: "5000uatom", - }, "", " ") + msgs := []sdk.Msg{upgradeProp} + protoMsgs, err := txtypes.SetMsgs(msgs) + s.Require().NoError(err) + proposalSendMsg.Messages = protoMsgs + upgradeProposalBody, err := cdc.MarshalJSON(proposalSendMsg) + s.Require().NoError(err) err = writeFile(filepath.Join(c.validators[0].configDir(), "config", "proposal_3.json"), upgradeProposalBody) s.Require().NoError(err) +} + +func (s *IntegrationTestSuite) writeGovCancelUpgradeSoftwareProposal(c *chain) { + cancelUpgradeProp := &upgradetypes.MsgCancelUpgrade{ + Authority: govModuleAddress, + } + protoMsgs, err := txtypes.SetMsgs([]sdk.Msg{cancelUpgradeProp}) + s.Require().NoError(err) + proposalSendMsg.Messages = protoMsgs + cancelUpgradeProposalBody, err := cdc.MarshalJSON(proposalSendMsg) + s.Require().NoError(err) err = writeFile(filepath.Join(c.validators[0].configDir(), "config", "proposal_4.json"), cancelUpgradeProposalBody) s.Require().NoError(err) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index f7390ffcea4b7..9e861f907ee1c 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -9,273 +9,10 @@ import ( govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" ) -func (s *IntegrationTestSuite) TestSendTokensFromNewGovAccount() { - s.writeGovProposals(s.chainA) - chainAAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainA.id][0].GetHostPort("1317/tcp")) - senderAddress, err := s.chainA.validators[0].keyInfo.GetAddress() - s.Require().NoError(err) - sender := senderAddress.String() - proposalCounter++ - s.T().Logf("Proposal number: %d", proposalCounter) - - s.fundCommunityPool(chainAAPIEndpoint, sender) - - s.T().Logf("Submitting Legacy Gov Proposal: Community Spend Funding Gov Module") - s.submitLegacyProposalFundGovAccount(chainAAPIEndpoint, sender, proposalCounter) - s.T().Logf("Depositing Legacy Gov Proposal: Community Spend Funding Gov Module") - s.depositGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter) - s.T().Logf("Voting Legacy Gov Proposal: Community Spend Funding Gov Module") - s.voteGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter, "yes", false) - - initialGovBalance, err := getSpecificBalance(chainAAPIEndpoint, govModuleAddress, uatomDenom) - s.Require().NoError(err) - proposalCounter++ - - s.T().Logf("Submitting Gov Proposal: Sending Tokens from Gov Module to Recipient") - s.submitNewGovProposal(chainAAPIEndpoint, sender, proposalCounter, configFile("proposal_2.json")) - s.T().Logf("Depositing Gov Proposal: Sending Tokens from Gov Module to Recipient") - s.depositGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter) - s.T().Logf("Voting Gov Proposal: Sending Tokens from Gov Module to Recipient") - s.voteGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter, "yes", false) - s.Require().Eventually( - func() bool { - newGovBalance, err := getSpecificBalance(chainAAPIEndpoint, govModuleAddress, uatomDenom) - s.Require().NoError(err) - - recipientBalance, err := getSpecificBalance(chainAAPIEndpoint, govSendMsgRecipientAddress, uatomDenom) - s.Require().NoError(err) - return newGovBalance.IsEqual(initialGovBalance.Sub(sendGovAmount)) && recipientBalance.Equal(initialGovBalance.Sub(newGovBalance)) - }, - 15*time.Second, - 5*time.Second, - ) -} - -func (s *IntegrationTestSuite) TestGovSoftwareUpgrade() { - chainAAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainA.id][0].GetHostPort("1317/tcp")) - senderAddress, err := s.chainA.validators[0].keyInfo.GetAddress() - s.Require().NoError(err) - sender := senderAddress.String() - height := s.getLatestBlockHeight(s.chainA, 0) - proposalHeight := height + govProposalBlockBuffer - proposalCounter++ - - s.T().Logf("Writing proposal %d on chain %s", proposalCounter, s.chainA.id) - s.writeGovUpgradeSoftwareProposal(s.chainA, proposalHeight) - - s.T().Logf("Submitting Gov Proposal: Software Upgrade") - s.submitNewGovProposal(chainAAPIEndpoint, sender, proposalCounter, configFile("proposal_3.json")) - s.T().Logf("Depositing Gov Proposal: Software Upgrade") - s.depositGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter) - s.T().Logf("Weighted Voting Gov Proposal: Software Upgrade") - s.voteGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter, "yes=0.8,no=0.1,abstain=0.05,no_with_veto=0.05", true) - - s.verifyChainHaltedAtUpgradeHeight(s.chainA, 0, proposalHeight) - s.T().Logf("Successfully halted chain at height %d", proposalHeight) - - s.TearDownSuite() - - s.T().Logf("Restarting containers") - s.SetupSuite() - - s.Require().Eventually( - func() bool { - h := s.getLatestBlockHeight(s.chainA, 0) - s.Require().NoError(err) - - return h > 0 - }, - 30*time.Second, - 5*time.Second, - ) - - proposalCounter = 0 -} - -func (s *IntegrationTestSuite) TestGovCancelSoftwareUpgrade() { - s.T().Skip() - - chainAAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainA.id][0].GetHostPort("1317/tcp")) - senderAddress, err := s.chainA.validators[0].keyInfo.GetAddress() - s.Require().NoError(err) - sender := senderAddress.String() - height := s.getLatestBlockHeight(s.chainA, 0) - proposalHeight := height + 50 - proposalCounter++ - - s.T().Logf("Writing proposal %d on chain %s", proposalCounter, s.chainA.id) - s.writeGovUpgradeSoftwareProposal(s.chainA, proposalHeight) - - s.T().Logf("Submitting Gov Proposal: Software Upgrade") - s.submitNewGovProposal(chainAAPIEndpoint, sender, proposalCounter, configFile("proposal_3.json")) - s.depositGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter) - s.voteGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter, "yes", false) - - proposalCounter++ - - s.T().Logf("Submitting Gov Proposal: Cancel Software Upgrade") - s.submitNewGovProposal(chainAAPIEndpoint, sender, proposalCounter, configFile("proposal_4.json")) - s.depositGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter) - s.voteGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter, "yes", false) - - s.verifyChainPassesUpgradeHeight(s.chainA, 0, proposalHeight) - s.T().Logf("Successfully canceled upgrade at height %d", proposalHeight) -} - -func (s *IntegrationTestSuite) fundCommunityPool(chainAAPIEndpoint, sender string) { - s.Run("fund_community_pool", func() { - beforeDistUatomBalance, _ := getSpecificBalance(chainAAPIEndpoint, distModuleAddress, tokenAmount.Denom) - if beforeDistUatomBalance.IsNil() { - // Set balance to 0 if previous balance does not exist - beforeDistUatomBalance = sdk.NewInt64Coin(uatomDenom, 0) - } - - s.execDistributionFundCommunityPool(s.chainA, 0, sender, tokenAmount.String(), fees.String()) - - // there are still tokens being added to the community pool through block production rewards but they should be less than 500 tokens - marginOfErrorForBlockReward := sdk.NewInt64Coin(uatomDenom, 500) - - s.Require().Eventually( - func() bool { - afterDistPhotonBalance, err := getSpecificBalance(chainAAPIEndpoint, distModuleAddress, tokenAmount.Denom) - s.Require().NoErrorf(err, "Error getting balance: %s", afterDistPhotonBalance) - - return afterDistPhotonBalance.Sub(beforeDistUatomBalance.Add(tokenAmount.Add(fees))).IsLT(marginOfErrorForBlockReward) - }, - 15*time.Second, - 5*time.Second, - ) - }) -} - -func (s *IntegrationTestSuite) submitLegacyProposalFundGovAccount(chainAAPIEndpoint, sender string, proposalId int) { - s.Run("submit_legacy_community_spend_proposal_to_fund_gov_acct", func() { - s.execGovSubmitLegacyGovProposal(s.chainA, 0, sender, configFile("proposal.json"), fees.String(), "community-pool-spend") - - s.Require().Eventually( - func() bool { - proposal, err := queryGovProposal(chainAAPIEndpoint, proposalId) - s.Require().NoError(err) - - return proposal.GetProposal().Status == govv1beta1.StatusDepositPeriod - }, - 15*time.Second, - 5*time.Second, - ) - }) -} - -func (s *IntegrationTestSuite) submitLegacyGovProposal(chainAAPIEndpoint string, sender string, fees string, proposalTypeSubCmd string, proposalId int, proposalPath string) { - s.Run("submit_legacy_gov_proposal", func() { - s.execGovSubmitLegacyGovProposal(s.chainA, 0, sender, proposalPath, fees, proposalTypeSubCmd) - - s.Require().Eventually( - func() bool { - proposal, err := queryGovProposal(chainAAPIEndpoint, proposalId) - s.Require().NoError(err) - return proposal.GetProposal().Status == govv1beta1.StatusDepositPeriod - }, - 15*time.Second, - 5*time.Second, - ) - }) -} - -func (s *IntegrationTestSuite) submitNewGovProposal(chainAAPIEndpoint, sender string, proposalId int, proposalPath string) { - s.Run("submit_new_gov_proposal", func() { - s.execGovSubmitProposal(s.chainA, 0, sender, proposalPath, fees.String()) - - s.Require().Eventually( - func() bool { - proposal, err := queryGovProposal(chainAAPIEndpoint, proposalId) - s.T().Logf("Proposal: %s", proposal.String()) - s.Require().NoError(err) - - return proposal.GetProposal().Status == govv1beta1.StatusDepositPeriod - }, - 15*time.Second, - 5*time.Second, - ) - }) -} - -func (s *IntegrationTestSuite) depositGovProposal(chainAAPIEndpoint, sender string, fees string, proposalId int) { - s.Run("deposit_gov_proposal", func() { - s.execGovDepositProposal(s.chainA, 0, sender, proposalId, depositAmount.String(), fees) - - s.Require().Eventually( - func() bool { - proposal, err := queryGovProposal(chainAAPIEndpoint, proposalId) - s.Require().NoError(err) - - return proposal.GetProposal().Status == govv1beta1.StatusVotingPeriod - }, - 15*time.Second, - 5*time.Second, - ) - }) -} - -func (s *IntegrationTestSuite) voteGovProposal(chainAAPIEndpoint, sender string, fees string, proposalId int, vote string, weighted bool) { - s.Run("vote_gov_proposal", func() { - if weighted { - s.execGovWeightedVoteProposal(s.chainA, 0, sender, proposalId, vote, fees) - } else { - s.execGovVoteProposal(s.chainA, 0, sender, proposalId, vote, fees) - } - - s.Require().Eventually( - func() bool { - proposal, err := queryGovProposal(chainAAPIEndpoint, proposalId) - s.Require().NoError(err) - - return proposal.GetProposal().Status == govv1beta1.StatusPassed - }, - 15*time.Second, - 5*time.Second, - ) - }) -} - -func (s *IntegrationTestSuite) verifyChainHaltedAtUpgradeHeight(c *chain, valIdx, upgradeHeight int) { - s.Require().Eventually( - func() bool { - currentHeight := s.getLatestBlockHeight(c, valIdx) - - return currentHeight == upgradeHeight - }, - 30*time.Second, - 5*time.Second, - ) - - counter := 0 - s.Require().Eventually( - func() bool { - currentHeight := s.getLatestBlockHeight(c, valIdx) - - if currentHeight > upgradeHeight { - return false - } - if currentHeight == upgradeHeight { - counter++ - } - return counter >= 2 - }, - 8*time.Second, - 2*time.Second, - ) -} - -func (s *IntegrationTestSuite) verifyChainPassesUpgradeHeight(c *chain, valIdx, upgradeHeight int) { - s.Require().Eventually( - func() bool { - currentHeight := s.getLatestBlockHeight(c, valIdx) - - return currentHeight > upgradeHeight - }, - 30*time.Second, - 5*time.Second, - ) +func (s *IntegrationTestSuite) TestGov() { + s.SendTokensFromNewGovAccount() + s.GovSoftwareUpgrade() + s.GovCancelSoftwareUpgrade() } // globalfee in genesis is set to be "0.00001uatom"