Skip to content

Commit

Permalink
ict
Browse files Browse the repository at this point in the history
  • Loading branch information
Reecepbcups committed Oct 13, 2024
1 parent dfbd468 commit e8ebbf7
Show file tree
Hide file tree
Showing 18 changed files with 3,323 additions and 0 deletions.
58 changes: 58 additions & 0 deletions interchaintest/basic_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package e2e

import (
"context"
"testing"

"cosmossdk.io/math"

"github.com/strangelove-ventures/interchaintest/v8"
"github.com/strangelove-ventures/interchaintest/v8/chain/cosmos"
"github.com/strangelove-ventures/interchaintest/v8/testreporter"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zaptest"
)

func TestBasicChain(t *testing.T) {
ctx := context.Background()
rep := testreporter.NewNopReporter()
eRep := rep.RelayerExecReporter(t)
client, network := interchaintest.DockerSetup(t)

cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{
&DefaultChainSpec,
})

chains, err := cf.Chains(t.Name())
require.NoError(t, err)

chain := chains[0].(*cosmos.CosmosChain)

// Setup Interchain
ic := interchaintest.NewInterchain().
AddChain(chain)

require.NoError(t, ic.Build(ctx, eRep, interchaintest.InterchainBuildOptions{
TestName: t.Name(),
Client: client,
NetworkID: network,
SkipPathCreation: false,
}))
t.Cleanup(func() {
_ = ic.Close()
})

amt := math.NewInt(10_000_000)
users := interchaintest.GetAndFundTestUsers(t, ctx, "default", amt,
chain,
)
user := users[0]

t.Run("validate funding", func(t *testing.T) {
bal, err := chain.BankQueryBalance(ctx, user.FormattedAddress(), chain.Config().Denom)
require.NoError(t, err)
require.EqualValues(t, amt, bal)

})

}
178 changes: 178 additions & 0 deletions interchaintest/chain_upgrade_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
package e2e

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

sdkmath "cosmossdk.io/math"

conformance "github.com/andromedaprotocol/andromedad/interchaintest/conformance"
helpers "github.com/andromedaprotocol/andromedad/interchaintest/helpers"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
"github.com/docker/docker/client"
"github.com/strangelove-ventures/interchaintest/v8"
"github.com/strangelove-ventures/interchaintest/v8/chain/cosmos"
"github.com/strangelove-ventures/interchaintest/v8/ibc"
"github.com/strangelove-ventures/interchaintest/v8/testutil"
"github.com/stretchr/testify/require"
)

const (
chainName = "andromedad"
upgradeName = "v2"

haltHeightDelta = int64(9) // will propose upgrade this many blocks in the future
blocksAfterUpgrade = int64(7)
)

var (
// baseChain is the current version of the chain that will be upgraded from
baseChain = ibc.DockerImage{
Repository: "ghcr.io/strangelove-ventures/heighliner/andromeda",
Version: "andromeda-1-v0.1.0",
UidGid: "1025:1025",
}
)

func TestProtocolForkUpgrade(t *testing.T) {
repo, version := ChainImage.Repository, ChainImage.Version
CosmosChainUpgradeTest(t, chainName, version, repo, upgradeName)
}

func CosmosChainUpgradeTest(t *testing.T, chainName, upgradeBranchVersion, upgradeRepo, upgradeName string) {
if testing.Short() {
t.Skip("skipping in short mode")
}

t.Parallel()

t.Log(chainName, upgradeBranchVersion, upgradeRepo, upgradeName)

previousVersionGenesis := []cosmos.GenesisKV{
{
Key: "app_state.gov.params.voting_period",
Value: VotingPeriod,
},
{
Key: "app_state.gov.params.max_deposit_period",
Value: MaxDepositPeriod,
},
{
Key: "app_state.gov.params.min_deposit.0.denom",
Value: Denom,
},
}

cfg := DefaultChainConfig
cfg.ModifyGenesis = cosmos.ModifyGenesis(previousVersionGenesis)
cfg.Images = []ibc.DockerImage{baseChain}

numVals, numNodes := 2, 0
chains := interchaintest.CreateChainWithConfig(t, numVals, numNodes, baseChain.Repository, baseChain.Version, cfg)
chain := chains[0].(*cosmos.CosmosChain)

ctx, ic, client, _ := interchaintest.BuildInitialChain(t, chains, false)

t.Cleanup(func() {
_ = ic.Close()
})

userFunds := sdkmath.NewInt(10_000_000_000)
users := interchaintest.GetAndFundTestUsers(t, ctx, t.Name(), userFunds, chain)
chainUser := users[0]

// execute a contract before the upgrade
beforeContract := conformance.StdExecute(t, ctx, chain, chainUser, "0"+chain.Config().Denom)
fmt.Println("beforeContract", beforeContract)

// upgrade
height, err := chain.Height(ctx)
require.NoError(t, err, "error fetching height before submit upgrade proposal")

haltHeight := height + haltHeightDelta
proposalID := SubmitUpgradeProposal(t, ctx, chain, chainUser, upgradeName, haltHeight)

proposalIDInt, err := strconv.ParseInt(proposalID, 10, 64)
require.NoError(t, err, "failed to parse proposal ID")

ValidatorVoting(t, ctx, chain, proposalIDInt, height, haltHeight)

UpgradeNodes(t, ctx, chain, client, haltHeight, upgradeRepo, upgradeBranchVersion)

// confirm we can execute against the beforeContract (validates wasmvm .wasm files are in the correct place before and after.)
helpers.ExecuteMsgWithFee(t, ctx, chain, chainUser, beforeContract, "", "10000"+chain.Config().Denom, `{"increment":{}}`)

// Post Upgrade: Conformance Validation
conformance.CosmWasm(t, ctx, chain, chainUser, "10000"+chain.Config().Denom)
}

