Skip to content
This repository has been archived by the owner on Aug 1, 2024. It is now read-only.

ISM refactor, add support for custom ISMs #88

Merged
merged 2 commits into from
Nov 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
243 changes: 90 additions & 153 deletions docs/proto/proto-docs.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions interchaintest/helpers/ism.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"github.com/strangelove-ventures/hyperlane-cosmos/x/ism/types/message_id_multisig"
)

func GetDefaultIsms(counterChains ...*counterchain.CounterChain) (isms []*ismtypes.Ism) {
func GetDefaultIsms(counterChains ...*counterchain.CounterChain) (isms []*ismtypes.DefaultIsm) {
for _, counterChain := range counterChains {
var valSet []string
for _, val := range counterChain.ValSet.Vals {
Expand Down Expand Up @@ -51,7 +51,7 @@ func GetDefaultIsms(counterChains ...*counterchain.CounterChain) (isms []*ismtyp
},
)
}
isms = append(isms, &ismtypes.Ism{
isms = append(isms, &ismtypes.DefaultIsm{
Origin: counterChain.Domain,
AbstractIsm: ism,
})
Expand Down
3 changes: 1 addition & 2 deletions interchaintest/tests/cosmos_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"strings"
"testing"
"time"

"cosmossdk.io/math"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
Expand Down Expand Up @@ -271,7 +271,6 @@ func TestHyperlaneCosmosE2E(t *testing.T) {
require.NoError(t, err)
require.Equal(t, simd1Oracle.FormattedAddress(), oracleEvtAddr)


// This should succeed, and we verify the events contain the expected domain/exchange rate/gas price.
setGasOutput := helpers.CallSetGasPriceMsg(t, ctx, simd1, simd1Oracle.KeyName(), igpId, destDomainStr, gasPrice.String(), exchangeRate.String())
setGasTxHash2 := helpers.ParseTxHash(string(setGasOutput))
Expand Down
4 changes: 3 additions & 1 deletion proto/hyperlane/ism/v1/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@ option go_package = "github.com/strangelove-ventures/hyperlane-cosmos/x/ism/type
// Hyperlane ISM's keeper genesis state
message GenesisState {
// Genesis default ISM
repeated Ism default_ism = 1 [ (gogoproto.nullable) = false ];
repeated DefaultIsm default_ism = 1 [ (gogoproto.nullable) = false ];
// Custom Isms
repeated CustomIsm custom_ism = 2 [ (gogoproto.nullable) = false ];
}
10 changes: 8 additions & 2 deletions proto/hyperlane/ism/v1/ism.proto
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ import "google/protobuf/any.proto";
option go_package = "github.com/strangelove-ventures/hyperlane-cosmos/x/ism/types";

// Hyperlane's default ISM
message Ism {
message DefaultIsm {
uint32 origin = 1;
google.protobuf.Any abstract_ism = 2;
}
}

// Hyperlane's custom ISM
message CustomIsm {
uint32 index = 1;
google.protobuf.Any abstract_ism = 2;
}
25 changes: 24 additions & 1 deletion proto/hyperlane/ism/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ service Query {
returns (QueryAllDefaultIsmsResponse) {
option (google.api.http).get = "/hyperlane/ism/v1/all_default_isms";
}
// Get custom ISM
rpc CustomIsm(QueryCustomIsmRequest) returns (QueryCustomIsmResponse) {
option (google.api.http).get = "/hyperlane/ism/v1/custom_ism";
}
// Get all custom ISMs
rpc AllCustomIsms(QueryAllCustomIsmsRequest)
returns (QueryAllCustomIsmsResponse) {
option (google.api.http).get = "/hyperlane/ism/v1/all_custom_isms";
}
}

// QueryDefaultIsmRequest is the request type for the DefaultIsm RPC method.
Expand All @@ -33,4 +42,18 @@ message QueryAllDefaultIsmsRequest {}

// QueryAllDefaultIsmResponse is the response type for the AllDefaultIsms RPC
// method.
message QueryAllDefaultIsmsResponse { repeated Ism default_isms = 1; }
message QueryAllDefaultIsmsResponse { repeated DefaultIsm default_isms = 1; }

// QueryCustomIsmRequest is the request type for the CustomIsm RPC method.
message QueryCustomIsmRequest { uint32 ism_id = 1; }

// QueryCustomIsmResponse is the response type for the CustomIsm RPC method.
message QueryCustomIsmResponse { google.protobuf.Any custom_ism = 1; }

// QueryAllCustomIsmRequest is the request type for the AllCustomIsms RPC
// method.
message QueryAllCustomIsmsRequest {}

// QueryAllCustomIsmResponse is the response type for the AllCustomIsms RPC
// method.
message QueryAllCustomIsmsResponse { repeated CustomIsm custom_isms = 1; }
40 changes: 37 additions & 3 deletions proto/hyperlane/ism/v1/tx.proto
Original file line number Diff line number Diff line change
@@ -1,21 +1,55 @@
syntax = "proto3";
package hyperlane.ism.v1;

import "amino/amino.proto";
import "cosmos/msg/v1/msg.proto";
import "cosmos_proto/cosmos.proto";
import "gogoproto/gogo.proto";
import "google/protobuf/any.proto";
import "hyperlane/ism/v1/ism.proto";

option go_package = "github.com/strangelove-ventures/hyperlane-cosmos/x/ism/types";

// Msg defines the hyperlane ISM Msg service.
service Msg {
option (cosmos.msg.v1.service) = true;

// Create a custom ISM
rpc CreateIsm(MsgCreateIsm) returns (MsgCreateIsmResponse);

// SetDefaultIsm defines a rpc handler method for MsgSetDefaultIsm.
rpc SetDefaultIsm(MsgSetDefaultIsm) returns (MsgSetDefaultIsmResponse);
}

// MsgSetDefaultIsm defines the request type for the SetDefaultIsm rpc.
message MsgSetDefaultIsm {
string signer = 1;
repeated Ism isms = 2;
option (cosmos.msg.v1.signer) = "sender";
option (amino.name) = "hyperlane-ism/MsgSetDefaultIsm";

option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

string signer = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ];
repeated DefaultIsm isms = 2;
}

// MsgSetDefaultIsmResponse defines the Msg/SetDefaultIsm response type
message MsgSetDefaultIsmResponse {}
message MsgSetDefaultIsmResponse {}

// MsgCreateIsm defines the request type to create a hyperlane ISM
message MsgCreateIsm {
option (cosmos.msg.v1.signer) = "sender";
option (amino.name) = "hyperlane-ism/MsgCreateIsm";

option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

string signer = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ];
google.protobuf.Any ism = 2;
}

// MsgCreateIsmResponse deines the MsgCreateIsm response type
message MsgCreateIsmResponse {
// The unique ID assigned to the newly created ISM
uint32 ism_id = 1;
}
2 changes: 1 addition & 1 deletion x/igp/keeper/test_data_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ var messages = [...]string{
"000000045a000000010000000000000000000000009311cee522a7c122b843b66cc31c6a63e2f926410000a86a0000000000000000000000002a925cd8a5d919c5c6599633090c37fe38a561b648656c6c6f21",
}

var defaultIsms = []*types.Ism{
var defaultIsms = []*types.DefaultIsm{
{
Origin: 1, // Ethereum origin
AbstractIsm: types.MustPackAbstractIsm(
Expand Down
Empty file removed x/igp/placeholder
Empty file.
68 changes: 60 additions & 8 deletions x/ism/keeper/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,50 @@ import (
"github.com/strangelove-ventures/hyperlane-cosmos/x/ism/types"
)

// InitGenesis initializes the hyperlane mailbox module's state from a provided genesis
// InitGenesis initializes the hyperlane ISM module's state from a provided genesis
// state.
func (k Keeper) InitGenesis(ctx sdk.Context, gs types.GenesisState) error {
for _, originIsm := range gs.DefaultIsm {
ism, err := types.UnpackAbstractIsm(originIsm.AbstractIsm)
if err != nil {
return err
}
k.defaultIsm[originIsm.Origin] = ism
err = k.storeDefaultIsm(ctx, originIsm.Origin, ism)
if err != nil {
return err
}
}
for _, customIsm := range gs.CustomIsm {
ism, err := types.UnpackAbstractIsm(customIsm.AbstractIsm)
if err != nil {
return err
}
err = k.storeCustomIsm(ctx, customIsm.Index, ism)
if err != nil {
return err
}
}
return nil
}

// ExportGenesis returns the hyperlane mailbox module's exported genesis.
// ExportGenesis returns the hyperlane ISM module's exported genesis.
func (k Keeper) ExportGenesis(ctx sdk.Context) types.GenesisState {
return types.GenesisState{
DefaultIsm: k.ExportDefaultIsms(ctx),
CustomIsm: k.ExportCustomIsms(ctx),
}
}

// ExportDefaultIsms return the default ISMs
func (k Keeper) ExportDefaultIsms(ctx sdk.Context) []types.DefaultIsm {
store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, []byte(types.KeyOriginsDefaultIsm))
defer iterator.Close()

var genesisState types.GenesisState
var defaultIsms []types.DefaultIsm
for ; iterator.Valid(); iterator.Next() {
originBytes := bytes.TrimPrefix(iterator.Key(), []byte(fmt.Sprintf("%s/", types.KeyOriginsDefaultIsm)))
origin, err := strconv.ParseUint(string(originBytes), 10, 32)
originBz := bytes.TrimPrefix(iterator.Key(), []byte(fmt.Sprintf("%s/", types.KeyOriginsDefaultIsm)))
origin, err := strconv.ParseUint(string(originBz), 10, 32)
if err != nil {
panic(err)
}
Expand All @@ -45,11 +66,42 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) types.GenesisState {
if err != nil {
panic(err)
}
genesisState.DefaultIsm = append(genesisState.DefaultIsm, types.Ism{
defaultIsms = append(defaultIsms, types.DefaultIsm{
Origin: uint32(origin),
AbstractIsm: ismAny,
})
}

return genesisState
return defaultIsms
}

// ExportCustomIsms return the custom ISMs
func (k Keeper) ExportCustomIsms(ctx sdk.Context) []types.CustomIsm {
store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, []byte(types.KeyCustomIsm))
defer iterator.Close()

var customIsms []types.CustomIsm
for ; iterator.Valid(); iterator.Next() {
indexBz := bytes.TrimPrefix(iterator.Key(), []byte(fmt.Sprintf("%s/", types.KeyCustomIsm)))
index, err := strconv.ParseUint(string(indexBz), 10, 32)
if err != nil {
panic(err)
}
var ism types.AbstractIsm
err = k.cdc.UnmarshalInterface(iterator.Value(), &ism)
if err != nil {
panic(err)
}
ismAny, err := types.PackAbstractIsm(ism)
if err != nil {
panic(err)
}
customIsms = append(customIsms, types.CustomIsm{
Index: uint32(index),
AbstractIsm: ismAny,
})
}

return customIsms
}
46 changes: 42 additions & 4 deletions x/ism/keeper/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,28 @@ func (suite *KeeperTestSuite) TestGenesis() {
_, err := suite.msgServer.SetDefaultIsm(suite.ctx, msg)
suite.Require().NoError(err)

customIsmMsg1 := types.NewMsgCreateIsm(signer, defaultIsms[0].AbstractIsm)
_, err = suite.msgServer.CreateIsm(suite.ctx, customIsmMsg1)
suite.Require().NoError(err)

customIsmMsg2 := types.NewMsgCreateIsm(signer, defaultIsms[1].AbstractIsm)
_, err = suite.msgServer.CreateIsm(suite.ctx, customIsmMsg2)
suite.Require().NoError(err)

customIsmMsg3 := types.NewMsgCreateIsm(signer, defaultIsms[2].AbstractIsm)
_, err = suite.msgServer.CreateIsm(suite.ctx, customIsmMsg3)
suite.Require().NoError(err)

gs := suite.keeper.ExportGenesis(suite.ctx)
for i := 0; i < len(defaultIsms); i++ {
expectedIsm := types.MustUnpackAbstractIsm(defaultIsms[i].AbstractIsm)
actualIsm := types.MustUnpackAbstractIsm(gs.DefaultIsm[i].AbstractIsm)
actualDefaultIsm := types.MustUnpackAbstractIsm(gs.DefaultIsm[i].AbstractIsm)
suite.Require().Equal(defaultIsms[i].Origin, gs.DefaultIsm[i].Origin)
suite.Require().Equal(expectedIsm, actualIsm)
suite.Require().Equal(expectedIsm, actualDefaultIsm)

actualCustomIsm := types.MustUnpackAbstractIsm(gs.CustomIsm[i].AbstractIsm)
suite.Require().Equal(uint32(i+1), gs.CustomIsm[i].Index)
suite.Require().Equal(expectedIsm, actualCustomIsm)
}

suite.SetupTest()
Expand All @@ -30,14 +46,36 @@ func (suite *KeeperTestSuite) TestGenesis() {
suite.Require().NoError(err)
metadata, err := hex.DecodeString(metadatas[0])
suite.Require().NoError(err)
pass, err := suite.keeper.Verify(metadata, message)
pass, err := suite.keeper.Verify(suite.ctx, metadata, message)
suite.Require().Error(err)
suite.Require().False(pass)

err = suite.keeper.InitGenesis(suite.ctx, gs)
suite.Require().NoError(err)

pass, err = suite.keeper.Verify(metadata, message)
pass, err = suite.keeper.Verify(suite.ctx, metadata, message)
suite.Require().NoError(err)
suite.Require().True(pass)

for i := 0; i < len(defaultIsms); i++ {
expectedIsm := types.MustUnpackAbstractIsm(defaultIsms[i].AbstractIsm)

defaultIsmReq := types.QueryOriginsDefaultIsmRequest{
Origin: defaultIsms[i].Origin,
}
defaultIsmResp, err := suite.queryClient.OriginsDefaultIsm(suite.ctx, &defaultIsmReq)
suite.Require().NoError(err)
actualDefaultIsm := types.MustUnpackAbstractIsm(defaultIsmResp.DefaultIsm)
suite.Require().Equal(defaultIsms[i].Origin, gs.DefaultIsm[i].Origin)
suite.Require().Equal(expectedIsm, actualDefaultIsm)

customIsmReq := types.QueryCustomIsmRequest{
IsmId: uint32(i+1),
}
customIsmResp, err := suite.queryClient.CustomIsm(suite.ctx, &customIsmReq)
suite.Require().NoError(err)
actualCustomIsm := types.MustUnpackAbstractIsm(customIsmResp.CustomIsm)
suite.Require().Equal(uint32(i+1), gs.CustomIsm[i].Index)
suite.Require().Equal(expectedIsm, actualCustomIsm)
}
}
Loading
Loading