Skip to content

Commit 537b47c

Browse files
imp: eth light client and relayer sepolia support (#394)
Co-authored-by: srdtrk <[email protected]>
1 parent c75de20 commit 537b47c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+3790
-642
lines changed

Cargo.lock

+362-132
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+8-8
Original file line numberDiff line numberDiff line change
@@ -85,17 +85,17 @@ ibc-core-commitment-types = { version = "0.57", default-features = false }
8585
ibc-core-handler-types = { version = "0.57", default-features = false }
8686
ibc-client-tendermint-types = { version = "0.57", default-features = false }
8787

88-
alloy = { version = "0.11", default-features = false }
89-
alloy-contract = { version = "0.11", default-features = false }
88+
alloy = { version = "0.12", default-features = false }
89+
alloy-contract = { version = "0.12", default-features = false }
9090
alloy-sol-types = { version = "0.8", default-features = false }
9191
alloy-primitives = { version = "0.8", default-features = false }
92-
alloy-serde = { version = "0.11", default-features = false }
93-
alloy-network = { version = "0.11", default-features = false }
94-
alloy-signer-local = { version = "0.11", default-features = false }
92+
alloy-serde = { version = "0.12", default-features = false }
93+
alloy-network = { version = "0.12", default-features = false }
94+
alloy-signer-local = { version = "0.12", default-features = false }
9595
alloy-rlp = { version = "0.3", default-features = false }
96-
alloy-provider = { version = "0.11", default-features = false }
97-
alloy-transport = { version = "0.11", default-features = false }
98-
alloy-rpc-types-eth = { version = "0.11", default-features = false }
96+
alloy-provider = { version = "0.12", default-features = false }
97+
alloy-transport = { version = "0.12", default-features = false }
98+
alloy-rpc-types-eth = { version = "0.12", default-features = false }
9999

100100
sp1-sdk = { version = "4.1", default-features = false }
101101
sp1-prover = { version = "4.1", default-features = false }

e2e/interchaintestv8/chainconfig/kurtosis.go

+12-10
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,12 @@ var (
3131
kurtosisConfig = kurtosisNetworkParams{
3232
Participants: []kurtosisParticipant{
3333
{
34-
CLType: "lodestar",
35-
CLImage: "ethpandaops/lodestar:devnet-5-1c2b5ed",
36-
ELType: "geth",
37-
ELImage: "ethpandaops/geth:prague-devnet-5-a193537",
38-
ELLogLevel: "info",
34+
CLType: "lodestar",
35+
CLImage: "ethpandaops/lodestar:unstable",
36+
ELType: "geth",
37+
ELImage: "ethpandaops/geth:prague-devnet-6",
38+
ELLogLevel: "info",
39+
ValidatorCount: 64,
3940
},
4041
},
4142
NetworkParams: kurtosisNetworkConfigParams{
@@ -65,11 +66,12 @@ type kurtosisNetworkParams struct {
6566
}
6667

6768
type kurtosisParticipant struct {
68-
CLType string `json:"cl_type"`
69-
CLImage string `json:"cl_image"`
70-
ELType string `json:"el_type"`
71-
ELImage string `json:"el_image"`
72-
ELLogLevel string `json:"el_log_level"`
69+
CLType string `json:"cl_type"`
70+
CLImage string `json:"cl_image"`
71+
ELType string `json:"el_type"`
72+
ELImage string `json:"el_image"`
73+
ELLogLevel string `json:"el_log_level"`
74+
ValidatorCount uint64 `json:"validator_count"`
7375
}
7476

7577
type kurtosisNetworkConfigParams struct {

e2e/interchaintestv8/e2esuite/light_clients.go

+24-14
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"encoding/json"
77
"fmt"
88
"os"
9-
"strconv"
109

1110
ethcommon "github.com/ethereum/go-ethereum/common"
1211

@@ -55,20 +54,32 @@ func (s *TestSuite) createEthereumLightClient(
5554
spec, err := eth.BeaconAPIClient.GetSpec()
5655
s.Require().NoError(err)
5756

58-
executionHeight, err := eth.BeaconAPIClient.GetExecutionHeight("finalized")
57+
beaconBlock, err := eth.BeaconAPIClient.GetBeaconBlocks("finalized")
5958
s.Require().NoError(err)
59+
60+
executionHeight := beaconBlock.Data.Message.Body.ExecutionPayload.BlockNumber
6061
executionNumberHex := fmt.Sprintf("0x%x", executionHeight)
6162

63+
header, err := eth.BeaconAPIClient.GetHeader(beaconBlock.Data.Message.Slot)
64+
s.Require().NoError(err)
65+
66+
bootstrap, err := eth.BeaconAPIClient.GetBootstrap(header.Root)
67+
s.Require().NoError(err)
68+
s.Require().Equal(executionHeight, bootstrap.Data.Header.Execution.BlockNumber)
69+
70+
latestSlot := bootstrap.Data.Header.Beacon.Slot
71+
6272
ethClientState := ethereumtypes.ClientState{
6373
ChainID: eth.ChainID.Uint64(),
6474
GenesisValidatorsRoot: ethcommon.Bytes2Hex(genesis.GenesisValidatorsRoot[:]),
6575
MinSyncCommitteeParticipants: 32,
6676
GenesisTime: uint64(genesis.GenesisTime.Unix()),
77+
GenesisSlot: spec.GenesisSlot,
6778
ForkParameters: spec.ToForkParameters(),
6879
SecondsPerSlot: uint64(spec.SecondsPerSlot.Seconds()),
6980
SlotsPerEpoch: spec.SlotsPerEpoch,
7081
EpochsPerSyncCommitteePeriod: spec.EpochsPerSyncCommitteePeriod,
71-
LatestSlot: executionHeight,
82+
LatestSlot: latestSlot,
7283
IsFrozen: false,
7384
IbcCommitmentSlot: testvalues.IbcCommitmentSlotHex,
7485
IbcContractAddress: ibcContractAddress,
@@ -93,21 +104,14 @@ func (s *TestSuite) createEthereumLightClient(
93104
proofOfIBCContract, err := eth.EthAPI.GetProof(ibcContractAddress, []string{ics26router.IbcStoreStorageSlot}, executionNumberHex)
94105
s.Require().NoError(err)
95106

96-
header, err := eth.BeaconAPIClient.GetHeader(strconv.Itoa(int(executionHeight)))
97-
s.Require().NoError(err)
98-
bootstrap, err := eth.BeaconAPIClient.GetBootstrap(header.Root)
99-
s.Require().NoError(err)
100-
101-
if bootstrap.Data.Header.Beacon.Slot != executionHeight {
102-
s.Require().Fail(fmt.Sprintf("creating client: expected exec height %d, to equal boostrap slot %d", executionHeight, bootstrap.Data.Header.Beacon.Slot))
103-
}
104-
105107
unixTimestamp := bootstrap.Data.Header.Execution.Timestamp
106108

107-
currentPeriod := executionHeight / spec.Period()
109+
currentPeriod := latestSlot / spec.Period()
108110
clientUpdates, err := eth.BeaconAPIClient.GetLightClientUpdates(currentPeriod, 1)
109111
s.Require().NoError(err)
110-
s.Require().NotEmpty(clientUpdates)
112+
s.Require().Len(clientUpdates, 1)
113+
114+
fmt.Println("Current period:", currentPeriod)
111115

112116
ethConsensusState := ethereumtypes.ConsensusState{
113117
Slot: bootstrap.Data.Header.Beacon.Slot,
@@ -120,6 +124,9 @@ func (s *TestSuite) createEthereumLightClient(
120124

121125
ethConsensusStateBz, err := json.Marshal(&ethConsensusState)
122126
s.Require().NoError(err)
127+
128+
fmt.Printf("Eth consensus state: %+v\n", ethConsensusState)
129+
123130
consensusState := ibcwasmtypes.ConsensusState{
124131
Data: ethConsensusStateBz,
125132
}
@@ -189,3 +196,6 @@ func (s *TestSuite) createDummyLightClient(ctx context.Context, cosmosChain *cos
189196
s.Require().NoError(err)
190197
s.Require().Equal(testvalues.FirstWasmClientID, ethereumLightClientID)
191198
}
199+
200+
func CreateEthereumClientAndConsensusState() {
201+
}

e2e/interchaintestv8/relayer_test.go

+138
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/hex"
66
"fmt"
77
"math/big"
8+
"strconv"
89
"strings"
910
"sync"
1011
"testing"
@@ -25,12 +26,15 @@ import (
2526
transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types"
2627
channeltypesv2 "github.com/cosmos/ibc-go/v10/modules/core/04-channel/v2/types"
2728

29+
"github.com/strangelove-ventures/interchaintest/v8/testutil"
30+
2831
"github.com/cosmos/solidity-ibc-eureka/abigen/ibcerc20"
2932
"github.com/cosmos/solidity-ibc-eureka/abigen/ics20transfer"
3033

3134
"github.com/srdtrk/solidity-ibc-eureka/e2e/v8/e2esuite"
3235
"github.com/srdtrk/solidity-ibc-eureka/e2e/v8/operator"
3336
"github.com/srdtrk/solidity-ibc-eureka/e2e/v8/testvalues"
37+
ethereumtypes "github.com/srdtrk/solidity-ibc-eureka/e2e/v8/types/ethereum"
3438
relayertypes "github.com/srdtrk/solidity-ibc-eureka/e2e/v8/types/relayer"
3539
)
3640

@@ -469,6 +473,140 @@ func (s *RelayerTestSuite) ICS20TransferERC20TokenBatchedAckToEthTest(
469473
}))
470474
}
471475

476+
func (s *RelayerTestSuite) TestMultiPeriodClientUpdateToCosmos() {
477+
ctx := context.Background()
478+
479+
s.SetupSuite(ctx, operator.ProofTypeGroth16) // Doesn't matter, since we won't relay to eth in this test
480+
481+
eth, simd := s.EthChain, s.CosmosChains[0]
482+
483+
ics20Address := ethcommon.HexToAddress(s.contractAddresses.Ics20Transfer)
484+
erc20Address := ethcommon.HexToAddress(s.contractAddresses.Erc20)
485+
486+
ethereumUserAddress := crypto.PubkeyToAddress(s.key.PublicKey)
487+
cosmosUserWallet := s.CosmosUsers[0]
488+
cosmosUserAddress := cosmosUserWallet.FormattedAddress()
489+
490+
transferAmount := big.NewInt(testvalues.TransferAmount)
491+
492+
s.Require().True(s.Run("Approve the ICS20Transfer.sol contract to spend the erc20 tokens", func() {
493+
tx, err := s.erc20Contract.Approve(s.GetTransactOpts(s.key, eth), ics20Address, transferAmount)
494+
s.Require().NoError(err)
495+
496+
receipt, err := eth.GetTxReciept(ctx, tx.Hash())
497+
s.Require().NoError(err)
498+
s.Require().Equal(ethtypes.ReceiptStatusSuccessful, receipt.Status)
499+
}))
500+
501+
s.Require().True(s.Run("Wait for period to change twice on Eth before relaying", func() {
502+
_, ethClientState := s.GetEthereumClientState(ctx, simd, testvalues.FirstWasmClientID)
503+
clientPeriod := ethClientState.LatestSlot / (ethClientState.EpochsPerSyncCommitteePeriod * ethClientState.SlotsPerEpoch)
504+
err := testutil.WaitForCondition(time.Minute*30, time.Second*30, func() (bool, error) {
505+
finalityUpdate, err := eth.BeaconAPIClient.GetFinalityUpdate()
506+
if err != nil {
507+
return false, err
508+
}
509+
510+
finalitySlot, err := strconv.Atoi(finalityUpdate.Data.FinalizedHeader.Beacon.Slot)
511+
if err != nil {
512+
return false, err
513+
}
514+
finalityPeriod := uint64(finalitySlot) / (ethClientState.EpochsPerSyncCommitteePeriod * ethClientState.SlotsPerEpoch)
515+
516+
return finalityPeriod == clientPeriod+2, nil
517+
})
518+
s.Require().NoError(err)
519+
}))
520+
521+
var (
522+
sendTxHash []byte
523+
escrowAddress ethcommon.Address
524+
)
525+
s.Require().True(s.Run("Send transfers on Ethereum", func() {
526+
timeout := uint64(time.Now().Add(30 * time.Minute).Unix())
527+
528+
msgSendTransfer := ics20transfer.IICS20TransferMsgsSendTransferMsg{
529+
Denom: erc20Address,
530+
SourceClient: testvalues.CustomClientID,
531+
DestPort: transfertypes.PortID,
532+
Amount: transferAmount,
533+
Receiver: cosmosUserAddress,
534+
TimeoutTimestamp: timeout,
535+
Memo: "",
536+
}
537+
538+
tx, err := s.ics20Contract.SendTransfer(s.GetTransactOpts(s.key, eth), msgSendTransfer)
539+
s.Require().NoError(err)
540+
541+
receipt, err := eth.GetTxReciept(ctx, tx.Hash())
542+
s.Require().NoError(err)
543+
s.Require().Equal(ethtypes.ReceiptStatusSuccessful, receipt.Status)
544+
545+
sendTxHash = tx.Hash().Bytes()
546+
547+
s.True(s.Run("Verify balances on Ethereum", func() {
548+
// User balance on Ethereum
549+
userBalance, err := s.erc20Contract.BalanceOf(nil, ethereumUserAddress)
550+
s.Require().NoError(err)
551+
s.Require().Equal(new(big.Int).Sub(testvalues.StartingERC20Balance, transferAmount), userBalance)
552+
553+
// Get the escrow address
554+
escrowAddress, err = s.ics20Contract.GetEscrow(nil, testvalues.CustomClientID)
555+
s.Require().NoError(err)
556+
557+
// ICS20 contract balance on Ethereum
558+
escrowBalance, err := s.erc20Contract.BalanceOf(nil, escrowAddress)
559+
s.Require().NoError(err)
560+
s.Require().Equal(transferAmount, escrowBalance)
561+
}))
562+
}))
563+
564+
s.Require().True(s.Run("Receive packets on Cosmos chain", func() {
565+
var relayTxBodyBz []byte
566+
s.Require().True(s.Run("Retrieve relay tx", func() {
567+
resp, err := s.RelayerClient.RelayByTx(context.Background(), &relayertypes.RelayByTxRequest{
568+
SrcChain: eth.ChainID.String(),
569+
DstChain: simd.Config().ChainID,
570+
SourceTxIds: [][]byte{sendTxHash},
571+
TargetClientId: testvalues.FirstWasmClientID,
572+
})
573+
s.Require().NoError(err)
574+
s.Require().NotEmpty(resp.Tx)
575+
s.Require().Empty(resp.Address)
576+
577+
relayTxBodyBz = resp.Tx
578+
579+
s.wasmFixtureGenerator.AddFixtureStep("receive_packets", ethereumtypes.RelayerMessages{
580+
RelayerTxBody: hex.EncodeToString(relayTxBodyBz),
581+
})
582+
}))
583+
584+
var ackTxHash []byte
585+
s.Require().True(s.Run("Broadcast relay tx", func() {
586+
resp := s.BroadcastSdkTxBody(ctx, simd, s.SimdRelayerSubmitter, 2_000_000, relayTxBodyBz)
587+
588+
var err error
589+
ackTxHash, err = hex.DecodeString(resp.TxHash)
590+
s.Require().NoError(err)
591+
s.Require().NotEmpty(ackTxHash)
592+
}))
593+
594+
s.Require().True(s.Run("Verify balances on Cosmos chain", func() {
595+
denomOnCosmos := transfertypes.NewDenom(s.contractAddresses.Erc20, transfertypes.NewHop(transfertypes.PortID, testvalues.FirstWasmClientID))
596+
597+
// User balance on Cosmos chain
598+
resp, err := e2esuite.GRPCQuery[banktypes.QueryBalanceResponse](ctx, simd, &banktypes.QueryBalanceRequest{
599+
Address: cosmosUserAddress,
600+
Denom: denomOnCosmos.IBCDenom(),
601+
})
602+
s.Require().NoError(err)
603+
s.Require().NotNil(resp.Balance)
604+
s.Require().Equal(transferAmount, resp.Balance.Amount.BigInt())
605+
s.Require().Equal(denomOnCosmos.IBCDenom(), resp.Balance.Denom)
606+
}))
607+
}))
608+
}
609+
472610
func (s *RelayerTestSuite) Test_10_RecvPacketToCosmos() {
473611
ctx := context.Background()
474612
s.RecvPacketToCosmosTest(ctx, 10, big.NewInt(testvalues.TransferAmount))

e2e/interchaintestv8/types/ethereum/types.gen.go

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ type ClientState struct {
2121
EpochsPerSyncCommitteePeriod uint64 `json:"epochs_per_sync_committee_period"`
2222
// The fork parameters
2323
ForkParameters ForkParameters `json:"fork_parameters"`
24+
// The genesis slot
25+
GenesisSlot uint64 `json:"genesis_slot"`
2426
// The time of genesis (unix timestamp)
2527
GenesisTime uint64 `json:"genesis_time"`
2628
// The genesis validators root
Binary file not shown.

justfile

+6-4
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,13 @@ generate-abi: build-contracts
8484
generate-fixtures-wasm: clean
8585
@echo "Generating fixtures... This may take a while."
8686
@echo "Generating recvPacket and acknowledgePacket groth16 fixtures..."
87-
cd e2e/interchaintestv8 && GENERATE_WASM_FIXTURES=true SP1_PROVER=network go test -v -run '^TestWithIbcEurekaTestSuite/TestICS20TransferERC20TokenfromEthereumToCosmosAndBack_Groth16$' -timeout 40m
87+
cd e2e/interchaintestv8 && GENERATE_WASM_FIXTURES=true go test -v -run '^TestWithIbcEurekaTestSuite/TestICS20TransferERC20TokenfromEthereumToCosmosAndBack_Groth16$' -timeout 60m
8888
@echo "Generating native SdkCoin recvPacket groth16 fixtures..."
89-
cd e2e/interchaintestv8 && GENERATE_WASM_FIXTURES=true SP1_PROVER=network go test -v -run '^TestWithIbcEurekaTestSuite/TestICS20TransferNativeCosmosCoinsToEthereumAndBack_Groth16$' -timeout 40m
89+
cd e2e/interchaintestv8 && GENERATE_WASM_FIXTURES=true go test -v -run '^TestWithIbcEurekaTestSuite/TestICS20TransferNativeCosmosCoinsToEthereumAndBack_Groth16$' -timeout 60m
9090
@echo "Generating timeoutPacket groth16 fixtures..."
91-
cd e2e/interchaintestv8 && GENERATE_WASM_FIXTURES=true SP1_PROVER=network go test -v -run '^TestWithIbcEurekaTestSuite/TestTimeoutPacketFromEth_Groth16$' -timeout 40m
91+
cd e2e/interchaintestv8 && GENERATE_WASM_FIXTURES=true go test -v -run '^TestWithIbcEurekaTestSuite/TestTimeoutPacketFromEth_Groth16$' -timeout 60m
92+
@echo "Generating multi-period client update fixtures..."
93+
cd e2e/interchaintestv8 && GENERATE_WASM_FIXTURES=true go test -v -run '^TestWithRelayerTestSuite/TestMultiPeriodClientUpdateToCosmos$' -timeout 60m
9294

9395
# Generate go types for the e2e tests from the etheruem light client code
9496
generate-ethereum-types:
@@ -104,7 +106,7 @@ generate-ethereum-types:
104106
# For example, `just test-e2e TestWithIbcEurekaTestSuite/TestDeploy_Groth16`
105107
test-e2e testname: clean
106108
@echo "Running {{testname}} test..."
107-
cd e2e/interchaintestv8 && go test -v -run '^{{testname}}$' -timeout 40m
109+
cd e2e/interchaintestv8 && go test -v -run '^{{testname}}$' -timeout 120m
108110

109111
# Run any e2e test in the IbcEurekaTestSuite using the test's name
110112
# For example, `just test-e2e-eureka TestDeploy_Groth16`

0 commit comments

Comments
 (0)