func UpgradeNodes(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, client *client.Client, haltHeight int64, upgradeRepo, upgradeBranchVersion string) {
// bring down nodes to prepare for upgrade
t.Log("stopping node(s)")
err := chain.StopAllNodes(ctx)
require.NoError(t, err, "error stopping node(s)")

// upgrade version on all nodes
t.Log("upgrading node(s)")
chain.UpgradeVersion(ctx, client, upgradeRepo, upgradeBranchVersion)

// start all nodes back up.
// validators reach consensus on first block after upgrade height
// and chain block production resumes.
t.Log("starting node(s)")
err = chain.StartAllNodes(ctx)
require.NoError(t, err, "error starting upgraded node(s)")

timeoutCtx, timeoutCtxCancel := context.WithTimeout(ctx, time.Second*60)
defer timeoutCtxCancel()

err = testutil.WaitForBlocks(timeoutCtx, int(blocksAfterUpgrade), chain)
require.NoError(t, err, "chain did not produce blocks after upgrade")

height, err := chain.Height(ctx)
require.NoError(t, err, "error fetching height after upgrade")

require.GreaterOrEqual(t, height, haltHeight+blocksAfterUpgrade, "height did not increment enough after upgrade")
}

func ValidatorVoting(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, proposalID int64, height int64, haltHeight int64) {
err := chain.VoteOnProposalAllValidators(ctx, uint64(proposalID), cosmos.ProposalVoteYes)
require.NoError(t, err, "failed to submit votes")

_, err = cosmos.PollForProposalStatus(ctx, chain, height, height+(haltHeightDelta*2), uint64(proposalID), govtypes.StatusPassed)
require.NoError(t, err, "proposal status did not change to passed in expected number of blocks")

timeoutCtx, timeoutCtxCancel := context.WithTimeout(ctx, time.Second*45)
defer timeoutCtxCancel()

height, err = chain.Height(ctx)
require.NoError(t, err, "error fetching height before upgrade")

// this should timeout due to chain halt at upgrade height.
_ = testutil.WaitForBlocks(timeoutCtx, int(haltHeight-height), chain)
time.Sleep(3 * time.Second) // extra buffer

// TODO: the following can be flakey some times with +/- 1 block in timing.
// height, err = chain.Height(ctx)
// require.NoError(t, err, "error fetching height after chain should have halted")
// make sure that chain is halted
// require.Equal(t, haltHeight, height, "height is not equal to halt height")
}

func SubmitUpgradeProposal(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet, upgradeName string, haltHeight int64) string {
proposal := cosmos.SoftwareUpgradeProposal{
Deposit: "500000000" + chain.Config().Denom, // greater than min deposit
Title: "Chain Upgrade 1",
Name: upgradeName,
Description: "First chain software upgrade",
Height: haltHeight,
}

upgradeTx, err := chain.UpgradeProposal(ctx, user.KeyName(), proposal)
require.NoError(t, err, "error submitting software upgrade proposal tx")

return upgradeTx.ProposalID
}
63 changes: 63 additions & 0 deletions interchaintest/conformance/wasm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package ictconformance

import (
"context"
"fmt"
"testing"

"github.com/andromedaprotocol/andromedad/interchaintest/helpers"
"github.com/strangelove-ventures/interchaintest/v8/chain/cosmos"
"github.com/strangelove-ventures/interchaintest/v8/ibc"
"github.com/stretchr/testify/require"

wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types"
)

