11package docker_e2e
22
33import (
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"
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-
5956func 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+
6777func (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+
254351func (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+
604714func (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
0 commit comments