Skip to content

Commit

Permalink
feat: add ethereum light client (#3586)
Browse files Browse the repository at this point in the history
* feat: add ethereum light client

* rename to eth

* Fix import

---------

Co-authored-by: Eric Warehime <[email protected]>
  • Loading branch information
gjermundgaraba and Eric-Warehime authored Mar 3, 2025
1 parent 0eee1cd commit 5aa09c9
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 0 deletions.
7 changes: 7 additions & 0 deletions app/upgrades/v23/constants.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package v23

import (
_ "embed"

ibcwasmtypes "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/v10/types"

"cosmossdk.io/store/types"
Expand All @@ -12,8 +14,13 @@ const (
// UpgradeName defines the on-chain upgrade name.
UpgradeName = "v23"
IbcFeeStoreKey = "feeibc"

ExpectedEthLightClientChecksum = "f82549f5bc8adaef18e5ce4f5b68269947343742c938dac322faf1583319172c"
)

//go:embed cw_ics08_wasm_eth.wasm.gz
var ethWasmLightClient []byte

var Upgrade = upgrades.Upgrade{
UpgradeName: UpgradeName,
CreateUpgradeHandler: CreateUpgradeHandler,
Expand Down
Binary file added app/upgrades/v23/cw_ics08_wasm_eth.wasm.gz
Binary file not shown.
29 changes: 29 additions & 0 deletions app/upgrades/v23/upgrades.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ package v23

import (
"context"
"encoding/hex"
"fmt"

ibcwasmkeeper "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/v10/keeper"
ibcwasmtypes "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/v10/types"
ibctmtypes "github.com/cosmos/ibc-go/v10/modules/light-clients/07-tendermint"

Expand Down Expand Up @@ -31,11 +34,37 @@ func CreateUpgradeHandler(
}

// Set IBC Client AllowedClients
ctx.Logger().Info("Setting IBC Client AllowedClients")
params := keepers.IBCKeeper.ClientKeeper.GetParams(ctx)
params.AllowedClients = []string{ibctmtypes.ModuleName, ibcwasmtypes.ModuleName}
keepers.IBCKeeper.ClientKeeper.SetParams(ctx, params)

// Add Eth Light Wasm Light Client
ctx.Logger().Info("Adding Eth Light Wasm Light Client")
if err := AddEthLightWasmLightClient(ctx, keepers.WasmClientKeeper); err != nil {
ctx.Logger().Error("Error adding Eth Light Wasm Light Client", "message", err.Error())
return nil, err
}

ctx.Logger().Info("Upgrade v23 complete")
return vm, nil
}
}

func AddEthLightWasmLightClient(ctx context.Context, wasmKeeper ibcwasmkeeper.Keeper) error {
resp, err := wasmKeeper.StoreCode(ctx, &ibcwasmtypes.MsgStoreCode{
Signer: wasmKeeper.GetAuthority(),
WasmByteCode: ethWasmLightClient,
})
if err != nil {
return errorsmod.Wrap(err, "failed to store eth wasm light client during upgrade")
}

actualChecksum := hex.EncodeToString(resp.Checksum)

if hex.EncodeToString(resp.Checksum) != ExpectedEthLightClientChecksum {
return fmt.Errorf("checksum mismatch: expected %s, got %s", ExpectedEthLightClientChecksum, actualChecksum)
}

return nil
}
59 changes: 59 additions & 0 deletions app/upgrades/v23/upgrades_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package v23_test

import (
"testing"
"time"

"github.com/stretchr/testify/require"

tmproto "github.com/cometbft/cometbft/proto/tendermint/types"

ibcwasmtypes "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/v10/types"
clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types"
ibcexported "github.com/cosmos/ibc-go/v10/modules/core/exported"

"github.com/cosmos/gaia/v23/app/helpers"
v23 "github.com/cosmos/gaia/v23/app/upgrades/v23"
)

const (
clientStateJSON = `{"@type":"/ibc.lightclients.wasm.v1.ClientState","data":"eyJjaGFpbl9pZCI6MzE1MTkwOCwiZXBvY2hzX3Blcl9zeW5jX2NvbW1pdHRlZV9wZXJpb2QiOjgsImZvcmtfcGFyYW1ldGVycyI6eyJhbHRhaXIiOnsiZXBvY2giOjAsInZlcnNpb24iOiIyMDAwMDAzOCJ9LCJiZWxsYXRyaXgiOnsiZXBvY2giOjAsInZlcnNpb24iOiIzMDAwMDAzOCJ9LCJjYXBlbGxhIjp7ImVwb2NoIjowLCJ2ZXJzaW9uIjoiNDAwMDAwMzgifSwiZGVuZWIiOnsiZXBvY2giOjAsInZlcnNpb24iOiI1MDAwMDAzOCJ9LCJnZW5lc2lzX2ZvcmtfdmVyc2lvbiI6IjEwMDAwMDM4IiwiZ2VuZXNpc19zbG90IjowfSwiZ2VuZXNpc190aW1lIjoxNzQwODI3NDA3LCJnZW5lc2lzX3ZhbGlkYXRvcnNfcm9vdCI6ImQ2MWVhNDg0ZmViYWNmYWU1Mjk4ZDUyYTJiNTgxZjNlMzA1YTUxZjMxMTJhOTI0MWI5NjhkY2NmMDE5ZjdiMTEiLCJpYmNfY29tbWl0bWVudF9zbG90IjoiMHgxMjYwOTQ0NDg5MjcyOTg4ZDlkZjI4NTE0OWI1YWExYjBmNDhmMjEzNmQ2ZjQxNjE1OWY4NDBhM2UwNzQ3NjAwIiwiaWJjX2NvbnRyYWN0X2FkZHJlc3MiOiIweDI5M2MxOGUwOWU1NTA0ZWJjZTE3ZGFhN2YzZDY2MmM4YjliZjZkNzUiLCJpc19mcm96ZW4iOmZhbHNlLCJsYXRlc3Rfc2xvdCI6MzIsIm1pbl9zeW5jX2NvbW1pdHRlZV9wYXJ0aWNpcGFudHMiOjMyLCJzZWNvbmRzX3Blcl9zbG90Ijo2LCJzbG90c19wZXJfZXBvY2giOjh9","checksum":"+CVJ9byK2u8Y5c5PW2gmmUc0N0LJONrDIvrxWDMZFyw=","latest_height":{"revision_number":"0","revision_height":"32"}}`
consensusStateJSON = `{"@type":"/ibc.lightclients.wasm.v1.ConsensusState","data":"eyJjdXJyZW50X3N5bmNfY29tbWl0dGVlIjoiMHg4MTQ1ZjkyZDEzMTcxNTNlNmJiODFhOTAzZGI2ZjBiMTBjNTBhOTM2ODNmNGMyYWFiMzVlOWE4YTRiYjI4MzMyMzQyNWZiNTZhNDdkOGIzMGE5ZWZkNTA5YzhhZjE0ZTEiLCJuZXh0X3N5bmNfY29tbWl0dGVlIjoiMHg4MTQ1ZjkyZDEzMTcxNTNlNmJiODFhOTAzZGI2ZjBiMTBjNTBhOTM2ODNmNGMyYWFiMzVlOWE4YTRiYjI4MzMyMzQyNWZiNTZhNDdkOGIzMGE5ZWZkNTA5YzhhZjE0ZTEiLCJzbG90IjozMiwic3RhdGVfcm9vdCI6IjB4MjI4NTQzYWVlYzk0NjA5YjQwOGUyNzI0NjIzZjgyMGExNjFhYmY5OWRkODMyNzQ4MWQ1NGNmYmUyNzAyOTE1ZCIsInN0b3JhZ2Vfcm9vdCI6IjB4MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCIsInRpbWVzdGFtcCI6MTc0MDgyNzU5OX0="}`
)

func TestAddEthLightWasmLightClient(t *testing.T) {
gaiaApp := helpers.Setup(t)
ctx := gaiaApp.NewUncachedContext(true, tmproto.Header{
Time: time.Unix(1740829624, 0),
})

err := v23.AddEthLightWasmLightClient(ctx, gaiaApp.WasmClientKeeper)
require.NoError(t, err)

// check that the checksum is as expected
queryChecksumsResp, err := gaiaApp.WasmClientKeeper.Checksums(ctx, &ibcwasmtypes.QueryChecksumsRequest{})
require.NoError(t, err)
require.Len(t, queryChecksumsResp.Checksums, 1)
require.Equal(t, v23.ExpectedEthLightClientChecksum, queryChecksumsResp.Checksums[0])

var clientState ibcexported.ClientState
err = gaiaApp.AppCodec().UnmarshalInterfaceJSON([]byte(clientStateJSON), &clientState)
require.NoError(t, err)

var consensusState ibcexported.ConsensusState
err = gaiaApp.AppCodec().UnmarshalInterfaceJSON([]byte(consensusStateJSON), &consensusState)
require.NoError(t, err)

createMsg, err := clienttypes.NewMsgCreateClient(clientState, consensusState, "")
require.NoError(t, err)

// create a light client
createClientResp, err := gaiaApp.IBCKeeper.CreateClient(ctx, createMsg)
require.NoError(t, err)
require.Equal(t, "08-wasm-0", createClientResp.ClientId)

// Make a call into the actual light client to verify we can call the light client contract
timestamp, err := gaiaApp.IBCKeeper.ClientKeeper.GetClientTimestampAtHeight(ctx, "08-wasm-0", clienttypes.NewHeight(0, 32))
require.NoError(t, err)
require.Equal(t, uint64(1740827599000000000), timestamp)
}

0 comments on commit 5aa09c9

Please sign in to comment.