Skip to content

Commit 41e1693

Browse files
authored
test: add forwarding relayer to hyperlane e2e suite (#6592)
## Overview Requires: - celestiaorg/forwarding-relayer#9 - celestiaorg/tastora#176 Adapts the Hyperlane E2E test for `x/forwarding` to depend on a ForwardingRelayer service. The relayer service is deployed with an associated backend and is maintained here: https://github.com/celestiaorg/forwarding-relayer ref: https://linear.app/celestia/issue/INTEROP-20/use-the-interop-6-in-the-interop-e2e-tests
1 parent 7834c61 commit 41e1693

File tree

3 files changed

+123
-13
lines changed

3 files changed

+123
-13
lines changed

test/docker-e2e/e2e_hyperlane_test.go

Lines changed: 120 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package docker_e2e
22

33
import (
4+
"bytes"
45
"celestiaorg/celestia-app/test/docker-e2e/dockerchain"
56
"context"
67
"encoding/hex"
8+
"encoding/json"
79
"fmt"
810
"math/big"
911
"net/http"
@@ -25,6 +27,7 @@ import (
2527
"github.com/celestiaorg/tastora/framework/docker/evstack/reth"
2628
"github.com/celestiaorg/tastora/framework/docker/hyperlane"
2729
"github.com/celestiaorg/tastora/framework/testutil/evm"
30+
"github.com/cosmos/cosmos-sdk/crypto"
2831
sdk "github.com/cosmos/cosmos-sdk/types"
2932
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
3033
"github.com/cosmos/gogoproto/proto"
@@ -50,12 +53,6 @@ var (
5053
RethChainID1 = 1235
5154
)
5255

53-
// EvolveEVMChain encapsulates both the evolve evm sequencer node and execution client node.
54-
type EvolveEVMChain struct {
55-
*evmsingle.Chain
56-
*reth.Node
57-
}
58-
5956
func TestHyperlaneTestSuite(t *testing.T) {
6057
suite.Run(t, new(HyperlaneTestSuite))
6158
}
@@ -64,6 +61,19 @@ type HyperlaneTestSuite struct {
6461
CelestiaTestSuite
6562
}
6663

64+
// EvolveEVMChain encapsulates both the evolve evm sequencer node and execution client node.
65+
type EvolveEVMChain struct {
66+
*evmsingle.Chain
67+
*reth.Node
68+
}
69+
70+
// ForwardingRequest for encoding JSON payloads to the forwarding service.
71+
type ForwardingRequest struct {
72+
ForwardAddr string `json:"forward_addr"`
73+
DestDomain uint32 `json:"dest_domain"`
74+
DestRecipient string `json:"dest_recipient"`
75+
}
76+
6777
func (s *HyperlaneTestSuite) SetupSuite() {
6878
s.logger = zaptest.NewLogger(s.T())
6979
s.logger.Info("Setting up Celestia test suite: " + s.T().Name())
@@ -222,11 +232,15 @@ func (s *HyperlaneTestSuite) TestHyperlaneForwarding() {
222232

223233
s.AssertERC20Balance(ctx, reth0, tokenRouter, recipient, initialDeposit.BigInt())
224234

235+
forwardingService := s.ConfigureForwardRelayer(ctx, chain)
236+
225237
// Compute the forwarding address on celestia for recipient on reth1 destintation chain
226238
destDomain := s.GetDomainForChain(ctx, reth1.HyperlaneChainName(), hyp)
227239
destRecipient := "0x0000000000000000000000004A60C46F671A3B86D78E9C0B793235C2D502D44E"
228240
forwardAddress := s.QueryForwardingAddress(ctx, chain, destDomain, destRecipient)
229241

242+
s.SendForwardingRequest(ctx, forwardingService, forwardAddress, destDomain, destRecipient)
243+
230244
forwardAddrBytes32, err := bech32ToBytes(forwardAddress)
231245
s.Require().NoError(err)
232246

@@ -243,14 +257,97 @@ func (s *HyperlaneTestSuite) TestHyperlaneForwarding() {
243257
destRecipientAddress := ethcommon.HexToAddress(destRecipient)
244258
balanceBefore := s.QueryERC20Balance(ctx, reth1, tokenRouter, destRecipientAddress)
245259

246-
// Permissionless invocation of MsgForward (to be done by external relayer service)
247-
forwardFee := s.QueryForwardingFee(ctx, chain, destDomain)
248-
s.SendForwardingTx(ctx, chain, forwardAddress, destDomain, destRecipient, forwardFee)
249-
250260
expectedBalance := new(big.Int).Add(balanceBefore, amount.BigInt())
251261
s.AssertERC20Balance(ctx, reth1, tokenRouter, destRecipientAddress, expectedBalance)
252262
}
253263

264+
func (s *HyperlaneTestSuite) ConfigureForwardRelayer(ctx context.Context, chain *cosmos.Chain) *hyperlane.ForwardRelayer {
265+
backendCfg := hyperlane.ForwardRelayerConfig{
266+
Logger: s.logger,
267+
DockerClient: s.client,
268+
DockerNetworkID: s.network,
269+
Image: hyperlane.DefaultForwardRelayerImage(),
270+
Settings: hyperlane.ForwardRelayerSettings{
271+
Port: "8080",
272+
},
273+
}
274+
275+
backend, err := hyperlane.NewForwardRelayer(ctx, backendCfg, s.T().Name(), hyperlane.BackendMode)
276+
s.Require().NoError(err)
277+
278+
err = backend.Start(ctx)
279+
s.Require().NoError(err)
280+
281+
amount := sdkmath.NewInt(1000000)
282+
sendAmount := sdk.NewCoins(sdk.NewCoin(chain.Config.Denom, amount))
283+
284+
relayerWallet, err := chain.CreateWallet(ctx, "forward-rly")
285+
s.Require().NoError(err)
286+
287+
s.SendBankSendTx(ctx, chain, chain.GetFaucetWallet().Address, relayerWallet.Address, sendAmount)
288+
289+
chainNode := chain.GetNode()
290+
keyring, err := chainNode.GetKeyring()
291+
s.Require().NoError(err)
292+
293+
armor, err := keyring.ExportPrivKeyArmor("forward-rly", "")
294+
s.Require().NoError(err)
295+
296+
privKey, _, err := crypto.UnarmorDecryptPrivKey(armor, "")
297+
s.Require().NoError(err)
298+
299+
networkInfo, err := chain.GetNetworkInfo(ctx)
300+
s.Require().NoError(err)
301+
302+
relayerCfg := hyperlane.ForwardRelayerConfig{
303+
Logger: s.logger,
304+
DockerClient: s.client,
305+
DockerNetworkID: s.network,
306+
Image: hyperlane.DefaultForwardRelayerImage(),
307+
Settings: hyperlane.ForwardRelayerSettings{
308+
CelestiaGRPC: fmt.Sprintf("http://%s", networkInfo.Internal.GRPCAddress()),
309+
BackendURL: fmt.Sprintf("http://%s:%s", backend.HostName(), "8080"),
310+
PrivateKeyHex: fmt.Sprintf("0x%x", privKey.Bytes()),
311+
},
312+
}
313+
314+
relayer, err := hyperlane.NewForwardRelayer(ctx, relayerCfg, s.T().Name(), hyperlane.RelayerMode)
315+
s.Require().NoError(err)
316+
317+
err = relayer.Start(ctx)
318+
s.Require().NoError(err)
319+
320+
return backend
321+
}
322+
323+
func (s *HyperlaneTestSuite) SendForwardingRequest(ctx context.Context, forwardingService *hyperlane.ForwardRelayer, forwardAddr string, destDomain uint32, destRecipient string) {
324+
s.T().Helper()
325+
326+
networkInfo, err := forwardingService.GetNetworkInfo(ctx)
327+
s.Require().NoError(err)
328+
329+
url := fmt.Sprintf("http://localhost:%s/forwarding-requests", strings.TrimRight(networkInfo.External.Ports.HTTP, "/"))
330+
331+
forwardReq := ForwardingRequest{
332+
ForwardAddr: forwardAddr,
333+
DestDomain: destDomain,
334+
DestRecipient: destRecipient,
335+
}
336+
337+
reqBz, err := json.Marshal(forwardReq)
338+
s.Require().NoError(err)
339+
340+
req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(reqBz))
341+
s.Require().NoError(err)
342+
req.Header.Set("Content-Type", "application/json")
343+
344+
resp, err := http.DefaultClient.Do(req)
345+
s.Require().NoError(err)
346+
defer func() { _ = resp.Body.Close() }()
347+
348+
s.Require().Equalf(http.StatusCreated, resp.StatusCode, "expected %s, got %s", http.StatusCreated, resp.StatusCode)
349+
}
350+
254351
func (s *HyperlaneTestSuite) TestHyperlaneZKIsmStateTransition() {
255352
t := s.T()
256353
if testing.Short() {
@@ -601,6 +698,19 @@ func (s *HyperlaneTestSuite) SendForwardingTx(ctx context.Context, chain *cosmos
601698
s.Require().Equalf(uint32(0), resp.Code, "tx failed: code=%d, log=%s", resp.Code, resp.RawLog)
602699
}
603700

701+
func (s *HyperlaneTestSuite) SendBankSendTx(ctx context.Context, chain *cosmos.Chain, fromAddr, toAddr sdk.AccAddress, amount sdk.Coins) {
702+
s.T().Helper()
703+
704+
broadcaster := cosmos.NewBroadcaster(chain)
705+
signer := chain.GetFaucetWallet()
706+
707+
msgBankSend := banktypes.NewMsgSend(fromAddr, toAddr, amount)
708+
709+
resp, err := broadcaster.BroadcastMessages(ctx, signer, msgBankSend)
710+
s.Require().NoError(err)
711+
s.Require().Equalf(uint32(0), resp.Code, "tx failed: code=%d, log=%s", resp.Code, resp.RawLog)
712+
}
713+
604714
func (s *HyperlaneTestSuite) SendTransferRemoteTx(ctx context.Context, chain *cosmos.Chain, tokenID hyputil.HexAddress, domain uint32, recipient ethcommon.Address, amount sdkmath.Int) {
605715
s.T().Helper()
606716

test/docker-e2e/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ require (
77
github.com/bcp-innovations/hyperlane-cosmos v1.1.0
88
github.com/celestiaorg/celestia-app/v7 v7.0.0-rc0
99
github.com/celestiaorg/go-square/v3 v3.0.2
10-
github.com/celestiaorg/tastora v0.12.0
10+
github.com/celestiaorg/tastora v0.13.0
1111
github.com/cometbft/cometbft v0.38.17
1212
github.com/cosmos/cosmos-sdk v0.50.13
1313
github.com/cosmos/gogoproto v1.7.2

test/docker-e2e/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -796,8 +796,8 @@ github.com/celestiaorg/nmt v0.24.2 h1:LlpJSPOd6/Lw1Ig6HUhZuqiINHLka/ZSRTBzlNJpch
796796
github.com/celestiaorg/nmt v0.24.2/go.mod h1:vgLBpWBi8F5KLxTdXSwb7AU4NhiIQ1AQRGa+PzdcLEA=
797797
github.com/celestiaorg/rsmt2d v0.15.1 h1:NF4D0LX501oDjw00RoJrTUrMHrO+Kv0LewL0FKQU7hg=
798798
github.com/celestiaorg/rsmt2d v0.15.1/go.mod h1:WKkpXoD1foHn4qgFx6GNoz36Wm0fbCh29ze4rA7ZwCs=
799-
github.com/celestiaorg/tastora v0.12.0 h1:xs1a/d+/QFbebShoHZxnWj8q3Kr1i6PY5137oxR+h+4=
800-
github.com/celestiaorg/tastora v0.12.0/go.mod h1:ObeKMraNab/xofYZyylnOEiveHvUAPdKP5HiNjnvQoM=
799+
github.com/celestiaorg/tastora v0.13.0 h1:fZs3OSsk2GnShk5MG7bHwhk9KD38h0Szd2UTDmeRVoc=
800+
github.com/celestiaorg/tastora v0.13.0/go.mod h1:ObeKMraNab/xofYZyylnOEiveHvUAPdKP5HiNjnvQoM=
801801
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
802802
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
803803
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=

0 commit comments

Comments
 (0)