From 13027ccfafa267be015f4da52006212801e167f3 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Wed, 6 Apr 2022 02:46:29 +0000 Subject: [PATCH 01/12] second chain with tests --- tests/e2e/chain.go | 5 +-- tests/e2e/e2e_setup_test.go | 77 +++++++++++++++++++++++++++---------- tests/e2e/e2e_test.go | 42 +++++++++++++------- 3 files changed, 87 insertions(+), 37 deletions(-) diff --git a/tests/e2e/chain.go b/tests/e2e/chain.go index a5ce93561ad..24cea7e9f3b 100644 --- a/tests/e2e/chain.go +++ b/tests/e2e/chain.go @@ -10,7 +10,6 @@ import ( cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - tmrand "github.com/tendermint/tendermint/libs/rand" osmosisApp "github.com/osmosis-labs/osmosis/v7/app" "github.com/osmosis-labs/osmosis/v7/app/params" @@ -48,14 +47,14 @@ type chain struct { validators []*validator } -func newChain() (*chain, error) { +func newChain(name string) (*chain, error) { tmpDir, err := ioutil.TempDir("", "osmosis-e2e-testnet-") if err != nil { return nil, err } return &chain{ - id: "chain-" + tmrand.NewRand().Str(6), + id: name, dataDir: tmpDir, }, nil } diff --git a/tests/e2e/e2e_setup_test.go b/tests/e2e/e2e_setup_test.go index f88d265e073..f31208ae978 100644 --- a/tests/e2e/e2e_setup_test.go +++ b/tests/e2e/e2e_setup_test.go @@ -26,25 +26,37 @@ import ( ) const ( - osmoBalance = 200000000000 - osmoDenom = "uosmo" - stakeBalance = 110000000000 - stakeAmount = 100000000000 - stakeDenom = "stake" - minGasPrice = "0.00001" + // common + osmoDenom = "uosmo" + stakeDenom = "stake" + minGasPrice = "0.00001" + // chainA + chainAName = "osmo-test-a" + osmoBalanceA = 200000000000 + stakeBalanceA = 110000000000 + stakeAmountA = 100000000000 + // chainB + chainBName = "osmo-test-b" + osmoBalanceB = 500000000000 + stakeBalanceB = 440000000000 + stakeAmountB = 400000000000 ) var ( - initBalanceStr = fmt.Sprintf("%d%s,%d%s", osmoBalance, osmoDenom, stakeBalance, stakeDenom) - stakeAmountInt, _ = sdk.NewIntFromString(fmt.Sprintf("%d", stakeAmount)) - stakeAmountCoin = sdk.NewCoin(stakeDenom, stakeAmountInt) + initBalanceStrA = fmt.Sprintf("%d%s,%d%s", osmoBalanceA, osmoDenom, stakeBalanceA, stakeDenom) + initBalanceStrB = fmt.Sprintf("%d%s,%d%s", osmoBalanceB, osmoDenom, stakeBalanceB, stakeDenom) + stakeAmountIntA, _ = sdk.NewIntFromString(fmt.Sprintf("%d", stakeAmountA)) + stakeAmountCoinA = sdk.NewCoin(stakeDenom, stakeAmountIntA) + stakeAmountIntB, _ = sdk.NewIntFromString(fmt.Sprintf("%d", stakeAmountB)) + stakeAmountCoinB = sdk.NewCoin(stakeDenom, stakeAmountIntB) ) type IntegrationTestSuite struct { suite.Suite tmpDirs []string - chain *chain + chainA *chain + chainB *chain dkrPool *dockertest.Pool dkrNet *dockertest.Network valResources map[string][]*dockertest.Resource @@ -58,13 +70,16 @@ func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up e2e integration test suite...") var err error - s.chain, err = newChain() + s.chainA, err = newChain(chainAName) + s.Require().NoError(err) + + s.chainB, err = newChain(chainBName) s.Require().NoError(err) s.dkrPool, err = dockertest.NewPool("") s.Require().NoError(err) - s.dkrNet, err = s.dkrPool.CreateNetwork(fmt.Sprintf("%s-testnet", s.chain.id)) + s.dkrNet, err = s.dkrPool.CreateNetwork(fmt.Sprintf("%s-%s-testnet", s.chainA.id, s.chainB.id)) s.Require().NoError(err) s.valResources = make(map[string][]*dockertest.Resource) @@ -74,11 +89,17 @@ func (s *IntegrationTestSuite) SetupSuite() { // 1. Initialize Osmosis validator nodes. // 2. Create and initialize Osmosis validator genesis files (one chain) - s.T().Logf("starting e2e infrastructure for chain A; chain-id: %s; datadir: %s", s.chain.id, s.chain.dataDir) - s.initNodes(s.chain) - s.initGenesis(s.chain) - s.initValidatorConfigs(s.chain) - s.runValidators(s.chain, 0) + s.T().Logf("starting e2e infrastructure for chain A; chain-id: %s; datadir: %s", s.chainA.id, s.chainA.dataDir) + s.initNodes(s.chainA) + s.initGenesis(s.chainA) + s.initValidatorConfigs(s.chainA) + s.runValidators(s.chainA, 0) + + s.T().Logf("starting e2e infrastructure for chain B; chain-id: %s; datadir: %s", s.chainB.id, s.chainB.dataDir) + s.initNodes(s.chainB) + s.initGenesis(s.chainB) + s.initValidatorConfigs(s.chainB) + s.runValidators(s.chainB, 10) } func (s *IntegrationTestSuite) TearDownSuite() { @@ -101,7 +122,8 @@ func (s *IntegrationTestSuite) TearDownSuite() { s.Require().NoError(s.dkrPool.RemoveNetwork(s.dkrNet)) - os.RemoveAll(s.chain.dataDir) + os.RemoveAll(s.chainA.dataDir) + os.RemoveAll(s.chainB.dataDir) for _, td := range s.tmpDirs { os.RemoveAll(td) @@ -114,9 +136,15 @@ func (s *IntegrationTestSuite) initNodes(c *chain) { // initialize a genesis file for the first validator val0ConfigDir := c.validators[0].configDir() for _, val := range c.validators { - s.Require().NoError( - addGenesisAccount(val0ConfigDir, "", initBalanceStr, val.keyInfo.GetAddress()), - ) + if c.id == chainAName { + s.Require().NoError( + addGenesisAccount(val0ConfigDir, "", initBalanceStrA, val.keyInfo.GetAddress()), + ) + } else if c.id == chainBName { + s.Require().NoError( + addGenesisAccount(val0ConfigDir, "", initBalanceStrB, val.keyInfo.GetAddress()), + ) + } } // copy the genesis file to the remaining validators @@ -167,6 +195,13 @@ func (s *IntegrationTestSuite) initGenesis(c *chain) { // generate genesis txs genTxs := make([]json.RawMessage, len(c.validators)) for i, val := range c.validators { + stakeAmountCoin := stakeAmountCoinA + if c.id == chainAName { + stakeAmountCoin = stakeAmountCoinA + + } else { + stakeAmountCoin = stakeAmountCoinB + } createValmsg, err := val.buildCreateValidatorMsg(stakeAmountCoin) s.Require().NoError(err) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 5495a4efecd..77432ee1805 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -13,26 +13,42 @@ import ( func (s *IntegrationTestSuite) TestQueryBalances() { var ( - expectedDenoms = []string{osmoDenom, stakeDenom} - expectedBalances = []uint64{osmoBalance, stakeBalance - stakeAmount} + expectedDenoms = []string{osmoDenom, stakeDenom} + expectedBalancesA = []uint64{osmoBalanceA, stakeBalanceA - stakeAmountA} + expectedBalancesB = []uint64{osmoBalanceB, stakeBalanceB - stakeAmountB} ) - chainAAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chain.id][0].GetHostPort("1317/tcp")) - balances, err := queryBalances(chainAAPIEndpoint, s.chain.validators[0].keyInfo.GetAddress().String()) + chainAAPIEndpointA := fmt.Sprintf("http://%s", s.valResources[s.chainA.id][0].GetHostPort("1317/tcp")) + balancesA, err := queryBalances(chainAAPIEndpointA, s.chainA.validators[0].keyInfo.GetAddress().String()) s.Require().NoError(err) - s.Require().NotNil(balances) - s.Require().Equal(2, len(balances)) + s.Require().NotNil(balancesA) + s.Require().Equal(2, len(balancesA)) - actualDenoms := make([]string, 0, 2) - actualBalances := make([]uint64, 0, 2) + chainAAPIEndpointB := fmt.Sprintf("http://%s", s.valResources[s.chainB.id][0].GetHostPort("1317/tcp")) + balancesB, err := queryBalances(chainAAPIEndpointB, s.chainB.validators[0].keyInfo.GetAddress().String()) + s.Require().NoError(err) + s.Require().NotNil(balancesB) + s.Require().Equal(2, len(balancesB)) + + actualDenomsA := make([]string, 0, 2) + actualBalancesA := make([]uint64, 0, 2) + actualDenomsB := make([]string, 0, 2) + actualBalancesB := make([]uint64, 0, 2) + + for _, balanceA := range balancesA { + actualDenomsA = append(actualDenomsA, balanceA.GetDenom()) + actualBalancesA = append(actualBalancesA, balanceA.Amount.Uint64()) + } - for _, balance := range balances { - actualDenoms = append(actualDenoms, balance.GetDenom()) - actualBalances = append(actualBalances, balance.Amount.Uint64()) + for _, balanceB := range balancesB { + actualDenomsB = append(actualDenomsB, balanceB.GetDenom()) + actualBalancesB = append(actualBalancesB, balanceB.Amount.Uint64()) } - s.Require().ElementsMatch(expectedDenoms, actualDenoms) - s.Require().ElementsMatch(expectedBalances, actualBalances) + s.Require().ElementsMatch(expectedDenoms, actualDenomsA) + s.Require().ElementsMatch(expectedBalancesA, actualBalancesA) + s.Require().ElementsMatch(expectedDenoms, actualDenomsB) + s.Require().ElementsMatch(expectedBalancesB, actualBalancesB) } func queryBalances(endpoint, addr string) (sdk.Coins, error) { From e1d35e9da6eb11c063e97fa1da039f1fce049041 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Wed, 6 Apr 2022 16:47:57 +0000 Subject: [PATCH 02/12] add hermes, comment out balance query for now --- Makefile | 5 + tests/e2e/docker/hermes.Dockerfile | 12 ++ tests/e2e/e2e_setup_test.go | 109 ++++++++++++++- tests/e2e/e2e_test.go | 120 +++++++++++------ tests/e2e/e2e_util_test.go | 185 ++++++++++++++++++++++++++ tests/e2e/scripts/hermes_bootstrap.sh | 72 ++++++++++ 6 files changed, 457 insertions(+), 46 deletions(-) create mode 100644 tests/e2e/docker/hermes.Dockerfile create mode 100644 tests/e2e/e2e_util_test.go create mode 100644 tests/e2e/scripts/hermes_bootstrap.sh diff --git a/Makefile b/Makefile index 146688b64f4..3131f26b94d 100644 --- a/Makefile +++ b/Makefile @@ -230,6 +230,11 @@ benchmark: docker-build-debug: @docker build -t cosmos/osmosisd-e2e --build-arg IMG_TAG=debug -f e2e.Dockerfile . +# TODO: Push this to the Cosmos Dockerhub so we don't have to keep building it +# in CI. +docker-build-hermes: + @cd tests/e2e/docker; docker build -t cosmos/hermes-e2e:latest -f hermes.Dockerfile . + ############################################################################### ### Linting ### ############################################################################### diff --git a/tests/e2e/docker/hermes.Dockerfile b/tests/e2e/docker/hermes.Dockerfile new file mode 100644 index 00000000000..6478b8466de --- /dev/null +++ b/tests/e2e/docker/hermes.Dockerfile @@ -0,0 +1,12 @@ +FROM informalsystems/hermes:0.12.0 AS hermes-builder + +FROM debian:buster-slim +USER root + +COPY --chown=0:0 --from=hermes-builder /usr/lib/x86_64-linux-gnu/libssl.so.1.1 /usr/lib/x86_64-linux-gnu/libssl.so.1.1 +COPY --chown=0:0 --from=hermes-builder /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 +COPY --from=hermes-builder /usr/bin/hermes /usr/local/bin/ +RUN chmod +x /usr/local/bin/hermes + +EXPOSE 3031 +ENTRYPOINT ["hermes", "start"] \ No newline at end of file diff --git a/tests/e2e/e2e_setup_test.go b/tests/e2e/e2e_setup_test.go index f31208ae978..e1cfcba198b 100644 --- a/tests/e2e/e2e_setup_test.go +++ b/tests/e2e/e2e_setup_test.go @@ -4,7 +4,11 @@ import ( "context" "encoding/json" "fmt" + "io" + "io/ioutil" + "net/http" "os" + "path" "path/filepath" "strconv" "strings" @@ -54,12 +58,13 @@ var ( type IntegrationTestSuite struct { suite.Suite - tmpDirs []string - chainA *chain - chainB *chain - dkrPool *dockertest.Pool - dkrNet *dockertest.Network - valResources map[string][]*dockertest.Resource + tmpDirs []string + chainA *chain + chainB *chain + dkrPool *dockertest.Pool + dkrNet *dockertest.Network + hermesResource *dockertest.Resource + valResources map[string][]*dockertest.Resource } func TestIntegrationTestSuite(t *testing.T) { @@ -100,6 +105,8 @@ func (s *IntegrationTestSuite) SetupSuite() { s.initGenesis(s.chainB) s.initValidatorConfigs(s.chainB) s.runValidators(s.chainB, 10) + + s.runIBCRelayer() } func (s *IntegrationTestSuite) TearDownSuite() { @@ -114,6 +121,8 @@ func (s *IntegrationTestSuite) TearDownSuite() { s.T().Log("tearing down e2e integration test suite...") + s.Require().NoError(s.dkrPool.Purge(s.hermesResource)) + for _, vr := range s.valResources { for _, r := range vr { s.Require().NoError(s.dkrPool.Purge(r)) @@ -342,6 +351,94 @@ func (s *IntegrationTestSuite) runValidators(c *chain, portOffset int) { ) } +func (s *IntegrationTestSuite) runIBCRelayer() { + s.T().Log("starting Hermes relayer container...") + + tmpDir, err := ioutil.TempDir("", "gaia-e2e-testnet-hermes-") + s.Require().NoError(err) + s.tmpDirs = append(s.tmpDirs, tmpDir) + + gaiaAVal := s.chainA.validators[0] + gaiaBVal := s.chainB.validators[0] + hermesCfgPath := path.Join(tmpDir, "hermes") + + s.Require().NoError(os.MkdirAll(hermesCfgPath, 0755)) + _, err = copyFile( + filepath.Join("./scripts/", "hermes_bootstrap.sh"), + filepath.Join(hermesCfgPath, "hermes_bootstrap.sh"), + ) + s.Require().NoError(err) + + s.hermesResource, err = s.dkrPool.RunWithOptions( + &dockertest.RunOptions{ + Name: fmt.Sprintf("%s-%s-relayer", s.chainA.id, s.chainB.id), + Repository: "ghcr.io/cosmos/hermes-e2e", + Tag: "latest", + NetworkID: s.dkrNet.Network.ID, + Mounts: []string{ + fmt.Sprintf("%s/:/root/hermes", hermesCfgPath), + }, + PortBindings: map[docker.Port][]docker.PortBinding{ + "3031/tcp": {{HostIP: "", HostPort: "3031"}}, + }, + Env: []string{ + fmt.Sprintf("GAIA_A_E2E_CHAIN_ID=%s", s.chainA.id), + fmt.Sprintf("GAIA_B_E2E_CHAIN_ID=%s", s.chainB.id), + fmt.Sprintf("GAIA_A_E2E_VAL_MNEMONIC=%s", gaiaAVal.mnemonic), + fmt.Sprintf("GAIA_B_E2E_VAL_MNEMONIC=%s", gaiaBVal.mnemonic), + fmt.Sprintf("GAIA_A_E2E_VAL_HOST=%s", s.valResources[s.chainA.id][0].Container.Name[1:]), + fmt.Sprintf("GAIA_B_E2E_VAL_HOST=%s", s.valResources[s.chainB.id][0].Container.Name[1:]), + }, + Entrypoint: []string{ + "sh", + "-c", + "chmod +x /root/hermes/hermes_bootstrap.sh && /root/hermes/hermes_bootstrap.sh", + }, + }, + noRestart, + ) + s.Require().NoError(err) + + endpoint := fmt.Sprintf("http://%s/state", s.hermesResource.GetHostPort("3031/tcp")) + s.Require().Eventually( + func() bool { + resp, err := http.Get(endpoint) + if err != nil { + return false + } + + defer resp.Body.Close() + + bz, err := io.ReadAll(resp.Body) + if err != nil { + return false + } + + var respBody map[string]interface{} + if err := json.Unmarshal(bz, &respBody); err != nil { + return false + } + + status := respBody["status"].(string) + result := respBody["result"].(map[string]interface{}) + + return status == "success" && len(result["chains"].([]interface{})) == 2 + }, + 5*time.Minute, + time.Second, + "hermes relayer not healthy", + ) + + s.T().Logf("started Hermes relayer container: %s", s.hermesResource.Container.ID) + + // XXX: Give time to both networks to start, otherwise we might see gRPC + // transport errors. + time.Sleep(10 * time.Second) + + // create the client, connection and channel between the two Gaia chains + s.connectIBCChains() +} + func noRestart(config *docker.HostConfig) { // in this case we don't want the nodes to restart on failure config.RestartPolicy = docker.RestartPolicy{ diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 77432ee1805..eff185f601e 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -5,58 +5,60 @@ import ( "fmt" "io" "net/http" + "strings" "time" sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) -func (s *IntegrationTestSuite) TestQueryBalances() { - var ( - expectedDenoms = []string{osmoDenom, stakeDenom} - expectedBalancesA = []uint64{osmoBalanceA, stakeBalanceA - stakeAmountA} - expectedBalancesB = []uint64{osmoBalanceB, stakeBalanceB - stakeAmountB} - ) - - chainAAPIEndpointA := fmt.Sprintf("http://%s", s.valResources[s.chainA.id][0].GetHostPort("1317/tcp")) - balancesA, err := queryBalances(chainAAPIEndpointA, s.chainA.validators[0].keyInfo.GetAddress().String()) - s.Require().NoError(err) - s.Require().NotNil(balancesA) - s.Require().Equal(2, len(balancesA)) - - chainAAPIEndpointB := fmt.Sprintf("http://%s", s.valResources[s.chainB.id][0].GetHostPort("1317/tcp")) - balancesB, err := queryBalances(chainAAPIEndpointB, s.chainB.validators[0].keyInfo.GetAddress().String()) - s.Require().NoError(err) - s.Require().NotNil(balancesB) - s.Require().Equal(2, len(balancesB)) - - actualDenomsA := make([]string, 0, 2) - actualBalancesA := make([]uint64, 0, 2) - actualDenomsB := make([]string, 0, 2) - actualBalancesB := make([]uint64, 0, 2) - - for _, balanceA := range balancesA { - actualDenomsA = append(actualDenomsA, balanceA.GetDenom()) - actualBalancesA = append(actualBalancesA, balanceA.Amount.Uint64()) - } - - for _, balanceB := range balancesB { - actualDenomsB = append(actualDenomsB, balanceB.GetDenom()) - actualBalancesB = append(actualBalancesB, balanceB.Amount.Uint64()) - } - - s.Require().ElementsMatch(expectedDenoms, actualDenomsA) - s.Require().ElementsMatch(expectedBalancesA, actualBalancesA) - s.Require().ElementsMatch(expectedDenoms, actualDenomsB) - s.Require().ElementsMatch(expectedBalancesB, actualBalancesB) -} +// func (s *IntegrationTestSuite) TestQueryBalances() { +// var ( +// expectedDenoms = []string{osmoDenom, stakeDenom} +// expectedBalancesA = []uint64{osmoBalanceA, stakeBalanceA - stakeAmountA} +// expectedBalancesB = []uint64{osmoBalanceB, stakeBalanceB - stakeAmountB} +// ) + +// chainAAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainA.id][0].GetHostPort("1317/tcp")) +// balancesA, err := queryBalances(chainAAPIEndpoint, s.chainA.validators[0].keyInfo.GetAddress().String()) +// s.Require().NoError(err) +// s.Require().NotNil(balancesA) +// // s.Require().Equal(2, len(balancesA)) + +// chainBAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainB.id][0].GetHostPort("1317/tcp")) +// balancesB, err := queryBalances(chainBAPIEndpoint, s.chainB.validators[0].keyInfo.GetAddress().String()) +// s.Require().NoError(err) +// s.Require().NotNil(balancesB) +// // s.Require().Equal(2, len(balancesB)) + +// actualDenomsA := make([]string, 0, 2) +// actualBalancesA := make([]uint64, 0, 2) +// actualDenomsB := make([]string, 0, 2) +// actualBalancesB := make([]uint64, 0, 2) + +// for _, balanceA := range balancesA { +// actualDenomsA = append(actualDenomsA, balanceA.GetDenom()) +// actualBalancesA = append(actualBalancesA, balanceA.Amount.Uint64()) +// } + +// for _, balanceB := range balancesB { +// actualDenomsB = append(actualDenomsB, balanceB.GetDenom()) +// actualBalancesB = append(actualBalancesB, balanceB.Amount.Uint64()) +// } + +// s.Require().ElementsMatch(expectedDenoms, actualDenomsA) +// s.Require().ElementsMatch(expectedBalancesA, actualBalancesA) +// s.Require().ElementsMatch(expectedDenoms, actualDenomsB) +// s.Require().ElementsMatch(expectedBalancesB, actualBalancesB) +// } func queryBalances(endpoint, addr string) (sdk.Coins, error) { path := fmt.Sprintf( "%s/cosmos/bank/v1beta1/balances/%s", endpoint, addr, ) - resp, err := http.Get(path) + var err error + var resp *http.Response retriesLeft := 5 for { resp, err = http.Get(path) @@ -90,3 +92,41 @@ func queryBalances(endpoint, addr string) (sdk.Coins, error) { return balancesResp.GetBalances(), nil } + +func (s *IntegrationTestSuite) TestIBCTokenTransfer() { + var ibcStakeDenom string + + s.Run("send_uosmo_to_chainB", func() { + recipient := s.chainB.validators[0].keyInfo.GetAddress().String() + token := sdk.NewInt64Coin(osmoDenom, 3300000000) // 3,300uosmo + s.sendIBC(s.chainA.id, s.chainB.id, recipient, token) + + chainBAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainB.id][0].GetHostPort("1317/tcp")) + + // require the recipient account receives the IBC tokens (IBC packets ACKd) + var ( + balances sdk.Coins + err error + ) + s.Require().Eventually( + func() bool { + balances, err = queryBalances(chainBAPIEndpoint, recipient) + s.Require().NoError(err) + + return balances.Len() == 3 + }, + time.Minute, + 5*time.Second, + ) + + for _, c := range balances { + if strings.Contains(c.Denom, "ibc/") { + ibcStakeDenom = c.Denom + s.Require().Equal(token.Amount.Int64(), c.Amount.Int64()) + break + } + } + + s.Require().NotEmpty(ibcStakeDenom) + }) +} diff --git a/tests/e2e/e2e_util_test.go b/tests/e2e/e2e_util_test.go new file mode 100644 index 00000000000..ab6e8371e8c --- /dev/null +++ b/tests/e2e/e2e_util_test.go @@ -0,0 +1,185 @@ +package e2e + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/ory/dockertest/v3/docker" +) + +func (s *IntegrationTestSuite) connectIBCChains() { + s.T().Logf("connecting %s and %s chains via IBC", s.chainA.id, s.chainB.id) + + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + exec, err := s.dkrPool.Client.CreateExec(docker.CreateExecOptions{ + Context: ctx, + AttachStdout: true, + AttachStderr: true, + Container: s.hermesResource.Container.ID, + User: "root", + Cmd: []string{ + "hermes", + "create", + "channel", + s.chainA.id, + s.chainB.id, + "--port-a=transfer", + "--port-b=transfer", + }, + }) + s.Require().NoError(err) + + var ( + outBuf bytes.Buffer + errBuf bytes.Buffer + ) + + err = s.dkrPool.Client.StartExec(exec.ID, docker.StartExecOptions{ + Context: ctx, + Detach: false, + OutputStream: &outBuf, + ErrorStream: &errBuf, + }) + s.Require().NoErrorf( + err, + "failed connect chains; stdout: %s, stderr: %s", outBuf.String(), errBuf.String(), + ) + + s.Require().Containsf( + errBuf.String(), + "successfully opened init channel", + "failed to connect chains via IBC: %s", errBuf.String(), + ) + + s.T().Logf("connected %s and %s chains via IBC", s.chainA.id, s.chainB.id) +} + +func (s *IntegrationTestSuite) sendIBC(srcChainID, dstChainID, recipient string, token sdk.Coin) { + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + s.T().Logf("sending %s from %s to %s (%s)", token, srcChainID, dstChainID, recipient) + + exec, err := s.dkrPool.Client.CreateExec(docker.CreateExecOptions{ + Context: ctx, + AttachStdout: true, + AttachStderr: true, + Container: s.hermesResource.Container.ID, + User: "root", + Cmd: []string{ + "hermes", + "tx", + "raw", + "ft-transfer", + dstChainID, + srcChainID, + "transfer", // source chain port ID + "channel-0", // since only one connection/channel exists, assume 0 + token.Amount.String(), + fmt.Sprintf("--denom=%s", token.Denom), + fmt.Sprintf("--receiver=%s", recipient), + "--timeout-height-offset=1000", + }, + }) + s.Require().NoError(err) + + var ( + outBuf bytes.Buffer + errBuf bytes.Buffer + ) + + err = s.dkrPool.Client.StartExec(exec.ID, docker.StartExecOptions{ + Context: ctx, + Detach: false, + OutputStream: &outBuf, + ErrorStream: &errBuf, + }) + s.Require().NoErrorf( + err, + "failed to send IBC tokens; stdout: %s, stderr: %s", outBuf.String(), errBuf.String(), + ) + + s.T().Log("successfully sent IBC tokens") +} + +func queryGaiaTx(endpoint, txHash string) error { + resp, err := http.Get(fmt.Sprintf("%s/cosmos/tx/v1beta1/txs/%s", endpoint, txHash)) + if err != nil { + return fmt.Errorf("failed to execute HTTP request: %w", err) + } + + defer resp.Body.Close() + + if resp.StatusCode != 200 { + return fmt.Errorf("tx query returned non-200 status: %d", resp.StatusCode) + } + + var result map[string]interface{} + if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { + return fmt.Errorf("failed to read response body: %w", err) + } + + txResp := result["tx_response"].(map[string]interface{}) + if v := txResp["code"]; v.(float64) != 0 { + return fmt.Errorf("tx %s failed with status code %v", txHash, v) + } + + return nil +} + +func queryGaiaAllBalances(endpoint, addr string) (sdk.Coins, error) { + resp, err := http.Get(fmt.Sprintf("%s/cosmos/bank/v1beta1/balances/%s", endpoint, addr)) + if err != nil { + return nil, fmt.Errorf("failed to execute HTTP request: %w", err) + } + + defer resp.Body.Close() + + bz, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + var balancesResp banktypes.QueryAllBalancesResponse + if err := cdc.UnmarshalJSON(bz, &balancesResp); err != nil { + return nil, err + } + + return balancesResp.Balances, nil +} + +func queryGaiaDenomBalance(endpoint, addr, denom string) (sdk.Coin, error) { + var zeroCoin sdk.Coin + + path := fmt.Sprintf( + "%s/cosmos/bank/v1beta1/balances/%s/by_denom?denom=%s", + endpoint, addr, denom, + ) + resp, err := http.Get(path) + if err != nil { + return zeroCoin, fmt.Errorf("failed to execute HTTP request: %w", err) + } + + defer resp.Body.Close() + + bz, err := io.ReadAll(resp.Body) + if err != nil { + return zeroCoin, err + } + + var balanceResp banktypes.QueryBalanceResponse + if err := cdc.UnmarshalJSON(bz, &balanceResp); err != nil { + return zeroCoin, err + } + + return *balanceResp.Balance, nil +} diff --git a/tests/e2e/scripts/hermes_bootstrap.sh b/tests/e2e/scripts/hermes_bootstrap.sh new file mode 100644 index 00000000000..d1da5599bc2 --- /dev/null +++ b/tests/e2e/scripts/hermes_bootstrap.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +set -ex + +# initialize Hermes relayer configuration +mkdir -p /root/.hermes/ +touch /root/.hermes/config.toml + +# setup Hermes relayer configuration +tee /root/.hermes/config.toml < Date: Thu, 7 Apr 2022 16:34:00 +0000 Subject: [PATCH 03/12] eventually --- tests/e2e/chain.go | 4 ++-- tests/e2e/e2e_setup_test.go | 26 +++++++++++++------------- tests/e2e/e2e_test.go | 3 +-- tests/e2e/e2e_util_test.go | 6 +++--- tests/e2e/scripts/hermes_bootstrap.sh | 20 ++++++++++---------- 5 files changed, 29 insertions(+), 30 deletions(-) diff --git a/tests/e2e/chain.go b/tests/e2e/chain.go index 24cea7e9f3b..a5eadfe4230 100644 --- a/tests/e2e/chain.go +++ b/tests/e2e/chain.go @@ -47,14 +47,14 @@ type chain struct { validators []*validator } -func newChain(name string) (*chain, error) { +func newChain(id string) (*chain, error) { tmpDir, err := ioutil.TempDir("", "osmosis-e2e-testnet-") if err != nil { return nil, err } return &chain{ - id: name, + id: id, dataDir: tmpDir, }, nil } diff --git a/tests/e2e/e2e_setup_test.go b/tests/e2e/e2e_setup_test.go index 26b0a406d30..a2f969cb475 100644 --- a/tests/e2e/e2e_setup_test.go +++ b/tests/e2e/e2e_setup_test.go @@ -35,12 +35,12 @@ const ( stakeDenom = "stake" minGasPrice = "0.00001" // chainA - chainAName = "osmo-test-a" + chainAID = "osmo-test-a" osmoBalanceA = 200000000000 stakeBalanceA = 110000000000 stakeAmountA = 100000000000 // chainB - chainBName = "osmo-test-b" + chainBID = "osmo-test-b" osmoBalanceB = 500000000000 stakeBalanceB = 440000000000 stakeAmountB = 400000000000 @@ -75,10 +75,10 @@ func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up e2e integration test suite...") var err error - s.chainA, err = newChain(chainAName) + s.chainA, err = newChain(chainAID) s.Require().NoError(err) - s.chainB, err = newChain(chainBName) + s.chainB, err = newChain(chainBID) s.Require().NoError(err) s.dkrPool, err = dockertest.NewPool("") @@ -146,11 +146,11 @@ func (s *IntegrationTestSuite) initNodes(c *chain) { // initialize a genesis file for the first validator val0ConfigDir := c.validators[0].configDir() for _, val := range c.validators { - if c.id == chainAName { + if c.id == chainAID { s.Require().NoError( addGenesisAccount(val0ConfigDir, "", initBalanceStrA, val.keyInfo.GetAddress()), ) - } else if c.id == chainBName { + } else if c.id == chainBID { s.Require().NoError( addGenesisAccount(val0ConfigDir, "", initBalanceStrB, val.keyInfo.GetAddress()), ) @@ -206,7 +206,7 @@ func (s *IntegrationTestSuite) initGenesis(c *chain) { genTxs := make([]json.RawMessage, len(c.validators)) for i, val := range c.validators { stakeAmountCoin := stakeAmountCoinA - if c.id != chainAName { + if c.id != chainAID { stakeAmountCoin = stakeAmountCoinB } createValmsg, err := val.buildCreateValidatorMsg(stakeAmountCoin) @@ -380,12 +380,12 @@ func (s *IntegrationTestSuite) runIBCRelayer() { "3031/tcp": {{HostIP: "", HostPort: "3031"}}, }, Env: []string{ - fmt.Sprintf("GAIA_A_E2E_CHAIN_ID=%s", s.chainA.id), - fmt.Sprintf("GAIA_B_E2E_CHAIN_ID=%s", s.chainB.id), - fmt.Sprintf("GAIA_A_E2E_VAL_MNEMONIC=%s", gaiaAVal.mnemonic), - fmt.Sprintf("GAIA_B_E2E_VAL_MNEMONIC=%s", gaiaBVal.mnemonic), - fmt.Sprintf("GAIA_A_E2E_VAL_HOST=%s", s.valResources[s.chainA.id][0].Container.Name[1:]), - fmt.Sprintf("GAIA_B_E2E_VAL_HOST=%s", s.valResources[s.chainB.id][0].Container.Name[1:]), + fmt.Sprintf("OSMO_A_E2E_CHAIN_ID=%s", s.chainA.id), + fmt.Sprintf("OSMO_B_E2E_CHAIN_ID=%s", s.chainB.id), + fmt.Sprintf("OSMO_A_E2E_VAL_MNEMONIC=%s", gaiaAVal.mnemonic), + fmt.Sprintf("OSMO_B_E2E_VAL_MNEMONIC=%s", gaiaBVal.mnemonic), + fmt.Sprintf("OSMO_A_E2E_VAL_HOST=%s", s.valResources[s.chainA.id][0].Container.Name[1:]), + fmt.Sprintf("OSMO_B_E2E_VAL_HOST=%s", s.valResources[s.chainB.id][0].Container.Name[1:]), }, Entrypoint: []string{ "sh", diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index eff185f601e..54352d03845 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -1,7 +1,6 @@ package e2e import ( - "errors" "fmt" "io" "net/http" @@ -66,7 +65,7 @@ func queryBalances(endpoint, addr string) (sdk.Coins, error) { if resp.StatusCode == http.StatusServiceUnavailable { retriesLeft-- if retriesLeft == 0 { - return nil, errors.New(fmt.Sprintf("exceeded retry limit of %d with %d", retriesLeft, http.StatusServiceUnavailable)) + return nil, fmt.Errorf("exceeded retry limit of %d with %d", retriesLeft, http.StatusServiceUnavailable) } time.Sleep(10 * time.Second) } else { diff --git a/tests/e2e/e2e_util_test.go b/tests/e2e/e2e_util_test.go index ab6e8371e8c..39ba62c0973 100644 --- a/tests/e2e/e2e_util_test.go +++ b/tests/e2e/e2e_util_test.go @@ -111,7 +111,7 @@ func (s *IntegrationTestSuite) sendIBC(srcChainID, dstChainID, recipient string, s.T().Log("successfully sent IBC tokens") } -func queryGaiaTx(endpoint, txHash string) error { +func queryOsmoTx(endpoint, txHash string) error { resp, err := http.Get(fmt.Sprintf("%s/cosmos/tx/v1beta1/txs/%s", endpoint, txHash)) if err != nil { return fmt.Errorf("failed to execute HTTP request: %w", err) @@ -136,7 +136,7 @@ func queryGaiaTx(endpoint, txHash string) error { return nil } -func queryGaiaAllBalances(endpoint, addr string) (sdk.Coins, error) { +func queryOsmoAllBalances(endpoint, addr string) (sdk.Coins, error) { resp, err := http.Get(fmt.Sprintf("%s/cosmos/bank/v1beta1/balances/%s", endpoint, addr)) if err != nil { return nil, fmt.Errorf("failed to execute HTTP request: %w", err) @@ -157,7 +157,7 @@ func queryGaiaAllBalances(endpoint, addr string) (sdk.Coins, error) { return balancesResp.Balances, nil } -func queryGaiaDenomBalance(endpoint, addr, denom string) (sdk.Coin, error) { +func queryOsmoDenomBalance(endpoint, addr, denom string) (sdk.Coin, error) { var zeroCoin sdk.Coin path := fmt.Sprintf( diff --git a/tests/e2e/scripts/hermes_bootstrap.sh b/tests/e2e/scripts/hermes_bootstrap.sh index d1da5599bc2..1c9ec7d2a3b 100644 --- a/tests/e2e/scripts/hermes_bootstrap.sh +++ b/tests/e2e/scripts/hermes_bootstrap.sh @@ -33,10 +33,10 @@ enabled = true host = '127.0.0.1' port = 3001 [[chains]] -id = '$GAIA_A_E2E_CHAIN_ID' -rpc_addr = 'http://$GAIA_A_E2E_VAL_HOST:26657' -grpc_addr = 'http://$GAIA_A_E2E_VAL_HOST:9090' -websocket_addr = 'ws://$GAIA_A_E2E_VAL_HOST:26657/websocket' +id = '$OSMO_A_E2E_CHAIN_ID' +rpc_addr = 'http://$OSMO_A_E2E_VAL_HOST:26657' +grpc_addr = 'http://$OSMO_A_E2E_VAL_HOST:9090' +websocket_addr = 'ws://$OSMO_A_E2E_VAL_HOST:26657/websocket' rpc_timeout = '10s' account_prefix = 'osmo' key_name = 'val01-gaia-a' @@ -48,10 +48,10 @@ clock_drift = '1m' # to accomdate docker containers trusting_period = '14days' trust_threshold = { numerator = '1', denominator = '3' } [[chains]] -id = '$GAIA_B_E2E_CHAIN_ID' -rpc_addr = 'http://$GAIA_B_E2E_VAL_HOST:26657' -grpc_addr = 'http://$GAIA_B_E2E_VAL_HOST:9090' -websocket_addr = 'ws://$GAIA_B_E2E_VAL_HOST:26657/websocket' +id = '$OSMO_B_E2E_CHAIN_ID' +rpc_addr = 'http://$OSMO_B_E2E_VAL_HOST:26657' +grpc_addr = 'http://$OSMO_B_E2E_VAL_HOST:9090' +websocket_addr = 'ws://$OSMO_B_E2E_VAL_HOST:26657/websocket' rpc_timeout = '10s' account_prefix = 'osmo' key_name = 'val01-gaia-b' @@ -65,8 +65,8 @@ trust_threshold = { numerator = '1', denominator = '3' } EOF # import keys -hermes keys restore ${GAIA_B_E2E_CHAIN_ID} -n "val01-gaia-b" -m "${GAIA_B_E2E_VAL_MNEMONIC}" -hermes keys restore ${GAIA_A_E2E_CHAIN_ID} -n "val01-gaia-a" -m "${GAIA_A_E2E_VAL_MNEMONIC}" +hermes keys restore ${OSMO_B_E2E_CHAIN_ID} -n "val01-gaia-b" -m "${OSMO_B_E2E_VAL_MNEMONIC}" +hermes keys restore ${OSMO_A_E2E_CHAIN_ID} -n "val01-gaia-a" -m "${OSMO_A_E2E_VAL_MNEMONIC}" # start Hermes relayer hermes start \ No newline at end of file From 6311466ca6cdb4026651ebf6098729688e9bdd39 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Thu, 7 Apr 2022 14:42:20 -0500 Subject: [PATCH 04/12] Update Makefile Co-authored-by: Roman <34196718+p0mvn@users.noreply.github.com> --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 24182e02314..1105a5c2230 100644 --- a/Makefile +++ b/Makefile @@ -241,7 +241,7 @@ docker-build-debug: # TODO: Push this to the Cosmos Dockerhub so we don't have to keep building it # in CI. docker-build-hermes: - @cd tests/e2e/docker; docker build -t cosmos/hermes-e2e:latest -f hermes.Dockerfile . + @cd tests/e2e/docker; docker build -t osmolabs/hermes-e2e:latest -f hermes.Dockerfile . ############################################################################### ### Linting ### From bf33585e3b70c1763cb780158d0188e460b35a27 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Thu, 7 Apr 2022 21:48:05 +0000 Subject: [PATCH 05/12] remove gas fees and unused functions --- tests/e2e/docker/hermes.Dockerfile | 4 +- tests/e2e/e2e_setup_test.go | 12 ++-- tests/e2e/e2e_test.go | 82 ++++++++++++++------------- tests/e2e/e2e_util_test.go | 77 ------------------------- tests/e2e/scripts/hermes_bootstrap.sh | 6 +- 5 files changed, 54 insertions(+), 127 deletions(-) diff --git a/tests/e2e/docker/hermes.Dockerfile b/tests/e2e/docker/hermes.Dockerfile index 6478b8466de..b082044fb4a 100644 --- a/tests/e2e/docker/hermes.Dockerfile +++ b/tests/e2e/docker/hermes.Dockerfile @@ -1,4 +1,4 @@ -FROM informalsystems/hermes:0.12.0 AS hermes-builder +FROM informalsystems/hermes:0.13.0 AS hermes-builder FROM debian:buster-slim USER root @@ -9,4 +9,4 @@ COPY --from=hermes-builder /usr/bin/hermes /usr/local/bin/ RUN chmod +x /usr/local/bin/hermes EXPOSE 3031 -ENTRYPOINT ["hermes", "start"] \ No newline at end of file +ENTRYPOINT ["hermes", "start"] diff --git a/tests/e2e/e2e_setup_test.go b/tests/e2e/e2e_setup_test.go index a2f969cb475..06a2368d90a 100644 --- a/tests/e2e/e2e_setup_test.go +++ b/tests/e2e/e2e_setup_test.go @@ -31,16 +31,18 @@ import ( const ( // common - osmoDenom = "uosmo" - stakeDenom = "stake" - minGasPrice = "0.00001" + osmoDenom = "uosmo" + stakeDenom = "stake" + ibcDenom = "ibc/ED07A3391A112B175915CD8FAF43A2DA8E4790EDE12566649D0C2F97716B8518" + minGasPrice = "0.000" + ibcSendAmount = 3300000000 // chainA - chainAID = "osmo-test-a" + chainAID = "osmo-test-a" osmoBalanceA = 200000000000 stakeBalanceA = 110000000000 stakeAmountA = 100000000000 // chainB - chainBID = "osmo-test-b" + chainBID = "osmo-test-b" osmoBalanceB = 500000000000 stakeBalanceB = 440000000000 stakeAmountB = 400000000000 diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 54352d03845..e26e408fff5 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -11,45 +11,47 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) -// func (s *IntegrationTestSuite) TestQueryBalances() { -// var ( -// expectedDenoms = []string{osmoDenom, stakeDenom} -// expectedBalancesA = []uint64{osmoBalanceA, stakeBalanceA - stakeAmountA} -// expectedBalancesB = []uint64{osmoBalanceB, stakeBalanceB - stakeAmountB} -// ) - -// chainAAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainA.id][0].GetHostPort("1317/tcp")) -// balancesA, err := queryBalances(chainAAPIEndpoint, s.chainA.validators[0].keyInfo.GetAddress().String()) -// s.Require().NoError(err) -// s.Require().NotNil(balancesA) -// // s.Require().Equal(2, len(balancesA)) - -// chainBAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainB.id][0].GetHostPort("1317/tcp")) -// balancesB, err := queryBalances(chainBAPIEndpoint, s.chainB.validators[0].keyInfo.GetAddress().String()) -// s.Require().NoError(err) -// s.Require().NotNil(balancesB) -// // s.Require().Equal(2, len(balancesB)) - -// actualDenomsA := make([]string, 0, 2) -// actualBalancesA := make([]uint64, 0, 2) -// actualDenomsB := make([]string, 0, 2) -// actualBalancesB := make([]uint64, 0, 2) - -// for _, balanceA := range balancesA { -// actualDenomsA = append(actualDenomsA, balanceA.GetDenom()) -// actualBalancesA = append(actualBalancesA, balanceA.Amount.Uint64()) -// } - -// for _, balanceB := range balancesB { -// actualDenomsB = append(actualDenomsB, balanceB.GetDenom()) -// actualBalancesB = append(actualBalancesB, balanceB.Amount.Uint64()) -// } - -// s.Require().ElementsMatch(expectedDenoms, actualDenomsA) -// s.Require().ElementsMatch(expectedBalancesA, actualBalancesA) -// s.Require().ElementsMatch(expectedDenoms, actualDenomsB) -// s.Require().ElementsMatch(expectedBalancesB, actualBalancesB) -// } +func (s *IntegrationTestSuite) TestQueryBalances() { + var ( + expectedDenomsA = []string{osmoDenom, stakeDenom} + expectedDenomsB = []string{osmoDenom, stakeDenom, ibcDenom} + expectedBalancesA = []uint64{osmoBalanceA - ibcSendAmount, stakeBalanceA - stakeAmountA} + expectedBalancesB = []uint64{osmoBalanceB, stakeBalanceB - stakeAmountB, ibcSendAmount} + ) + + chainAAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainA.id][0].GetHostPort("1317/tcp")) + balancesA, err := queryBalances(chainAAPIEndpoint, s.chainA.validators[0].keyInfo.GetAddress().String()) + s.Require().NoError(err) + s.Require().NotNil(balancesA) + // s.Require().Equal(2, len(balancesA)) + + chainBAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainB.id][0].GetHostPort("1317/tcp")) + balancesB, err := queryBalances(chainBAPIEndpoint, s.chainB.validators[0].keyInfo.GetAddress().String()) + s.Require().NoError(err) + s.Require().NotNil(balancesB) + // s.Require().Equal(2, len(balancesB)) + + actualDenomsA := make([]string, 0, 2) + actualBalancesA := make([]uint64, 0, 2) + actualDenomsB := make([]string, 0, 2) + actualBalancesB := make([]uint64, 0, 2) + + for _, balanceA := range balancesA { + actualDenomsA = append(actualDenomsA, balanceA.GetDenom()) + actualBalancesA = append(actualBalancesA, balanceA.Amount.Uint64()) + } + + for _, balanceB := range balancesB { + actualDenomsB = append(actualDenomsB, balanceB.GetDenom()) + actualBalancesB = append(actualBalancesB, balanceB.Amount.Uint64()) + } + + s.Require().ElementsMatch(expectedDenomsA, actualDenomsA) + s.Require().ElementsMatch(expectedBalancesA, actualBalancesA) + s.Require().ElementsMatch(expectedDenomsB, actualDenomsB) + s.Require().ElementsMatch(expectedBalancesB, actualBalancesB) + +} func queryBalances(endpoint, addr string) (sdk.Coins, error) { path := fmt.Sprintf( @@ -97,7 +99,7 @@ func (s *IntegrationTestSuite) TestIBCTokenTransfer() { s.Run("send_uosmo_to_chainB", func() { recipient := s.chainB.validators[0].keyInfo.GetAddress().String() - token := sdk.NewInt64Coin(osmoDenom, 3300000000) // 3,300uosmo + token := sdk.NewInt64Coin(osmoDenom, ibcSendAmount) // 3,300uosmo s.sendIBC(s.chainA.id, s.chainB.id, recipient, token) chainBAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainB.id][0].GetHostPort("1317/tcp")) diff --git a/tests/e2e/e2e_util_test.go b/tests/e2e/e2e_util_test.go index 39ba62c0973..efd7cbffed9 100644 --- a/tests/e2e/e2e_util_test.go +++ b/tests/e2e/e2e_util_test.go @@ -3,14 +3,10 @@ package e2e import ( "bytes" "context" - "encoding/json" "fmt" - "io" - "net/http" "time" sdk "github.com/cosmos/cosmos-sdk/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/ory/dockertest/v3/docker" ) @@ -110,76 +106,3 @@ func (s *IntegrationTestSuite) sendIBC(srcChainID, dstChainID, recipient string, s.T().Log("successfully sent IBC tokens") } - -func queryOsmoTx(endpoint, txHash string) error { - resp, err := http.Get(fmt.Sprintf("%s/cosmos/tx/v1beta1/txs/%s", endpoint, txHash)) - if err != nil { - return fmt.Errorf("failed to execute HTTP request: %w", err) - } - - defer resp.Body.Close() - - if resp.StatusCode != 200 { - return fmt.Errorf("tx query returned non-200 status: %d", resp.StatusCode) - } - - var result map[string]interface{} - if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { - return fmt.Errorf("failed to read response body: %w", err) - } - - txResp := result["tx_response"].(map[string]interface{}) - if v := txResp["code"]; v.(float64) != 0 { - return fmt.Errorf("tx %s failed with status code %v", txHash, v) - } - - return nil -} - -func queryOsmoAllBalances(endpoint, addr string) (sdk.Coins, error) { - resp, err := http.Get(fmt.Sprintf("%s/cosmos/bank/v1beta1/balances/%s", endpoint, addr)) - if err != nil { - return nil, fmt.Errorf("failed to execute HTTP request: %w", err) - } - - defer resp.Body.Close() - - bz, err := io.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - var balancesResp banktypes.QueryAllBalancesResponse - if err := cdc.UnmarshalJSON(bz, &balancesResp); err != nil { - return nil, err - } - - return balancesResp.Balances, nil -} - -func queryOsmoDenomBalance(endpoint, addr, denom string) (sdk.Coin, error) { - var zeroCoin sdk.Coin - - path := fmt.Sprintf( - "%s/cosmos/bank/v1beta1/balances/%s/by_denom?denom=%s", - endpoint, addr, denom, - ) - resp, err := http.Get(path) - if err != nil { - return zeroCoin, fmt.Errorf("failed to execute HTTP request: %w", err) - } - - defer resp.Body.Close() - - bz, err := io.ReadAll(resp.Body) - if err != nil { - return zeroCoin, err - } - - var balanceResp banktypes.QueryBalanceResponse - if err := cdc.UnmarshalJSON(bz, &balanceResp); err != nil { - return zeroCoin, err - } - - return *balanceResp.Balance, nil -} diff --git a/tests/e2e/scripts/hermes_bootstrap.sh b/tests/e2e/scripts/hermes_bootstrap.sh index 1c9ec7d2a3b..7295a8e14ec 100644 --- a/tests/e2e/scripts/hermes_bootstrap.sh +++ b/tests/e2e/scripts/hermes_bootstrap.sh @@ -42,7 +42,7 @@ account_prefix = 'osmo' key_name = 'val01-gaia-a' store_prefix = 'ibc' max_gas = 6000000 -gas_price = { price = 0.001, denom = 'stake' } +gas_price = { price = 0.000, denom = 'stake' } gas_adjustment = 1.0 clock_drift = '1m' # to accomdate docker containers trusting_period = '14days' @@ -57,7 +57,7 @@ account_prefix = 'osmo' key_name = 'val01-gaia-b' store_prefix = 'ibc' max_gas = 6000000 -gas_price = { price = 0.001, denom = 'stake' } +gas_price = { price = 0.000, denom = 'stake' } gas_adjustment = 1.0 clock_drift = '1m' # to accomdate docker containers trusting_period = '14days' @@ -69,4 +69,4 @@ hermes keys restore ${OSMO_B_E2E_CHAIN_ID} -n "val01-gaia-b" -m "${OSMO_B_E2E_VA hermes keys restore ${OSMO_A_E2E_CHAIN_ID} -n "val01-gaia-a" -m "${OSMO_A_E2E_VAL_MNEMONIC}" # start Hermes relayer -hermes start \ No newline at end of file +hermes start From bf51d995c9d3210637fe551db1326df2e7e75010 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Fri, 8 Apr 2022 00:51:45 +0000 Subject: [PATCH 06/12] readded check --- tests/e2e/e2e_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index e26e408fff5..8be7b7dd446 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -23,13 +23,13 @@ func (s *IntegrationTestSuite) TestQueryBalances() { balancesA, err := queryBalances(chainAAPIEndpoint, s.chainA.validators[0].keyInfo.GetAddress().String()) s.Require().NoError(err) s.Require().NotNil(balancesA) - // s.Require().Equal(2, len(balancesA)) + s.Require().Equal(2, len(balancesA)) chainBAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainB.id][0].GetHostPort("1317/tcp")) balancesB, err := queryBalances(chainBAPIEndpoint, s.chainB.validators[0].keyInfo.GetAddress().String()) s.Require().NoError(err) s.Require().NotNil(balancesB) - // s.Require().Equal(2, len(balancesB)) + s.Require().Equal(3, len(balancesB)) actualDenomsA := make([]string, 0, 2) actualBalancesA := make([]uint64, 0, 2) From 4b91fd48c9a263839e70ac509b258cd76de4acea Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Fri, 8 Apr 2022 15:43:59 +0000 Subject: [PATCH 07/12] Nicco changes to own hermes image --- Makefile | 5 ----- tests/e2e/docker/hermes.Dockerfile | 2 +- tests/e2e/e2e_setup_test.go | 11 +++++++++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 1105a5c2230..380c1bf2172 100644 --- a/Makefile +++ b/Makefile @@ -238,11 +238,6 @@ benchmark: docker-build-debug: @docker build -t osmolabs/osmosisd-e2e --build-arg IMG_TAG=debug -f e2e.Dockerfile . -# TODO: Push this to the Cosmos Dockerhub so we don't have to keep building it -# in CI. -docker-build-hermes: - @cd tests/e2e/docker; docker build -t osmolabs/hermes-e2e:latest -f hermes.Dockerfile . - ############################################################################### ### Linting ### ############################################################################### diff --git a/tests/e2e/docker/hermes.Dockerfile b/tests/e2e/docker/hermes.Dockerfile index b082044fb4a..669c4c81358 100644 --- a/tests/e2e/docker/hermes.Dockerfile +++ b/tests/e2e/docker/hermes.Dockerfile @@ -1,4 +1,4 @@ -FROM informalsystems/hermes:0.13.0 AS hermes-builder +FROM osmolabs/hermes:0.13.0 AS hermes-builder FROM debian:buster-slim USER root diff --git a/tests/e2e/e2e_setup_test.go b/tests/e2e/e2e_setup_test.go index 06a2368d90a..609f6d97cdd 100644 --- a/tests/e2e/e2e_setup_test.go +++ b/tests/e2e/e2e_setup_test.go @@ -372,12 +372,19 @@ func (s *IntegrationTestSuite) runIBCRelayer() { s.hermesResource, err = s.dkrPool.RunWithOptions( &dockertest.RunOptions{ Name: fmt.Sprintf("%s-%s-relayer", s.chainA.id, s.chainB.id), - Repository: "ghcr.io/cosmos/hermes-e2e", - Tag: "latest", + Repository: "osmolabs/hermes", + Tag: "0.13.0", NetworkID: s.dkrNet.Network.ID, + Cmd: []string{ + "start", + }, + User: "root:root", Mounts: []string{ fmt.Sprintf("%s/:/root/hermes", hermesCfgPath), }, + ExposedPorts: []string{ + "3031", + }, PortBindings: map[docker.Port][]docker.PortBinding{ "3031/tcp": {{HostIP: "", HostPort: "3031"}}, }, From 94422652e4c514ca2c506f6234d26ca287d5e848 Mon Sep 17 00:00:00 2001 From: Niccolo Raspa Date: Fri, 8 Apr 2022 18:16:56 +0200 Subject: [PATCH 08/12] Remove unused hermes.Dockerfile --- tests/e2e/docker/hermes.Dockerfile | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 tests/e2e/docker/hermes.Dockerfile diff --git a/tests/e2e/docker/hermes.Dockerfile b/tests/e2e/docker/hermes.Dockerfile deleted file mode 100644 index 669c4c81358..00000000000 --- a/tests/e2e/docker/hermes.Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM osmolabs/hermes:0.13.0 AS hermes-builder - -FROM debian:buster-slim -USER root - -COPY --chown=0:0 --from=hermes-builder /usr/lib/x86_64-linux-gnu/libssl.so.1.1 /usr/lib/x86_64-linux-gnu/libssl.so.1.1 -COPY --chown=0:0 --from=hermes-builder /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 -COPY --from=hermes-builder /usr/bin/hermes /usr/local/bin/ -RUN chmod +x /usr/local/bin/hermes - -EXPOSE 3031 -ENTRYPOINT ["hermes", "start"] From af9ed4a0d6cfc0927f35354358ae379f0a4d8cd3 Mon Sep 17 00:00:00 2001 From: Niccolo Raspa Date: Fri, 8 Apr 2022 18:26:35 +0200 Subject: [PATCH 09/12] Use a single Dockerfile for both debug and official image --- Dockerfile | 9 ++++++--- Makefile | 2 +- e2e.Dockerfile | 26 -------------------------- tests/e2e/e2e_setup_test.go | 2 +- 4 files changed, 8 insertions(+), 31 deletions(-) delete mode 100644 e2e.Dockerfile diff --git a/Dockerfile b/Dockerfile index 022e5105bef..7068a414bc5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,9 @@ # syntax=docker/dockerfile:1 +ARG BASE_IMG_TAG=nonroot + ## Build Image -FROM golang:1.18-bullseye as build +FROM golang:1.17-bullseye as build WORKDIR /osmosis COPY . /osmosis @@ -13,7 +15,7 @@ RUN sha256sum /lib/libwasmvm_muslc.a | grep d0152067a5609bfdfb3f0d5d6c0f2760f79d RUN BUILD_TAGS=muslc make build ## Deploy image -FROM gcr.io/distroless/base-debian11:nonroot +FROM gcr.io/distroless/base-debian11:${BASE_IMG_TAG} COPY --from=build /osmosis/build/osmosisd /bin/osmosisd @@ -22,6 +24,7 @@ WORKDIR $HOME EXPOSE 26656 EXPOSE 26657 -EXPOSE 1317 +EXPOSE 1317 ENTRYPOINT ["osmosisd"] +CMD [ "start" ] diff --git a/Makefile b/Makefile index 380c1bf2172..7482b364c56 100644 --- a/Makefile +++ b/Makefile @@ -236,7 +236,7 @@ benchmark: @go test -mod=readonly -bench=. $(PACKAGES_UNIT) docker-build-debug: - @docker build -t osmolabs/osmosisd-e2e --build-arg IMG_TAG=debug -f e2e.Dockerfile . + @docker build -t osmosis:debug --build-arg BASE_IMG_TAG=debug -f Dockerfile . ############################################################################### ### Linting ### diff --git a/e2e.Dockerfile b/e2e.Dockerfile deleted file mode 100644 index f0bfd24d8f4..00000000000 --- a/e2e.Dockerfile +++ /dev/null @@ -1,26 +0,0 @@ -# syntax=docker/dockerfile:1 -ARG IMG_TAG=latest - -## Build Image -FROM golang:1.17-bullseye as build - -WORKDIR /osmosis -COPY . /osmosis - -# From https://github.com/CosmWasm/wasmd/blob/master/Dockerfile -# For more details see https://github.com/CosmWasm/wasmvm#builds-of-libwasmvm -ADD https://github.com/CosmWasm/wasmvm/releases/download/v1.0.0-beta7/libwasmvm_muslc.a /lib/libwasmvm_muslc.a -RUN sha256sum /lib/libwasmvm_muslc.a | grep d0152067a5609bfdfb3f0d5d6c0f2760f79d5f2cd7fd8513cafa9932d22eb350 -RUN BUILD_TAGS=muslc make build - -## Deploy image -FROM gcr.io/distroless/cc:$IMG_TAG -ARG IMG_TAG -COPY --from=build /osmosis/build/osmosisd /bin/osmosisd - -ENV HOME /osmosis -WORKDIR $HOME - -EXPOSE 26656 26657 1317 9090 - -ENTRYPOINT ["osmosisd", "start"] diff --git a/tests/e2e/e2e_setup_test.go b/tests/e2e/e2e_setup_test.go index 609f6d97cdd..5c6b0feed99 100644 --- a/tests/e2e/e2e_setup_test.go +++ b/tests/e2e/e2e_setup_test.go @@ -299,7 +299,7 @@ func (s *IntegrationTestSuite) runValidators(c *chain, portOffset int) { Mounts: []string{ fmt.Sprintf("%s/:/osmosis/.osmosisd", val.configDir()), }, - Repository: "osmolabs/osmosisd-e2e", + Repository: "osmosis:debug", } // expose the first validator for debugging and communication From c38c1c66b272a083f2b77a6430cb7b2013b03c2c Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Fri, 8 Apr 2022 16:49:35 +0000 Subject: [PATCH 10/12] readd build hermes in makefile --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 7482b364c56..092bf725c96 100644 --- a/Makefile +++ b/Makefile @@ -238,6 +238,9 @@ benchmark: docker-build-debug: @docker build -t osmosis:debug --build-arg BASE_IMG_TAG=debug -f Dockerfile . +docker-build-hermes: + @cd tests/e2e/docker; docker build -t osmolabs/hermes-e2e:latest -f hermes.Dockerfile . + ############################################################################### ### Linting ### ############################################################################### From d0b3705395802babbff5724123d3b878967c3147 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Fri, 8 Apr 2022 16:50:56 +0000 Subject: [PATCH 11/12] remove hermes --- Makefile | 3 --- 1 file changed, 3 deletions(-) diff --git a/Makefile b/Makefile index 092bf725c96..7482b364c56 100644 --- a/Makefile +++ b/Makefile @@ -238,9 +238,6 @@ benchmark: docker-build-debug: @docker build -t osmosis:debug --build-arg BASE_IMG_TAG=debug -f Dockerfile . -docker-build-hermes: - @cd tests/e2e/docker; docker build -t osmolabs/hermes-e2e:latest -f hermes.Dockerfile . - ############################################################################### ### Linting ### ############################################################################### From 826bad4511349816b68e9a88d8a71a74ad44e82c Mon Sep 17 00:00:00 2001 From: Niccolo Raspa Date: Fri, 8 Apr 2022 19:34:12 +0200 Subject: [PATCH 12/12] Set correct golang image and use correct debug image tag --- Dockerfile | 2 +- tests/e2e/e2e_setup_test.go | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7068a414bc5..2a01c6639ef 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ ARG BASE_IMG_TAG=nonroot ## Build Image -FROM golang:1.17-bullseye as build +FROM golang:1.18-bullseye as build WORKDIR /osmosis COPY . /osmosis diff --git a/tests/e2e/e2e_setup_test.go b/tests/e2e/e2e_setup_test.go index 5c6b0feed99..53bf8cbd67c 100644 --- a/tests/e2e/e2e_setup_test.go +++ b/tests/e2e/e2e_setup_test.go @@ -299,7 +299,8 @@ func (s *IntegrationTestSuite) runValidators(c *chain, portOffset int) { Mounts: []string{ fmt.Sprintf("%s/:/osmosis/.osmosisd", val.configDir()), }, - Repository: "osmosis:debug", + Repository: "osmosis", + Tag: "debug", } // expose the first validator for debugging and communication