From 0b203a6dcd48b6a49bb80c51bcb5774473da1eaa Mon Sep 17 00:00:00 2001 From: Runchao Han Date: Thu, 10 Oct 2024 10:10:18 +1100 Subject: [PATCH 1/3] chore: backport github action (#149) Part of https://github.com/babylonlabs-io/babylon/issues/110 This PR introduces the backport Github action. One can label a hotfix PR to `main` with `backport release/0.Y.x`, and this GH action will open a backport PR automatically. --- .github/workflows/backport.yml | 38 ++++++++++++++++++++++++++++++++++ RELEASE_PROCESS.md | 24 +++++++++++---------- 2 files changed, 51 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/backport.yml diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml new file mode 100644 index 000000000..47c9985f6 --- /dev/null +++ b/.github/workflows/backport.yml @@ -0,0 +1,38 @@ +# Adapted from https://github.com/marketplace/actions/backporting +# +# Usage: +# - Let's say you want to backport a pull request on a branch named `production`. +# - Then label it with `backport production`. +# - That's it! When the pull request gets merged, it will be backported to +# the `production` branch. If the pull request cannot be backported, a comment +# explaining why will automatically be posted. +# +# Note: multiple backport labels can be added. For example, if a pull request +# has the labels `backport staging` and `backport production` it will be +# backported to both branches: `staging` and `production`. +name: Backport +on: + pull_request_target: + types: + - closed + - labeled + +jobs: + backport: + name: Backport + runs-on: ubuntu-latest + # Only react to merged PRs for security reasons. + # See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target. + if: > + github.event.pull_request.merged + && ( + github.event.action == 'closed' + || ( + github.event.action == 'labeled' + && contains(github.event.label.name, 'backport') + ) + ) + steps: + - uses: tibdex/backport@v2 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/RELEASE_PROCESS.md b/RELEASE_PROCESS.md index eb58482c5..a1a846d09 100644 --- a/RELEASE_PROCESS.md +++ b/RELEASE_PROCESS.md @@ -1,12 +1,11 @@ # Release Process -- [Release Process](#release-process) - - [Breaking Changes](#breaking-changes) - - [Release Procedure](#release-procedure) - - [Creating a new release branch](#creating-a-new-release-branch) - - [Cutting a new release](#cutting-a-new-release) - - [Tagging Procedure](#tagging-procedure) - - [Patch release Procedure](#patch-release-procedure) +- [Breaking Changes](#breaking-changes) +- [Release Procedure](#release-procedure) + - [Creating a new release branch](#creating-a-new-release-branch) + - [Cutting a new release](#cutting-a-new-release) + - [Tagging Procedure](#tagging-procedure) +- [Patch Release Procedure](#patch-release-procedure) This document outlines the release process for the Babylon node (babylond) @@ -119,10 +118,13 @@ A _patch release_ is an increment of the patch number (eg: `v10.0.0` → `v10.0. circumstances .**_ Updates to the release branch should come from `main` by backporting PRs -(usually done by automatic cherry pick followed by a PRs to the release branch). -The backports must be marked using `backport/Y` label in PR for main. -It is the PR author's responsibility to fix merge conflicts and -ensure CI passes. +(usually done by automatic cherry pick followed by a PR to the release branch). +The backports must be marked using `backport release/v0.Y.x` label in PR for +`main`, where `release/v0.Y.x` is the name of the release branch. It is the PR +author's responsibility to fix merge conflicts, update changelog entries, and +ensure CI passes. If a PR originates from an external contributor, a member of +the stewarding team assumes responsibility to perform this process instead of +the original author. After the release branch has all commits required for the next patch release: * Create a new annotated git tag in the release From 223c541e64599ef5416ca0a6dc8ab7eff878e824 Mon Sep 17 00:00:00 2001 From: Cirrus Gai Date: Thu, 10 Oct 2024 14:05:42 +0800 Subject: [PATCH 2/3] chore(query): Add block results query (#148) Needed by api querying block execution results --- CHANGELOG.md | 4 ++++ client/query/tendermint.go | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c11bed963..6f6061b64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ## Unreleased +### Improvements + +* [#148](https://github.com/babylonlabs-io/babylon/pull/148) Add block results query + ## v0.12.0 ### State Machine Breaking diff --git a/client/query/tendermint.go b/client/query/tendermint.go index cf00304dc..b1afd123c 100644 --- a/client/query/tendermint.go +++ b/client/query/tendermint.go @@ -47,6 +47,13 @@ func (c *QueryClient) GetTx(hash []byte) (*coretypes.ResultTx, error) { return c.RPCClient.Tx(ctx, hash, false) } +func (c *QueryClient) BlockResults(height int64) (*coretypes.ResultBlockResults, error) { + ctx, cancel := c.getQueryContext() + defer cancel() + + return c.RPCClient.BlockResults(ctx, &height) +} + func (c *QueryClient) Subscribe(subscriber, query string, outCapacity ...int) (out <-chan coretypes.ResultEvent, err error) { return c.RPCClient.Subscribe(context.Background(), subscriber, query, outCapacity...) } From e4a655b800d40d2979894bee3c74c6dfaaa7e5d1 Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Thu, 10 Oct 2024 08:18:14 +0200 Subject: [PATCH 3/3] Housekeeping: backport IBC transfer e2e (#151) --- CHANGELOG.md | 1 + contrib/images/babylond/Dockerfile | 4 +- .../images/e2e-initialization/init.Dockerfile | 5 +- test/e2e/configurer/chain/chain.go | 2 +- test/e2e/ibc_transfer_e2e_test.go | 130 +++++++++++++++++- 5 files changed, 132 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f6061b64..9b6bd8cd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,7 @@ insert from the v1 upgrade handler. ### Improvements +* [#151](https://github.com/babylonlabs-io/babylon/pull/151) Improve IBC transfer e2e test * [#130](https://github.com/babylonlabs-io/babylon/pull/130) Fix bugs in the transaction fee refunding mechanism for covenant signatures and finality signatures * [#125](https://github.com/babylonlabs-io/babylon/pull/125) Implement ADR-028 and diff --git a/contrib/images/babylond/Dockerfile b/contrib/images/babylond/Dockerfile index 9fb29c340..0d274fa48 100644 --- a/contrib/images/babylond/Dockerfile +++ b/contrib/images/babylond/Dockerfile @@ -26,6 +26,8 @@ RUN LEDGER_ENABLED=$LEDGER_ENABLED \ FROM debian:bookworm-slim AS wasm-link +ARG VERSION + # Create a user RUN addgroup --gid 1137 --system babylon && adduser --uid 1137 --gid 1137 --system --home /home/babylon babylon @@ -51,4 +53,4 @@ COPY --from=build-env /go/src/github.com/babylonlabs-io/babylon/build/babylond / WORKDIR /home/babylon RUN chown -R babylon /home/babylon RUN chmod g+s /home/babylon -USER babylon \ No newline at end of file +USER babylon diff --git a/contrib/images/e2e-initialization/init.Dockerfile b/contrib/images/e2e-initialization/init.Dockerfile index 2a496a1ab..1457299be 100644 --- a/contrib/images/e2e-initialization/init.Dockerfile +++ b/contrib/images/e2e-initialization/init.Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.21 as build-env +FROM golang:1.21 AS build-env ARG E2E_SCRIPT_NAME # Version to build. Default is empty @@ -18,6 +18,7 @@ RUN LEDGER_ENABLED=false LINK_STATICALLY=false E2E_SCRIPT_NAME=${E2E_SCRIPT_NAME FROM debian:bookworm-slim AS wasm-link +ARG VERSION # Create a user RUN addgroup --gid 1137 --system babylon && adduser --uid 1137 --gid 1137 --system --home /home/babylon babylon @@ -47,4 +48,4 @@ COPY --from=build-env /go/src/github.com/babylonlabs-io/babylon/build/${E2E_SCRI # As a workaround, we create the entrypoint.sh script to bypass these issues. RUN echo "#!/bin/bash\n${E2E_SCRIPT_NAME} \"\$@\"" >> entrypoint.sh && chmod +x entrypoint.sh -ENTRYPOINT ["./entrypoint.sh"] \ No newline at end of file +ENTRYPOINT ["./entrypoint.sh"] diff --git a/test/e2e/configurer/chain/chain.go b/test/e2e/configurer/chain/chain.go index 137d002e0..b93aeb0bc 100644 --- a/test/e2e/configurer/chain/chain.go +++ b/test/e2e/configurer/chain/chain.go @@ -176,7 +176,7 @@ func (c *Config) GetPersistentPeers() []string { func (c *Config) GetNodeAtIndex(nodeIndex int) (*NodeConfig, error) { if nodeIndex > len(c.NodeConfigs) { - return nil, fmt.Errorf("node index (%d) is greter than the number of nodes available (%d)", nodeIndex, len(c.NodeConfigs)) + return nil, fmt.Errorf("node index (%d) is greater than the number of nodes available (%d)", nodeIndex, len(c.NodeConfigs)) } return c.NodeConfigs[nodeIndex], nil } diff --git a/test/e2e/ibc_transfer_e2e_test.go b/test/e2e/ibc_transfer_e2e_test.go index 921026dce..60f29d237 100644 --- a/test/e2e/ibc_transfer_e2e_test.go +++ b/test/e2e/ibc_transfer_e2e_test.go @@ -1,6 +1,8 @@ package e2e import ( + "math" + "strings" "time" "github.com/babylonlabs-io/babylon/test/e2e/configurer" @@ -39,16 +41,132 @@ func (s *IBCTransferTestSuite) TearDownSuite() { } } +func getFirstIBCDenom(balance sdk.Coins) string { + // Look up the ugly IBC denom + denoms := balance.Denoms() + var denomB string + for _, d := range denoms { + if strings.HasPrefix(d, "ibc/") { + denomB = d + break + } + } + return denomB +} + func (s *IBCTransferTestSuite) Test1IBCTransfer() { - bbnChain := s.configurer.GetChainConfig(0) + denom := "ubbn" + amount := int64(1_000_000) + delta := float64(10000) // Tolerance to account for gas fees + + transferCoin := sdk.NewInt64Coin(denom, amount) + + bbnChainA := s.configurer.GetChainConfig(0) + bbnChainB := s.configurer.GetChainConfig(1) + + babylonNodeA, err := bbnChainA.GetNodeAtIndex(2) + s.NoError(err) + babylonNodeB, err := bbnChainB.GetNodeAtIndex(2) + s.NoError(err) + + val := initialization.ValidatorWalletName + + // Check balance of val in chain-A (Node 3) + addrA := babylonNodeA.GetWallet(val) + balanceA, err := babylonNodeA.QueryBalances(addrA) + s.Require().NoError(err) + // Confirm val on A has enough funds + s.Assert().GreaterOrEqual(balanceA.AmountOf(denom).Int64(), amount) + + addrB := babylonNodeB.GetWallet(val) + balanceB, err := babylonNodeB.QueryBalances(addrB) + s.Require().NoError(err) + // Only one denom in B + s.Require().Len(balanceB, 1) - babylonNode, err := bbnChain.GetNodeAtIndex(2) + // Send transfer from val in chain-A (Node 3) to val in chain-B (Node 3) + babylonNodeA.SendIBCTransfer(val, addrB, "transfer", transferCoin) + + s.Require().Eventually(func() bool { + // Check that the transfer is successful. + // Amounts have been discounted from val in chain-A and added (as a wrapped denom) to val in chain-B + balanceA2, err := babylonNodeA.QueryBalances(addrA) + if err != nil { + return false + } + return math.Abs(float64(balanceA.Sub(transferCoin).AmountOf(denom).Int64()- + balanceA2.AmountOf(denom).Int64())) < delta + }, 10*time.Second, 1*time.Second, "Transfer was not successful") + + s.Require().Eventually(func() bool { + balanceB2, err := babylonNodeB.QueryBalances(addrB) + if err != nil { + return false + } + // Check that there are now two denoms in B + if len(balanceB2) != 2 { + return false + } + denomB := getFirstIBCDenom(balanceB2) + // Check the balance of the IBC denom + return math.Abs(float64(balanceB2.AmountOf(denomB).Int64()- + transferCoin.Amount.Int64())) < delta + }, 10*time.Second, 1*time.Second, "Transfer was not successful") +} + +func (s *IBCTransferTestSuite) Test2IBCTransferBack() { + nativeDenom := "ubbn" + delta := float64(10000) // Tolerance to account for gas fees + + bbnChainA := s.configurer.GetChainConfig(0) + bbnChainB := s.configurer.GetChainConfig(1) + + babylonNodeA, err := bbnChainA.GetNodeAtIndex(0) + s.NoError(err) + babylonNodeB, err := bbnChainB.GetNodeAtIndex(2) s.NoError(err) - sender := initialization.ValidatorWalletName - babylonNode.SendIBCTransfer(sender, sender, "", sdk.NewInt64Coin("ubbn", 1000)) + val := initialization.ValidatorWalletName + + addrB := babylonNodeB.GetWallet(val) + balanceB, err := babylonNodeB.QueryBalances(addrB) + s.Require().NoError(err) + // Two denoms in B + s.Require().Len(balanceB, 2) + // Look for the ugly IBC one + denom := getFirstIBCDenom(balanceB) + amount := balanceB.AmountOf(denom).Int64() - int64(delta) // have to pay gas fees + + transferCoin := sdk.NewInt64Coin(denom, amount) + + // Send transfer from val in chain-B (Node 3) to val in chain-A (Node 1) + addrA := babylonNodeA.GetWallet(val) + balanceA, err := babylonNodeA.QueryBalances(addrA) + s.Require().NoError(err) + + babylonNodeB.SendIBCTransfer(val, addrA, "transfer back", transferCoin) - time.Sleep(1 * time.Minute) + s.Require().Eventually(func() bool { + balanceB2, err := babylonNodeB.QueryBalances(addrB) + if err != nil { + return false + } + return math.Abs(float64(balanceB.Sub(transferCoin).AmountOf(denom).Int64()- + balanceB2.AmountOf(denom).Int64())) < delta + }, 10*time.Second, 1*time.Second, "Transfer back was not successful") - // TODO: check the transfer is successful. Right now this is done by manually looking at the log + nativeCoin := sdk.NewInt64Coin(nativeDenom, amount) + s.Require().Eventually(func() bool { + balanceA2, err := babylonNodeA.QueryBalances(addrA) + if err != nil { + return false + } + // Check that there's still one denom in A + if len(balanceA2) != 1 { + return false + } + // Check that the balance of the native denom has increased + return math.Abs(float64(balanceA.Add(nativeCoin).AmountOf(nativeDenom).Int64()- + balanceA2.AmountOf(nativeDenom).Int64())) < delta + }, 10*time.Second, 1*time.Second, "Transfer back was not successful") }