// ConformanceCosmWasm validates that store, instantiate, execute, and query work on a CosmWasm contract.
func CosmWasm(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet, fees string) {
// new contracts should execute without issue
StdExecute(t, ctx, chain, user, fees)
// verify sub messages pass from contract to contract (can break if using a wasm decorator incorrectly)
subMsg(t, ctx, chain, user)
}

func StdExecute(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet, fees string) (contractAddr string) {
_, contractAddr = helpers.SetupContract(t, ctx, chain, user.KeyName(), "contracts/cw_template.wasm", `{"count":0}`)
helpers.ExecuteMsgWithFee(t, ctx, chain, user, contractAddr, "", fees, `{"increment":{}}`)

var res helpers.GetCountResponse
err := helpers.SmartQueryString(t, ctx, chain, contractAddr, `{"get_count":{}}`, &res)
require.NoError(t, err)
require.Equal(t, int64(1), res.Data.Count)

return contractAddr
}

func subMsg(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet) {
// ref: https://github.com/CosmWasm/wasmd/issues/1735

// === execute a contract sub message ===
_, senderContractAddr := helpers.SetupContract(t, ctx, chain, user.KeyName(), "contracts/cw721_base.wasm.gz", fmt.Sprintf(`{"name":"Reece #00001", "symbol":"reece-test-#00001", "minter":"%s"}`, user.FormattedAddress()))
_, receiverContractAddr := helpers.SetupContract(t, ctx, chain, user.KeyName(), "contracts/cw721_receiver.wasm.gz", `{}`)

// mint a token
res, err := helpers.ExecuteMsgWithFeeReturn(t, ctx, chain, user, senderContractAddr, "", "10000"+chain.Config().Denom, fmt.Sprintf(`{"mint":{"token_id":"00000", "owner":"%s"}}`, user.FormattedAddress()))
fmt.Println("First", res)
require.NoError(t, err)

// this purposely will fail with the current, we are just validating the messsage is not unknown.
// sub message of unknown means the `wasmkeeper.WithMessageHandlerDecorator` is not setup properly.
fail := "ImZhaWwi"
res2, err := helpers.ExecuteMsgWithFeeReturn(t, ctx, chain, user, senderContractAddr, "", "10000"+chain.Config().Denom, fmt.Sprintf(`{"send_nft": { "contract": "%s", "token_id": "00000", "msg": "%s" }}`, receiverContractAddr, fail))
require.NoError(t, err)
fmt.Println("Second", res2)
require.NotEqualValues(t, wasmtypes.ErrUnknownMsg.ABCICode(), res2.Code)
require.NotContains(t, res2.RawLog, "unknown message from the contract")

success := "InN1Y2NlZWQi"
res3, err := helpers.ExecuteMsgWithFeeReturn(t, ctx, chain, user, senderContractAddr, "", "10000"+chain.Config().Denom, fmt.Sprintf(`{"send_nft": { "contract": "%s", "token_id": "00000", "msg": "%s" }}`, receiverContractAddr, success))
require.NoError(t, err)
fmt.Println("Third", res3)
require.EqualValues(t, 0, res3.Code)
require.NotContains(t, res3.RawLog, "unknown message from the contract")
}
14 changes: 14 additions & 0 deletions interchaintest/contracts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Contracts

A list of the contracts here which are pre-compiled in other repos.

> cw_template -> `cargo generate --git https://github.com/CosmWasm/cw-template.git --name cwtemplate -d minimal=false --tag 9ef93954d62f383468bb1ec869fef894be53bc4d`
cw_template uses an older version so cosmwasm_1_3 feature is not required (breaks upgrade test since old v1.1.0-beta1 version did not have it. Same concept though)

> ibchooks_counter.wasm -> <https://github.com/osmosis-labs/osmosis/blob/64393a14e18b2562d72a3892eec716197a3716c7/tests/ibc-hooks/bytecode/counter.wasm>
SubMessage test
> cw721_base - https://github.com/CosmWasm/cw-nfts/releases/download/v0.17.0/cw721_base.wasm
> cw721-receiver - https://github.com/CosmWasm/cw-nfts/pull/144
Binary file added interchaintest/contracts/cw721_base.wasm.gz
Binary file not shown.
Binary file added interchaintest/contracts/cw721_receiver.wasm.gz
Binary file not shown.
Binary file added interchaintest/contracts/cw_template.wasm
Binary file not shown.
Binary file added interchaintest/contracts/ibchooks_counter.wasm
Binary file not shown.
Loading

0 comments on commit e8ebbf7

Please sign in to comment.