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

Commit

Permalink
Merge pull request #88 from strangelove-ventures/steve/abstractions
Browse files Browse the repository at this point in the history
ISM refactor, add support for custom ISMs
  • Loading branch information
misko9 authored Nov 8, 2023
2 parents df93c7f + 83692a3 commit bb23774
Show file tree
Hide file tree
Showing 35 changed files with 2,719 additions and 394 deletions.
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

0 comments on commit bb23774

Please sign in to comment.