Skip to content

Commit

Permalink
Timestamping phase 2 e2e tests (#419)
Browse files Browse the repository at this point in the history
* Update babylon-contract

* Update README

* Fix localnet nodes 3 & 4

* Fix babylon contract instantiation

* Fix / adapt contract execution test

* Contract download script (#155)

Add download contract from release script

* Fix typos

* Reduce network / IB relayer start wait time

* Move IBC config to chain config

* Add BTC Timestamping Phase 2 test

* Improve syntax

Co-authored-by: Runchao Han <me@runchao.rocks>

* Revert "Fix localnet nodes 3 & 4"

This reverts commit aaf3707b28985d5f03261107d0fad518fc478527.

* Now fix localnet nodes 3 & 4

* Simplify phase-2 vs phase-1 test setup

* Simplify phase 2 test

* Make chain-B the CZ chain

* Use regtest const for network

* Use default checkpoint tag const for babylon tag

Update contract to custom

* Fix comment

Co-authored-by: Runchao Han <me@runchao.rocks>

* Update contract to custom

* Fix original test as well

* Increase delay to wait for chain ready

* Add (failing) next IBC packet sequence check

* Fix: contains wasm check

* Storage contract e2e (#171)

* Revert "Update babylon-contract"

This reverts commit 7c656b183818098f2662ac9996cde80b8f4009ba.

* Update storage-contract to custom

* Revert "Update README"

This reverts commit 3669c88d16b2ea1c8185ed53a74be0a0ae3b11ea.

* Revert "Fix babylon contract instantiation"

This reverts commit 1fb44d7fcfac3d79a4c8b9323a56eb8b0a837d83.

* Revert "Fix / adapt contract execution test"

This reverts commit 124099dd64dd519aba0774d3e5a7e43d7a44162a.

* Fix imports

* fix phase-2 e2e test (#163)

* Upgrade keyring / go-keychain dependency (#170)

* Add cosmos relayer docker image build

* Reduce cosmos-relayer image

* Set / use relayer tag

* Improve hermes bootstrap script

* Set ABCI packet persistence

* Add Cosmos relayer setup

* Enable debug logs

* Reduce relayer setup wait time

* Simplify seup / remove commented lines

* fix

* Fix: packet acknowledgements check

* Rename for consistency

* Same acknowledgements logic for Hermes relayer

* More test renaming for consistency

* Skip BTC timestamping phase 2 test (Hermes)

* Fix: BTC timestamping phase 1 tests

* Improve flaky BTC timestamping tests

* Return network to RegTest

* Update contracts code to latest

* Remove docker Platform directive / commented code

* Increase wait for blocks delay

* Add cosmos relayer docker build target to e2e target deps

* Fix rebase errors

* Remove unused helper

* Add TODOs

* Remove commented code

* Comment BTC timestamping hermes test out

* Restore original BTC timestamping test

* Report target arch / Go lang version

* Hardcode target arch for CI

* Hardcode next expected sequence

---------

Co-authored-by: Runchao Han <me@runchao.rocks>
Co-authored-by: Mauro Lacy <mauro@babylonchain.io>
  • Loading branch information
3 people authored Jan 22, 2024
1 parent fa904d3 commit fac4830
Show file tree
Hide file tree
Showing 32 changed files with 1,037 additions and 94 deletions.
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ endif

.PHONY: run-tests test test-all $(TEST_TARGETS)

test-e2e: build-docker
test-e2e: build-docker build-cosmos-relayer-docker
go test -mod=readonly -timeout=25m -v $(PACKAGES_E2E) -count=1 --tags=e2e

test-sim-nondeterminism:
Expand Down Expand Up @@ -391,7 +391,10 @@ proto-lint:
build-docker:
$(MAKE) -C contrib/images babylond

.PHONY: build-docker
build-cosmos-relayer-docker:
$(MAKE) -C contrib/images cosmos-relayer

.PHONY: build-docker build-cosmos-relayer-docker

###############################################################################
### Localnet ###
Expand Down
14 changes: 12 additions & 2 deletions contrib/images/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
all: babylond
RELAYER_TAG := $(shell grep '^ENV RELAYER_TAG' cosmos-relayer/Dockerfile | cut -f3 -d\ )

all: babylond cosmos-relayer

babylond: babylond-rmi
docker build --tag babylonchain/babylond -f babylond/Dockerfile \
Expand All @@ -7,4 +9,12 @@ babylond: babylond-rmi
babylond-rmi:
docker rmi babylonchain/babylond 2>/dev/null; true

.PHONY: all babylond babylond-rmi
cosmos-relayer: cosmos-relayer-rmi
docker build --tag babylonchain/cosmos-relayer:${RELAYER_TAG} -f cosmos-relayer/Dockerfile \
$(shell git rev-parse --show-toplevel)/contrib/images/cosmos-relayer
docker tag babylonchain/cosmos-relayer:${RELAYER_TAG} babylonchain/cosmos-relayer:latest

cosmos-relayer-rmi:
docker rmi babylonchain/cosmos-relayer 2>/dev/null; true

.PHONY: all babylond cosmos-relayer babylond-rmi cosmos-relayer-rmi
38 changes: 38 additions & 0 deletions contrib/images/cosmos-relayer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
FROM debian:bullseye-slim AS build-env

RUN apt-get update && apt-get install -y git make jq gcc make wget

WORKDIR /work

ARG TARGETARCH="amd64"

# Download and install Go
ENV GOLANG_VERSION 1.21.4
RUN wget -q https://golang.org/dl/go${GOLANG_VERSION}.linux-${TARGETARCH}.tar.gz && \
tar -C /usr/local -xzf go${GOLANG_VERSION}.linux-${TARGETARCH}.tar.gz && \
rm go${GOLANG_VERSION}.linux-${TARGETARCH}.tar.gz
# Set Go environment variables
ENV PATH /usr/local/go/bin:$PATH
ENV GOPATH /go
ENV PATH $GOPATH/bin:$PATH

WORKDIR /work

ENV GO111MODULE on
ENV RELAYER_TAG main
# ENV RELAYER_TAG v2.4.2

# Install the relayer
RUN git clone https://github.com/cosmos/relayer.git
RUN cd relayer && git fetch origin && git checkout ${RELAYER_TAG} && make install && cd -

FROM debian:bullseye-slim AS run
# Create a user
RUN addgroup --system rly && adduser --system --gid 101 rly

COPY --from=build-env /go/bin/rly /usr/bin/rly

# Set home directory and user
WORKDIR /home/rly
RUN chown -R rly /home/rly
USER rly
2 changes: 0 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ services:
container_name: babylondnode2
image: "babylonchain/babylond"
environment:
- HOME=/data/node2/babylond
- LOG=${LOG:-babylond.log}
command: >
babylond --home /babylondhome start --log_format 'plain' 2>&1 | tee /babylondhome/babylond.log
Expand All @@ -68,7 +67,6 @@ services:
container_name: babylondnode3
image: "babylonchain/babylond"
environment:
- HOME=/data/node3/babylond
- LOG=${LOG:-babylond.log}
command: >
babylond --home /babylondhome start --log_format 'plain' 2>&1 | tee /babylondhome/babylond.log
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ approach.

### Wasm contract used for e2e testing

Wasm contract located in `bytecode/storage_contract.wasm` is compiled from most recent commit `main` branch - https://github.com/babylonchain/storage-contract
Wasm contract located in `bytecode/babylon_contract.wasm` is compiled from most recent commit `main` branch - https://github.com/babylonchain/babylon-contract

This contract uses feature specific to Babylon, through Babylon bindings library.

### Common Problems

Please note that if the tests are stopped mid-way, the e2e framework might fail to start again due to duplicated containers. Make sure that
containers are removed before running the tests again: `docker containers rm -f $(docker containers ls -a -q)`.
containers are removed before running the tests again: `docker container rm -f $(docker container ls -a -q)`.

Additionally, Docker networks do not get auto-removed. Therefore, you can manually remove them by running `docker network prune`.
17 changes: 11 additions & 6 deletions test/e2e/btc_timestamping_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func (s *BTCTimestampingTestSuite) SetupSuite() {
// * For each chain, set up several validator nodes
// * Initialize configs and genesis for all them.
// 2. Start both networks.
// 3. Run IBC relayer betweeen the two chains.
// 3. Run IBC relayer between the two chains.
// 4. Execute various e2e tests, including IBC
s.configurer, err = configurer.NewBTCTimestampingConfigurer(s.T(), true)

Expand Down Expand Up @@ -116,13 +116,13 @@ func (s *BTCTimestampingTestSuite) Test4IbcCheckpointing() {
s.NoError(err)
s.Equal(chainsInfo[0].ChainId, initialization.ChainBID)

// Finalize epoch 1,2,3 , as first headers of opposing chain are in epoch 3
// Finalize epoch 1, 2, 3, as first headers of opposing chain are in epoch 3
var (
startEpochNum uint64 = 1
endEpochNum uint64 = 3
)

// submitter/reporter address should not have any reward yet
// submitter/reporter address should not have any rewards yet
submitterReporterAddr := sdk.MustAccAddressFromBech32(nonValidatorNode.PublicAddress)
_, err = nonValidatorNode.QueryRewardGauge(submitterReporterAddr)
s.Error(err)
Expand All @@ -133,6 +133,11 @@ func (s *BTCTimestampingTestSuite) Test4IbcCheckpointing() {
s.NoError(err)
s.Equal(endEpoch.Status, ct.Finalized)

// Wait for a some time to ensure that the checkpoint is included in the chain
time.Sleep(20 * time.Second)
// Wait for next block
nonValidatorNode.WaitForNextBlock()

// Check we have epoch info for opposing chain and some basic assertions
epochChainsInfo, err := nonValidatorNode.QueryEpochChainsInfo(endEpochNum, []string{initialization.ChainBID})
s.NoError(err)
Expand Down Expand Up @@ -244,7 +249,7 @@ func (s *BTCTimestampingTestSuite) Test6Wasm() {
}
latestWasmId = newLatestWasmId
return true
}, time.Second*10, time.Second)
}, time.Second*20, time.Second)

// instantiate the wasm contract
var contracts []string
Expand All @@ -264,11 +269,11 @@ func (s *BTCTimestampingTestSuite) Test6Wasm() {
dataHex := hex.EncodeToString(data)
dataHash := sha256.Sum256(data)
dataHashHex := hex.EncodeToString(dataHash[:])
storeMsg := fmt.Sprintf(`{"save_data":{"data":"%s"}}`, dataHex)
storeMsg := fmt.Sprintf(`{"save_data": { "data": "%s" } }`, dataHex)
nonValidatorNode.WasmExecute(contractAddr, storeMsg, initialization.ValidatorWalletName)

// the data is eventually included in the contract
queryMsg := fmt.Sprintf(`{"check_data": {"data_hash":"%s"}}`, dataHashHex)
queryMsg := fmt.Sprintf(`{"check_data": { "data_hash": "%s" } }`, dataHashHex)
var queryResult map[string]interface{}
s.Eventually(func() bool {
queryResult, err = nonValidatorNode.QueryWasmSmartObject(contractAddr, queryMsg)
Expand Down
127 changes: 127 additions & 0 deletions test/e2e/btc_timestamping_phase2_hermes_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package e2e

import (
"time"

"github.com/babylonchain/babylon/test/e2e/configurer"
"github.com/babylonchain/babylon/test/e2e/initialization"
ct "github.com/babylonchain/babylon/x/checkpointing/types"
zctypes "github.com/babylonchain/babylon/x/zoneconcierge/types"
"github.com/cosmos/cosmos-sdk/types/query"
channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types"
"github.com/stretchr/testify/suite"
)

type BTCTimestampingPhase2HermesTestSuite struct {
suite.Suite

configurer configurer.Configurer
}

func (s *BTCTimestampingPhase2HermesTestSuite) SetupSuite() {
s.T().Log("setting up phase 2 integration test suite...")
var (
err error
)

// The e2e test flow is as follows:
//
// 1. Configure two chains - chain A and chain B.
// * For each chain, set up several validator nodes
// * Initialize configs and genesis for all them.
// 2. Start both networks.
// 3. Store and instantiate babylon contract on chain B.
// 3. Execute various e2e tests, excluding IBC
s.configurer, err = configurer.NewBTCTimestampingPhase2Configurer(s.T(), true)

s.Require().NoError(err)

err = s.configurer.ConfigureChains()
s.Require().NoError(err)

err = s.configurer.RunSetup()
s.Require().NoError(err)
}

func (s *BTCTimestampingPhase2HermesTestSuite) TearDownSuite() {
err := s.configurer.ClearResources()
s.Require().NoError(err)
}

func (s *BTCTimestampingPhase2HermesTestSuite) Test1IbcCheckpointingPhase2Hermes() {
chainA := s.configurer.GetChainConfig(0)

babylonNode, err := chainA.GetNodeAtIndex(2)
s.NoError(err)
czNode, err := s.configurer.GetChainConfig(1).GetNodeAtIndex(2)
s.NoError(err)

// Validate channel state and kind (Babylon side)
babylonChannelsResp, err := babylonNode.QueryIBCChannels()
s.NoError(err)
s.Len(babylonChannelsResp.Channels, 1)
babylonChannel := babylonChannelsResp.Channels[0]
// channel has to be open and ordered
s.Equal(channeltypes.OPEN, babylonChannel.State)
s.Equal(channeltypes.ORDERED, babylonChannel.Ordering)
// the counterparty has to be the Babylon smart contract
s.Contains(babylonChannel.Counterparty.PortId, "wasm.")

// Validate channel state (CZ side)
czChannelsResp, err := czNode.QueryIBCChannels()
s.NoError(err)
s.Len(czChannelsResp.Channels, 2) // TODO: why 2 channels?
czChannel := czChannelsResp.Channels[0]
s.Equal(channeltypes.OPEN, czChannel.State)
s.Equal(channeltypes.ORDERED, czChannel.Ordering)
s.Equal(zctypes.PortID, czChannel.Counterparty.PortId)

// Query checkpoint chain info for the consumer chain
listHeaderResp, err := babylonNode.QueryListHeaders(initialization.ChainBID, &query.PageRequest{Limit: 1})
s.NoError(err)
startEpochNum := listHeaderResp.Headers[0].BabylonEpoch
endEpochNum := startEpochNum + 2

// wait until epoch endEpochNum
// so that there will be endEpochNum - startEpochNum + 1 = 3
// BTC timestamps in Babylon contract
chainA.WaitUntilHeight(int64(endEpochNum*10 + 5))
babylonNode.FinalizeSealedEpochs(1, endEpochNum)

// ensure endEpochNum has been finalised
endEpoch, err := babylonNode.QueryRawCheckpoint(endEpochNum)
s.NoError(err)
s.Equal(endEpoch.Status, ct.Finalized)

// there should be 3 IBC packets sent (with sequence number 1, 2, 3).
// Thus, the next sequence number will eventually be 4
s.Eventually(func() bool {
nextSequenceSendResp, err := babylonNode.QueryNextSequenceSend(babylonChannel.ChannelId, babylonChannel.PortId)
if err != nil {
return false
}
s.T().Logf("next sequence send at ZoneConcierge is %d", nextSequenceSendResp.NextSequenceSend)
return nextSequenceSendResp.NextSequenceSend >= endEpochNum-startEpochNum+1+1
}, time.Minute, time.Second*2)

// ensure the next receive sequence number of Babylon contract is also 3
s.Eventually(func() bool {
nextSequenceRecv, err := czNode.QueryNextSequenceReceive(babylonChannel.Counterparty.ChannelId, babylonChannel.Counterparty.PortId)
if err != nil {
return false
}
s.T().Logf("next sequence receive at Babylon contract is %d", nextSequenceRecv.NextSequenceReceive)
return nextSequenceRecv.NextSequenceReceive >= endEpochNum-startEpochNum+1+1
}, time.Minute, time.Second*2)

// Ensure the IBC packet acknowledgements (on chain B) are there
lastSequence := endEpochNum
for seq := uint64(1); seq < lastSequence; seq++ {
var seqResp *channeltypes.QueryPacketAcknowledgementResponse
s.Eventually(func() bool {
seqResp, err = czNode.QueryPacketAcknowledgement(czChannel.ChannelId, czChannel.PortId, seq)
s.T().Logf("acknowledgement resp of IBC packet #%d: %v, err: %v", seq, seqResp, err)
return err == nil
}, time.Minute, time.Second*2)
}
}
Loading

0 comments on commit fac4830

Please sign in to comment.