From b61f8dacb94889215496aa65c877a5732419841c Mon Sep 17 00:00:00 2001 From: Kyle Date: Wed, 18 Oct 2023 16:06:11 -0400 Subject: [PATCH] cosmos e2e with multiple messages --- docs/proto/proto-docs.md | 221 +++++++---------- interchaintest/helpers/announce.go | 2 +- interchaintest/tests/announcement_test.go | 13 +- interchaintest/tests/cosmos_e2e_test.go | 246 ++++++++++++++++++- interchaintest/tests/helpers.go | 5 +- proto/hyperlane/announce/v1/genesis.proto | 7 +- proto/hyperlane/announce/v1/types.proto | 11 +- x/announce/client/cli/tx.go | 2 +- x/announce/keeper/genesis.go | 61 ++++- x/announce/keeper/grpc_query.go | 8 +- x/announce/keeper/grpc_query_test.go | 1 + x/announce/keeper/msg_server.go | 7 - x/announce/keeper/store.go | 38 +-- x/announce/types/genesis.pb.go | 81 ++++++- x/announce/types/types.pb.go | 275 ++++++++++++++++++---- x/mailbox/keeper/keeper.go | 4 +- 16 files changed, 725 insertions(+), 257 deletions(-) diff --git a/docs/proto/proto-docs.md b/docs/proto/proto-docs.md index 5178450..7407247 100644 --- a/docs/proto/proto-docs.md +++ b/docs/proto/proto-docs.md @@ -4,119 +4,95 @@ ## Table of Contents -- [hyperlane/ism/v1/ism.proto](#hyperlane/ism/v1/ism.proto) - - [Ism](#hyperlane.ism.v1.Ism) +- [hyperlane/announce/v1/types.proto](#hyperlane/announce/v1/types.proto) + - [GenesisAnnouncement](#hyperlane.announce.v1.GenesisAnnouncement) + - [StorageMetadata](#hyperlane.announce.v1.StorageMetadata) + - [StoredAnnouncement](#hyperlane.announce.v1.StoredAnnouncement) + - [StoredAnnouncements](#hyperlane.announce.v1.StoredAnnouncements) -- [hyperlane/ism/v1/genesis.proto](#hyperlane/ism/v1/genesis.proto) - - [GenesisState](#hyperlane.ism.v1.GenesisState) +- [hyperlane/announce/v1/genesis.proto](#hyperlane/announce/v1/genesis.proto) + - [GenesisState](#hyperlane.announce.v1.GenesisState) -- [hyperlane/ism/v1/legacy_multisig.proto](#hyperlane/ism/v1/legacy_multisig.proto) - - [LegacyMultiSig](#hyperlane.ism.v1.LegacyMultiSig) +- [hyperlane/announce/v1/query.proto](#hyperlane/announce/v1/query.proto) + - [GetAnnouncedStorageLocationsRequest](#hyperlane.announce.v1.GetAnnouncedStorageLocationsRequest) + - [GetAnnouncedStorageLocationsResponse](#hyperlane.announce.v1.GetAnnouncedStorageLocationsResponse) + - [GetAnnouncedValidatorsRequest](#hyperlane.announce.v1.GetAnnouncedValidatorsRequest) + - [GetAnnouncedValidatorsResponse](#hyperlane.announce.v1.GetAnnouncedValidatorsResponse) -- [hyperlane/ism/v1/merkle_root_multisig.proto](#hyperlane/ism/v1/merkle_root_multisig.proto) - - [MerkleRootMultiSig](#hyperlane.ism.v1.MerkleRootMultiSig) + - [Query](#hyperlane.announce.v1.Query) -- [hyperlane/ism/v1/message_id_multisig.proto](#hyperlane/ism/v1/message_id_multisig.proto) - - [MessageIdMultiSig](#hyperlane.ism.v1.MessageIdMultiSig) +- [hyperlane/announce/v1/tx.proto](#hyperlane/announce/v1/tx.proto) + - [MsgAnnouncement](#hyperlane.announce.v1.MsgAnnouncement) + - [MsgAnnouncementResponse](#hyperlane.announce.v1.MsgAnnouncementResponse) -- [hyperlane/ism/v1/query.proto](#hyperlane/ism/v1/query.proto) - - [QueryAllDefaultIsmsRequest](#hyperlane.ism.v1.QueryAllDefaultIsmsRequest) - - [QueryAllDefaultIsmsResponse](#hyperlane.ism.v1.QueryAllDefaultIsmsResponse) - - [QueryOriginsDefaultIsmRequest](#hyperlane.ism.v1.QueryOriginsDefaultIsmRequest) - - [QueryOriginsDefaultIsmResponse](#hyperlane.ism.v1.QueryOriginsDefaultIsmResponse) - - - [Query](#hyperlane.ism.v1.Query) - -- [hyperlane/ism/v1/tx.proto](#hyperlane/ism/v1/tx.proto) - - [MsgSetDefaultIsm](#hyperlane.ism.v1.MsgSetDefaultIsm) - - [MsgSetDefaultIsmResponse](#hyperlane.ism.v1.MsgSetDefaultIsmResponse) - - - [Msg](#hyperlane.ism.v1.Msg) + - [Msg](#hyperlane.announce.v1.Msg) - [Scalar Value Types](#scalar-value-types) - +

Top

-## hyperlane/ism/v1/ism.proto +## hyperlane/announce/v1/types.proto - + -### Ism -Hyperlane's default ISM +### GenesisAnnouncement +Genesis helper type for Hyperlane's Announcement. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `origin` | [uint32](#uint32) | | | -| `abstract_ism` | [google.protobuf.Any](#google.protobuf.Any) | | | - - - - - - - - - - - - +| `announcement` | [StoredAnnouncement](#hyperlane.announce.v1.StoredAnnouncement) | | | +| `validator` | [bytes](#bytes) | | The validator (in eth address format) that announced | - -

Top

-## hyperlane/ism/v1/genesis.proto + - - -### GenesisState -Hyperlane ISM's keeper genesis state +### StorageMetadata +Helper type for Hyperlane's getAnnouncedStorageLocations. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `default_ism` | [Ism](#hyperlane.ism.v1.Ism) | repeated | Genesis default ISM | +| `metadata` | [string](#string) | repeated | | - - + - +### StoredAnnouncement +Helper type for Hyperlane's Announcement. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `storage_location` | [string](#string) | | location where signatures will be stored | - -

Top

-## hyperlane/ism/v1/legacy_multisig.proto - + -### LegacyMultiSig -LegacyMultiSig ISM for a specific origin +### StoredAnnouncements +Helper type for Hyperlane's Announcement. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_pub_keys` | [string](#string) | repeated | Validator pub keys | -| `threshold` | [uint32](#uint32) | | number of validators required | +| `announcement` | [StoredAnnouncement](#hyperlane.announce.v1.StoredAnnouncement) | repeated | | @@ -132,23 +108,22 @@ LegacyMultiSig ISM for a specific origin - +

Top

-## hyperlane/ism/v1/merkle_root_multisig.proto +## hyperlane/announce/v1/genesis.proto - + -### MerkleRootMultiSig -MerkleRootMultiSig ISM for a specific origin +### GenesisState +Hyperlane Announce's keeper genesis state | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_pub_keys` | [string](#string) | repeated | Validator pub keys | -| `threshold` | [uint32](#uint32) | | number of validators required | +| `announcements` | [GenesisAnnouncement](#hyperlane.announce.v1.GenesisAnnouncement) | repeated | | @@ -164,96 +139,66 @@ MerkleRootMultiSig ISM for a specific origin - +

Top

-## hyperlane/ism/v1/message_id_multisig.proto +## hyperlane/announce/v1/query.proto - + -### MessageIdMultiSig -MessageIdMultiSig ISM for a specific origin +### GetAnnouncedStorageLocationsRequest +GetAnnouncedStorageLocationsRequest is the request type for the +GetAnnouncedStorageLocations RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_pub_keys` | [string](#string) | repeated | Validator pub keys | -| `threshold` | [uint32](#uint32) | | number of validators required | +| `validator` | [bytes](#bytes) | repeated | list of validators where each validator is in hex-encoded eth address format (20 bytes) | - - - - - - - - - - - -

Top

- -## hyperlane/ism/v1/query.proto - + - - -### QueryAllDefaultIsmsRequest -QueryAllDefaultIsmRequest is the request type for the AllDefaultIsms RPC -method. - - - - - - - - -### QueryAllDefaultIsmsResponse -QueryAllDefaultIsmResponse is the response type for the AllDefaultIsms RPC -method. +### GetAnnouncedStorageLocationsResponse +GetAnnouncedStorageLocationsResponse is the response type for the +GetAnnouncedStorageLocations RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `default_isms` | [Ism](#hyperlane.ism.v1.Ism) | repeated | | - +| `metadata` | [StorageMetadata](#hyperlane.announce.v1.StorageMetadata) | repeated | | - -### QueryOriginsDefaultIsmRequest -QueryDefaultIsmRequest is the request type for the DefaultIsm RPC method. + - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `origin` | [uint32](#uint32) | | | +### GetAnnouncedValidatorsRequest +GetAnnouncedValidatorsRequest is the request type for the +GetAnnouncedValidators RPC method. - + -### QueryOriginsDefaultIsmResponse -QueryDefaultIsmResponse is the response type for the DefaultIsm RPC method. +### GetAnnouncedValidatorsResponse +GetAnnouncedValidatorsResponse is the response type for the +GetAnnouncedValidators RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `default_ism` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `validator` | [string](#string) | repeated | list of validators where each validator is in hex-encoded eth address format (20 bytes) | @@ -266,47 +211,49 @@ QueryDefaultIsmResponse is the response type for the DefaultIsm RPC method. - + ### Query -Query service for hyperlane ISM module +Query service for hyperlane announce module | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `OriginsDefaultIsm` | [QueryOriginsDefaultIsmRequest](#hyperlane.ism.v1.QueryOriginsDefaultIsmRequest) | [QueryOriginsDefaultIsmResponse](#hyperlane.ism.v1.QueryOriginsDefaultIsmResponse) | Get current default multisig ISM for an origin | GET|/hyperlane/ism/v1/origins_default_ism| -| `AllDefaultIsms` | [QueryAllDefaultIsmsRequest](#hyperlane.ism.v1.QueryAllDefaultIsmsRequest) | [QueryAllDefaultIsmsResponse](#hyperlane.ism.v1.QueryAllDefaultIsmsResponse) | Get all current default multisig ISMs | GET|/hyperlane/ism/v1/all_default_isms| +| `GetAnnouncedStorageLocations` | [GetAnnouncedStorageLocationsRequest](#hyperlane.announce.v1.GetAnnouncedStorageLocationsRequest) | [GetAnnouncedStorageLocationsResponse](#hyperlane.announce.v1.GetAnnouncedStorageLocationsResponse) | Gets the announced storage locations (where signatures are stored) for the requested validators | GET|/hyperlane/announce/v1/get_announced_storage_locations| +| `GetAnnouncedValidators` | [GetAnnouncedValidatorsRequest](#hyperlane.announce.v1.GetAnnouncedValidatorsRequest) | [GetAnnouncedValidatorsResponse](#hyperlane.announce.v1.GetAnnouncedValidatorsResponse) | Gets a list of validators that have made announcements | GET|/hyperlane/announce/v1/get_announced_validators| - +

Top

-## hyperlane/ism/v1/tx.proto +## hyperlane/announce/v1/tx.proto - + -### MsgSetDefaultIsm -MsgSetDefaultIsm defines the request type for the SetDefaultIsm rpc. +### MsgAnnouncement +MsgAnnouncement Announces a validator signature storage location | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `signer` | [string](#string) | | | -| `isms` | [Ism](#hyperlane.ism.v1.Ism) | repeated | | +| `sender` | [string](#string) | | | +| `validator` | [bytes](#bytes) | | The validator (in eth address format) that is announcing its storage location | +| `storage_location` | [string](#string) | | location where signatures will be stored | +| `signature` | [bytes](#bytes) | | signed validator announcement | - + -### MsgSetDefaultIsmResponse -MsgSetDefaultIsmResponse defines the Msg/SetDefaultIsm response type +### MsgAnnouncementResponse +MsgAnnouncementResponse defines the MsgAnnouncementResponse response type. @@ -319,14 +266,14 @@ MsgSetDefaultIsmResponse defines the Msg/SetDefaultIsm response type - + ### Msg -Msg defines the hyperlane ISM Msg service. +Msg defines the hyperlane announce Msg service. | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `SetDefaultIsm` | [MsgSetDefaultIsm](#hyperlane.ism.v1.MsgSetDefaultIsm) | [MsgSetDefaultIsmResponse](#hyperlane.ism.v1.MsgSetDefaultIsmResponse) | SetDefaultIsm defines a rpc handler method for MsgSetDefaultIsm. | | +| `Announcement` | [MsgAnnouncement](#hyperlane.announce.v1.MsgAnnouncement) | [MsgAnnouncementResponse](#hyperlane.announce.v1.MsgAnnouncementResponse) | Announces a validator signature storage location | | diff --git a/interchaintest/helpers/announce.go b/interchaintest/helpers/announce.go index a9896f1..738ed7b 100644 --- a/interchaintest/helpers/announce.go +++ b/interchaintest/helpers/announce.go @@ -111,7 +111,7 @@ func VerifyAnnounceEvents(c *cosmos.CosmosChain, txHash string) (storageLocation } func ParseEnvVar(envVar, key string) (value string) { - //HYP_BASE_CHECKPOINTSYNCER_PATH=${val_dir}/signatures-simd1 + // HYP_BASE_CHECKPOINTSYNCER_PATH=${val_dir}/signatures-simd1 pattern := fmt.Sprintf(`(?m)^%s=(?P.*)$`, key) r, _ := regexp.Compile(pattern) diff --git a/interchaintest/tests/announcement_test.go b/interchaintest/tests/announcement_test.go index c76fa54..952cb5a 100644 --- a/interchaintest/tests/announcement_test.go +++ b/interchaintest/tests/announcement_test.go @@ -12,10 +12,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" - "github.com/strangelove-ventures/hyperlane-cosmos/interchaintest/counterchain" - "github.com/strangelove-ventures/hyperlane-cosmos/interchaintest/docker" - "github.com/strangelove-ventures/hyperlane-cosmos/interchaintest/helpers" - "github.com/strangelove-ventures/hyperlane-cosmos/x/announce/types" icv7 "github.com/strangelove-ventures/interchaintest/v7" interchaintest "github.com/strangelove-ventures/interchaintest/v7" "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos" @@ -24,6 +20,11 @@ import ( "github.com/strangelove-ventures/interchaintest/v7/testreporter" "github.com/stretchr/testify/require" "go.uber.org/zap" + + "github.com/strangelove-ventures/hyperlane-cosmos/interchaintest/counterchain" + "github.com/strangelove-ventures/hyperlane-cosmos/interchaintest/docker" + "github.com/strangelove-ventures/hyperlane-cosmos/interchaintest/helpers" + "github.com/strangelove-ventures/hyperlane-cosmos/x/announce/types" ) // Test the announce module 'announce' TX @@ -163,7 +164,7 @@ func TestAnnounce(t *testing.T) { valSignature := simd1IsmValidator.Sign(digest) valSigHex := hex.EncodeToString(valSignature) - //Announcement sends the announcement to the chain + // Announcement sends the announcement to the chain processStdout := helpers.CallAnnounceMsg(t, ctx, simd1, announceWallet.KeyName(), valAddrHex, expectedStorageLocation, valSigHex) announcementTxHash := helpers.ParseTxHash(string(processStdout)) @@ -262,7 +263,7 @@ func TestHyperlaneAnnounceWithValidator(t *testing.T) { require.NoError(t, err) fmt.Printf("simd mailbox domain: %d\n", simdDomain) _, err = icv7.GetAndFundTestUserWithMnemonic(ctx, "valannounce", mnemonic, int64(10_000_000_000), simd1) - //announceWallet, err := icv7.GetAndFundTestUserWithMnemonic(ctx, "valannounce", mnemonic, int64(10_000_000_000), simd1) + // announceWallet, err := icv7.GetAndFundTestUserWithMnemonic(ctx, "valannounce", mnemonic, int64(10_000_000_000), simd1) require.NoError(t, err) userSimd := icv7.GetAndFundTestUsers(t, ctx, "default", int64(10_000_000_000), simd1)[0] diff --git a/interchaintest/tests/cosmos_e2e_test.go b/interchaintest/tests/cosmos_e2e_test.go index 9daa643..640ba6b 100644 --- a/interchaintest/tests/cosmos_e2e_test.go +++ b/interchaintest/tests/cosmos_e2e_test.go @@ -16,11 +16,13 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keyring" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common/hexutil" + icv7 "github.com/strangelove-ventures/interchaintest/v7" interchaintest "github.com/strangelove-ventures/interchaintest/v7" "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos" hyperlane "github.com/strangelove-ventures/interchaintest/v7/chain/hyperlane" "go.uber.org/zap" + "golang.org/x/sync/errgroup" "github.com/strangelove-ventures/hyperlane-cosmos/interchaintest/counterchain" "github.com/strangelove-ventures/hyperlane-cosmos/interchaintest/helpers" @@ -37,7 +39,7 @@ const ( mnemonic = "spare number knock scan copper method lunch camera trap inject fine suspect edit sure design crowd sorry actual better spatial cover grit entire raccoon" // Testing only, do NOT use this mnemonic bech32Addr = "cosmos13gpsgkxaavz3kcvh8y55xzat9umg944qnwxq4k" // for the mnemonic above mnemonicPrivKey = "fe257759a16d7085ba4df68773c94647966e9fc8c7a7e1eb3311c40bbe1a0ed3" // for the mnemonic above // Corresponds to the key above - //valPrivKey = "8166f546bab6da521a8369cab06c5d2b9e46670292d85c875ee9ec20e84ffb61" // Testing only, do NOT use this key. Corresponds to the hyperlane validator signing key, not the mnemonic above + // valPrivKey = "8166f546bab6da521a8369cab06c5d2b9e46670292d85c875ee9ec20e84ffb61" // Testing only, do NOT use this key. Corresponds to the hyperlane validator signing key, not the mnemonic above ) var ( @@ -273,6 +275,246 @@ func TestHyperlaneCosmosE2E(t *testing.T) { require.NoError(t, err) } +func TestHyperlaneCosmosMultiMessageE2E(t *testing.T) { + logger := NewLogger(t) + + // Mailbox address - will be used in the hyperlane validator config + mailboxHex, expectedMailbox := helpers.GetMailboxAddress() + prefixedMailboxHex := "0x" + mailboxHex + + // Directories where files related to this test will be stored + val1TmpDir := t.TempDir() + val2TmpDir := t.TempDir() + rlyTmpDir := t.TempDir() + + // Get the hyperlane agent raw configs (before variable replacements) + valSimd1, valSimd2, rly := readHyperlaneConfig(t, COSMOS_E2E_CONFIG, logger) + + // Get the validator key for the agents. We also need this key to configure the chain ISM. + valSimd1PrivKey, err := getHyperlaneBaseValidatorKey(valSimd1) + require.NoError(t, err) + valSimd2PrivKey, err := getHyperlaneBaseValidatorKey(valSimd2) + require.NoError(t, err) + + // Build the chain docker image from the local repo + optionalBuildChainImage() + + DockerImage := ibc.DockerImage{ + Repository: docker.HyperlaneImageName, + Version: "local", + UidGid: "1025:1025", + } + + simd1Domain := uint32(23456) + simd2Domain := uint32(34567) + + // Set up two Cosmos chains (with our hyperlane modules) for the test. + // The images must be in our local registry so we skip image pull. + chains := CreateHyperlaneSimds(t, DockerImage, []uint32{simd1Domain, simd2Domain}) + simd1 := chains[0].(*cosmos.CosmosChain) + simd1.SkipImagePull = true + simd2 := chains[1].(*cosmos.CosmosChain) + simd2.SkipImagePull = true + + // Create a new Interchain object which describes the chains, relayers, and IBC connections we want to use + ic := interchaintest.NewInterchain() + + for _, chain := range chains { + ic.AddChain(chain) + } + + rep := testreporter.NewNopReporter() + eRep := rep.RelayerExecReporter(t) + ctx := context.Background() + + // Note: make sure that both the 'ic' interchain AND the hyperlane network share this client/network + client, network := interchaintest.DockerSetup(t) + opts := interchaintest.InterchainBuildOptions{ + TestName: t.Name(), + Client: client, + NetworkID: network, + SkipPathCreation: true, + BlockDatabaseFile: interchaintest.DefaultBlockDatabaseFilepath(), + } + + err = ic.Build(ctx, eRep, opts) + require.NoError(t, err) + + t.Cleanup(func() { + _ = ic.Close() + }) + + // Query the cosmos chains and ensure the hyperlane domain configuration is as expected + verifyDomain(t, ctx, simd1, uint64(simd1Domain)) + verifyDomain(t, ctx, simd2, uint64(simd2Domain)) + + // Now we need to configure the Hyperlane modules and setup some test users... + userSimd := icv7.GetAndFundTestUsers(t, ctx, "default", int64(10_000_000_000), simd1)[0] + userSimd2 := icv7.GetAndFundTestUsers(t, ctx, "default", int64(10_000_000_000), simd2)[0] + + // Fund this wallet since the validator will announce its storage location with this mnemonic's private key. + _, err = icv7.GetAndFundTestUserWithMnemonic(ctx, "valannounce", mnemonic, int64(10_000_000_000), simd1) + require.NoError(t, err) + _, err = icv7.GetAndFundTestUserWithMnemonic(ctx, "valannounce", mnemonic, int64(10_000_000_000), simd2) + require.NoError(t, err) + + msg := `{}` + _, contract := helpers.SetupContract(t, ctx, simd1, userSimd.KeyName(), "../contracts/hyperlane.wasm", msg) + logger.Info("simd1 contract", zap.String("address", contract)) + _, contract2 := helpers.SetupContract(t, ctx, simd2, userSimd2.KeyName(), "../contracts/hyperlane.wasm", msg) + logger.Info("simd2 contract", zap.String("address", contract2)) + + verifyContractEntryPoints(t, ctx, simd1, userSimd, contract) + verifyContractEntryPoints(t, ctx, simd2, userSimd2, contract2) + + // Create counter chain 1 with val set signing legacy multisig. + // The private key used here MUST be the one from the validator config file. + simd1IsmValidator := counterchain.CreateEmperorValidator(t, simd1Domain, counterchain.LEGACY_MULTISIG, valSimd1PrivKey) + // Create counter chain 2 with val set signing legacy multisig + simd2IsmValidator := counterchain.CreateEmperorValidator(t, simd2Domain, counterchain.LEGACY_MULTISIG, valSimd2PrivKey) + + // Set default isms for counter chains for SIMD + helpers.SetDefaultIsm(t, ctx, simd1, userSimd.KeyName(), simd2IsmValidator) + // Set default isms for counter chains for SIMD2 + helpers.SetDefaultIsm(t, ctx, simd2, userSimd2.KeyName(), simd1IsmValidator) + + recipientAccAddr := sdk.MustAccAddressFromBech32(contract2).Bytes() + recipientDispatch := hexutil.Encode([]byte(recipientAccAddr)) + fmt.Printf("Recipient dispatch addr hex: %s", recipientDispatch) + + logger.Info("Preconfiguring Hyperlane (getting configs)") + + valJson, err := preconfigureHyperlaneValidator(t, valSimd1, val1TmpDir, mnemonicPrivKey, chains[0].Config().ChainID, chains[0].Config().Name, chains[0].GetRPCAddress(), "http://"+chains[0].GetGRPCAddress(), prefixedMailboxHex, 23456) + require.NoError(t, err) + + simd1MailboxHex, err := getMailbox(valJson, chains[0].Config().Name) + require.NoError(t, err) + _, simd1MailboxUnprefixed, found := strings.Cut(simd1MailboxHex, "0x") + require.True(t, found) + simd1Mailbox, err := hex.DecodeString(simd1MailboxUnprefixed) + require.NoError(t, err) + originMailboxB := []byte(simd1Mailbox) + require.Equal(t, expectedMailbox, originMailboxB) + + valJson, err = preconfigureHyperlaneValidator(t, valSimd2, val2TmpDir, mnemonicPrivKey, chains[1].Config().ChainID, chains[1].Config().Name, chains[1].GetRPCAddress(), "http://"+chains[1].GetGRPCAddress(), prefixedMailboxHex, 34567) + require.NoError(t, err) + simd1ValidatorSignaturesDir := filepath.Join(val1TmpDir, "signatures-"+chains[0].Config().Name) //${val_dir}/signatures-${chainName} + simd2ValidatorSignaturesDir := filepath.Join(val2TmpDir, "signatures-"+chains[1].Config().Name) //${val_dir}/signatures-${chainName} + + rlyCfgs := []chainCfg{ + { + privKey: mnemonicPrivKey, + chainID: chains[0].Config().ChainID, + chainName: chains[0].Config().Name, + rpcUrl: chains[0].GetRPCAddress(), + grpcUrl: "http://" + chains[0].GetGRPCAddress(), + originMailboxHex: prefixedMailboxHex, + domain: 23456, + validatorSignaturePath: simd1ValidatorSignaturesDir, + }, + { + privKey: mnemonicPrivKey, + chainID: chains[1].Config().ChainID, + chainName: chains[1].Config().Name, + rpcUrl: chains[1].GetRPCAddress(), + grpcUrl: "http://" + chains[1].GetGRPCAddress(), + originMailboxHex: prefixedMailboxHex, + domain: 34567, + validatorSignaturePath: simd2ValidatorSignaturesDir, + }, + } + _, err = preconfigureHyperlaneRelayer(t, rly, rlyTmpDir, rlyCfgs) + require.NoError(t, err) + + // Our images are currently local. You must build locally in monorepo, e.g. "cd rust && docker build .". + // Also make sure that the tags in hyperlane.yaml match the local docker image repo and version. + hyperlaneNetwork := hyperlane.NewHyperlaneNetwork(true, true) + err = hyperlaneNetwork.Build(ctx, logger, eRep, opts, *valSimd1, *valSimd2, *rly) + require.NoError(t, err) + + // Give the hyperlane validators and relayer time to start up and start watching the mailbox for the chain + time.Sleep(10 * time.Second) + + var eg errgroup.Group + numMsgs := 100 + + for i := 0; i < numMsgs; i++ { + i := i + eg.Go(func() (err error) { + dispatchedRecipientAddrHex, dispatchedMsgBody, dispatchSender, dispatchedMsgId := dispatchMsg(t, i, ctx, simd2Domain, recipientDispatch, userSimd.KeyName(), contract, simd1, logger) + return processMsg(t, ctx, simd1IsmValidator, simd2, simd1Domain, simd2Domain, dispatchedRecipientAddrHex, dispatchedMsgBody, dispatchSender, dispatchedMsgId) + }) + } + + err = eg.Wait() + require.NoError(t, err) +} + +func processMsg( + t *testing.T, + ctx context.Context, + validator *counterchain.CounterChain, + destChain *cosmos.CosmosChain, + originDomain uint32, + destDomain uint32, + dispatchedRecipientAddrHex, + dispatchedMsgBody, + dispatchSender, + dispatchedMsgId string) error { + // Find the message ID of the dispatched message and wait for the message to be processed on the destination. + dispatchedRecipientAddr := hexutil.MustDecode(dispatchedRecipientAddrHex) + bech32Recipient := sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), dispatchedRecipientAddr) + + b, err := hexutil.Decode(dispatchedMsgBody) + require.NoError(t, err) + message, _ := validator.CreateMessage(dispatchSender, originDomain, destDomain, bech32Recipient, string(b)) + messageId := validator.GetMessageId(message) + require.Equal(t, dispatchedMsgId, hexutil.Encode(messageId)) + + return Await(func() (bool, error) { + return helpers.QueryMsgDelivered(t, ctx, destChain, dispatchedMsgId), nil + }, 10*time.Minute, 5*time.Second) +} + +// Dispatch the message to the chain and verify it was sent successfully +func dispatchMsg( + t *testing.T, + msgIndex int, + ctx context.Context, + destDomain uint32, + recipientAddr string, + keyName string, + contract string, + chain *cosmos.CosmosChain, + logger *zap.Logger, +) (dispatchedRecipientAddrHex, dispatchedMsgBody, dispatchSender, dispatchedMsgId string) { + // Dispatch a message to SIMD1 + dMsg := []byte("CosmosSimd1ToCosmosSimd2" + fmt.Sprintf("%d", msgIndex)) + dispatchedMsg := hexutil.Encode(dMsg) + + dispatchMsgStruct := helpers.ExecuteMsg{ + DispatchMsg: &helpers.DispatchMsg{ + DestinationAddr: destDomain, + RecipientAddr: recipientAddr, + MessageBody: dispatchedMsg, + }, + } + + // Dispatch the hyperlane message to simd1 + dipatchMsg, err := json.Marshal(dispatchMsgStruct) + require.NoError(t, err) + dispatchedTxHash, err := chain.ExecuteContract(ctx, keyName, contract, string(dipatchMsg)) + require.NoError(t, err) + logger.Info("Message dispatched to simd1") + var dispatchedDestDomain string + dispatchedDestDomain, dispatchedRecipientAddrHex, dispatchedMsgBody, dispatchedMsgId, dispatchSender, _, err = helpers.VerifyDispatchEvents(chain, dispatchedTxHash) + require.NoError(t, err) + require.NotEmpty(t, dispatchSender) + require.NotEmpty(t, dispatchedRecipientAddrHex) + require.Equal(t, fmt.Sprintf("%d", destDomain), dispatchedDestDomain) + return +} + // e2e style test that spins up two Cosmos nodes (with different origin domains), // a hyperlane validator (for Cosmos), and sends messages back and forth. // Does not use a hyperlane relayer. @@ -403,7 +645,7 @@ func TestHyperlaneCosmosValidator(t *testing.T) { require.NoError(t, err) simd1ValidatorSignaturesDir := filepath.Join(val1TmpDir, "signatures-"+chains[0].Config().Name) //${val_dir}/signatures-${chainName} - //simd2ValidatorSignaturesDir := filepath.Join(tmpDir2, "signatures-"+chains[1].Config().Name) //${val_dir}/signatures-${chainName} + // simd2ValidatorSignaturesDir := filepath.Join(tmpDir2, "signatures-"+chains[1].Config().Name) //${val_dir}/signatures-${chainName} // Our images are currently local. You must build locally in monorepo, e.g. "cd rust && docker build .". // Also make sure that the tags in hyperlane.yaml match the local docker image repo and version. diff --git a/interchaintest/tests/helpers.go b/interchaintest/tests/helpers.go index df83109..2b876f0 100644 --- a/interchaintest/tests/helpers.go +++ b/interchaintest/tests/helpers.go @@ -17,12 +17,13 @@ import ( "time" "github.com/go-cmd/cmd" - "github.com/strangelove-ventures/hyperlane-cosmos/interchaintest/docker" - "github.com/strangelove-ventures/hyperlane-cosmos/interchaintest/helpers" "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos" "github.com/strangelove-ventures/interchaintest/v7/chain/hyperlane" "github.com/stretchr/testify/require" "go.uber.org/zap" + + "github.com/strangelove-ventures/hyperlane-cosmos/interchaintest/docker" + "github.com/strangelove-ventures/hyperlane-cosmos/interchaintest/helpers" ) const ( diff --git a/proto/hyperlane/announce/v1/genesis.proto b/proto/hyperlane/announce/v1/genesis.proto index aa9fb75..c6724d0 100644 --- a/proto/hyperlane/announce/v1/genesis.proto +++ b/proto/hyperlane/announce/v1/genesis.proto @@ -1,10 +1,13 @@ syntax = "proto3"; package hyperlane.announce.v1; - +import "hyperlane/announce/v1/types.proto"; import "gogoproto/gogo.proto"; option go_package = "github.com/strangelove-ventures/hyperlane-cosmos/x/announce/types"; // Hyperlane Announce's keeper genesis state -message GenesisState { option (gogoproto.goproto_getters) = false; } +message GenesisState { + option (gogoproto.goproto_getters) = false; + repeated GenesisAnnouncement announcements = 1; +} diff --git a/proto/hyperlane/announce/v1/types.proto b/proto/hyperlane/announce/v1/types.proto index cdac986..09cd1dd 100644 --- a/proto/hyperlane/announce/v1/types.proto +++ b/proto/hyperlane/announce/v1/types.proto @@ -17,9 +17,6 @@ message StoredAnnouncement { // location where signatures will be stored string storage_location = 1; - - // signed validator announcement - bytes signature = 2; } // Helper type for Hyperlane's Announcement. @@ -27,3 +24,11 @@ message StoredAnnouncements { option (gogoproto.goproto_getters) = false; repeated StoredAnnouncement announcement = 1; } + +// Genesis helper type for Hyperlane's Announcement. +message GenesisAnnouncement { + option (gogoproto.goproto_getters) = false; + StoredAnnouncement announcement = 1; + // The validator (in eth address format) that announced + bytes validator = 2; +} diff --git a/x/announce/client/cli/tx.go b/x/announce/client/cli/tx.go index 441229b..3246fde 100644 --- a/x/announce/client/cli/tx.go +++ b/x/announce/client/cli/tx.go @@ -18,7 +18,7 @@ func announceCmd() *cobra.Command { cmd := &cobra.Command{ Use: "announce ", Short: "announce - Announces a validator signature location", - Example: fmt.Sprintf("%s tx %s announce 0xFFFFFFFFFFFFFFFFFFFF", version.AppName, types.ModuleName), + Example: fmt.Sprintf("%s tx %s announce 0xFFFFFFFFFFFFFFFFFFFF file:///hyperlane/val-signatures 0x...", version.AppName, types.ModuleName), Args: cobra.ExactArgs(3), RunE: func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientTxContext(cmd) diff --git a/x/announce/keeper/genesis.go b/x/announce/keeper/genesis.go index cc87f37..27adfea 100644 --- a/x/announce/keeper/genesis.go +++ b/x/announce/keeper/genesis.go @@ -9,10 +9,69 @@ import ( // InitGenesis initializes the hyperlane announce module's state from a provided genesis // state. func (k Keeper) InitGenesis(ctx sdk.Context, gs types.GenesisState) error { + var storedAnnouncements *types.StoredAnnouncements + var err error + + for _, announcement := range gs.Announcements { + storedAnnouncements, err = k.getAnnouncements(ctx, announcement.Validator) + if err != nil { + storedAnnouncements = &types.StoredAnnouncements{ + Announcement: []*types.StoredAnnouncement{}, + } + } else { + // Check for replays since there were existing announcements for this validator + for _, existingAnnouncement := range storedAnnouncements.Announcement { + if existingAnnouncement.StorageLocation == announcement.Announcement.StorageLocation { + return types.ErrReplayAnnouncement + } + } + } + + storedAnnouncements.Announcement = append(storedAnnouncements.Announcement, &types.StoredAnnouncement{ + StorageLocation: announcement.Announcement.StorageLocation, + }) + + err = k.setAnnouncements(ctx, announcement.Validator, storedAnnouncements) + if err != nil { + return err + } + } + return nil } // ExportGenesis returns the hyperlane announce module's exported genesis. func (k Keeper) ExportGenesis(ctx sdk.Context) types.GenesisState { - return types.GenesisState{} + announcements, err := ExportAnnouncements(ctx.KVStore(k.storeKey)) + if err != nil { + panic("Exporting genesis state failed - exporting announcements failed") + } + return types.GenesisState{ + Announcements: announcements, + } +} + +// getAnnouncedValidators unmarshal announced validators from storage +func ExportAnnouncements(store sdk.KVStore) ([]*types.GenesisAnnouncement, error) { + iterator := sdk.KVStorePrefixIterator(store, types.AnnouncedStorageLocations) + defer iterator.Close() + announcements := []*types.GenesisAnnouncement{} + + for ; iterator.Valid(); iterator.Next() { + validator := iterator.Key() + storedAnnouncementsBytes := iterator.Value() + storedAnnouncements := &types.StoredAnnouncements{} + err := storedAnnouncements.Unmarshal(storedAnnouncementsBytes) + if err != nil { + return nil, err + } + for _, curr := range storedAnnouncements.Announcement { + currAnnouncement := &types.GenesisAnnouncement{ + Announcement: curr, + Validator: validator, + } + announcements = append(announcements, currAnnouncement) + } + } + return announcements, nil } diff --git a/x/announce/keeper/grpc_query.go b/x/announce/keeper/grpc_query.go index 2be1222..2da603a 100644 --- a/x/announce/keeper/grpc_query.go +++ b/x/announce/keeper/grpc_query.go @@ -18,13 +18,7 @@ func (k Keeper) GetAnnouncedValidators(ctx context.Context, req *types.GetAnnoun return nil, status.Error(codes.InvalidArgument, "invalid request") } sdkCtx := sdk.UnwrapSDKContext(ctx) - - resp, err := k.getAnnouncedValidators(sdkCtx) - if err != nil { - return nil, types.ErrMarshalAnnouncedValidators - } - - return resp, nil + return k.getAnnouncedValidators(sdkCtx), nil } // GetAnnouncedStorageLocations returns the list of storage locations for each requested validator diff --git a/x/announce/keeper/grpc_query_test.go b/x/announce/keeper/grpc_query_test.go index 175ce60..aa43126 100644 --- a/x/announce/keeper/grpc_query_test.go +++ b/x/announce/keeper/grpc_query_test.go @@ -2,6 +2,7 @@ package keeper_test import ( "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/strangelove-ventures/hyperlane-cosmos/x/announce/types" ) diff --git a/x/announce/keeper/msg_server.go b/x/announce/keeper/msg_server.go index c58403b..81d28aa 100644 --- a/x/announce/keeper/msg_server.go +++ b/x/announce/keeper/msg_server.go @@ -5,7 +5,6 @@ import ( "encoding/hex" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/strangelove-ventures/hyperlane-cosmos/x/announce/types" ) @@ -49,14 +48,8 @@ func (k Keeper) Announcement(goCtx context.Context, msg *types.MsgAnnouncement) storedAnnouncements.Announcement = append(storedAnnouncements.Announcement, &types.StoredAnnouncement{ StorageLocation: msg.StorageLocation, - Signature: msg.Signature, }) - valHex := hexutil.Encode(msg.Validator) - err = k.setAnnouncedValidators(ctx, valHex) - if err != nil { - return nil, types.ErrMarshalAnnouncedValidators - } err = k.setAnnouncements(ctx, msg.Validator, storedAnnouncements) if err != nil { return nil, err diff --git a/x/announce/keeper/store.go b/x/announce/keeper/store.go index ba18d1d..9c12fd1 100644 --- a/x/announce/keeper/store.go +++ b/x/announce/keeper/store.go @@ -1,10 +1,9 @@ package keeper import ( - "errors" - "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/strangelove-ventures/hyperlane-cosmos/x/announce/types" ) @@ -15,36 +14,21 @@ func (k Keeper) getAnnouncementsStore(ctx sdk.Context) prefix.Store { } // getAnnouncedValidators unmarshal announced validators from storage -func (k Keeper) getAnnouncedValidators(ctx sdk.Context) (*types.GetAnnouncedValidatorsResponse, error) { +func (k Keeper) getAnnouncedValidators(ctx sdk.Context) *types.GetAnnouncedValidatorsResponse { store := ctx.KVStore(k.storeKey) - announcedValidatorBytes := store.Get(types.AnnouncedValidators) - announcedValidators := &types.GetAnnouncedValidatorsResponse{} - - if announcedValidatorBytes == nil { - return nil, errors.New("No announced validators") - } - - err := announcedValidators.Unmarshal(announcedValidatorBytes) - return announcedValidators, err -} + iterator := sdk.KVStorePrefixIterator(store, types.AnnouncedStorageLocations) + defer iterator.Close() + validators := []string{} -// setAnnouncedValidators store an announced validator -func (k Keeper) setAnnouncedValidators(ctx sdk.Context, validator string) (err error) { - var announcedValidators *types.GetAnnouncedValidatorsResponse - announcedValidators, err = k.getAnnouncedValidators(ctx) - if err != nil { - announcedValidators = &types.GetAnnouncedValidatorsResponse{Validator: []string{}} + for ; iterator.Valid(); iterator.Next() { + validator := iterator.Key() + validators = append(validators, hexutil.Encode(validator)) } - announcedValidators.Validator = append(announcedValidators.Validator, validator) - announcedValidatorsBytes, err := announcedValidators.Marshal() - if err != nil { - return types.ErrMarshalAnnouncedValidators + announcedValidators := &types.GetAnnouncedValidatorsResponse{ + Validator: validators, } - - store := ctx.KVStore(k.storeKey) - store.Set(types.AnnouncedValidators, announcedValidatorsBytes) - return nil + return announcedValidators } // getAnnouncements unmarshal announcements for the given validator from storage diff --git a/x/announce/types/genesis.pb.go b/x/announce/types/genesis.pb.go index 84750db..2f87130 100644 --- a/x/announce/types/genesis.pb.go +++ b/x/announce/types/genesis.pb.go @@ -27,7 +27,9 @@ var ( const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // Hyperlane Announce's keeper genesis state -type GenesisState struct{} +type GenesisState struct { + Announcements []*GenesisAnnouncement `protobuf:"bytes,1,rep,name=announcements,proto3" json:"announcements,omitempty"` +} func (m *GenesisState) Reset() { *m = GenesisState{} } func (m *GenesisState) String() string { return proto.CompactTextString(m) } @@ -76,19 +78,22 @@ func init() { } var fileDescriptor_b1e1010a9be4a04d = []byte{ - // 187 bytes of a gzipped FileDescriptorProto + // 226 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0xce, 0xa8, 0x2c, 0x48, 0x2d, 0xca, 0x49, 0xcc, 0x4b, 0xd5, 0x4f, 0xcc, 0xcb, 0xcb, 0x2f, 0xcd, 0x4b, 0x4e, 0xd5, 0x2f, 0x33, 0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, - 0x12, 0x85, 0x2b, 0xd2, 0x83, 0x29, 0xd2, 0x2b, 0x33, 0x94, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, - 0xab, 0xd0, 0x07, 0xb1, 0x20, 0x8a, 0x95, 0x44, 0xb8, 0x78, 0xdc, 0x21, 0xba, 0x83, 0x4b, 0x12, - 0x4b, 0x52, 0xad, 0x58, 0x3a, 0x16, 0xc8, 0x33, 0x38, 0x45, 0x9f, 0x78, 0x24, 0xc7, 0x78, 0xe1, - 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x13, 0x1e, 0xcb, 0x31, 0x5c, 0x78, 0x2c, 0xc7, 0x70, - 0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x63, 0x7a, 0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, - 0x7e, 0x71, 0x49, 0x51, 0x62, 0x5e, 0x7a, 0x6a, 0x4e, 0x7e, 0x59, 0xaa, 0x6e, 0x59, 0x6a, 0x5e, - 0x49, 0x69, 0x51, 0x6a, 0xb1, 0x3e, 0xdc, 0x72, 0xdd, 0xe4, 0xfc, 0xe2, 0xdc, 0xfc, 0x62, 0xfd, - 0x0a, 0x84, 0x53, 0x4b, 0x2a, 0x0b, 0x52, 0x8b, 0x93, 0xd8, 0xc0, 0x36, 0x1b, 0x03, 0x02, 0x00, - 0x00, 0xff, 0xff, 0x02, 0x05, 0xbc, 0xe2, 0xcd, 0x00, 0x00, 0x00, + 0x12, 0x85, 0x2b, 0xd2, 0x83, 0x29, 0xd2, 0x2b, 0x33, 0x94, 0x52, 0xc4, 0xae, 0xb7, 0xa4, 0xb2, + 0x20, 0x15, 0xaa, 0x53, 0x4a, 0x24, 0x3d, 0x3f, 0x3d, 0x1f, 0xcc, 0xd4, 0x07, 0xb1, 0x20, 0xa2, + 0x4a, 0x69, 0x5c, 0x3c, 0xee, 0x10, 0x0b, 0x82, 0x4b, 0x12, 0x4b, 0x52, 0x85, 0x02, 0xb8, 0x78, + 0x61, 0x06, 0xe4, 0xa6, 0xe6, 0x95, 0x14, 0x4b, 0x30, 0x2a, 0x30, 0x6b, 0x70, 0x1b, 0x69, 0xe9, + 0x61, 0xb5, 0x57, 0x0f, 0xaa, 0xd7, 0x11, 0x49, 0x4b, 0x10, 0xaa, 0x01, 0x56, 0x2c, 0x1d, 0x0b, + 0xe4, 0x19, 0x9c, 0xa2, 0x4f, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, + 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0xca, 0x31, + 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, 0xbf, 0xb8, 0xa4, 0x28, 0x31, 0x2f, + 0x3d, 0x35, 0x27, 0xbf, 0x2c, 0x55, 0xb7, 0x2c, 0x35, 0xaf, 0xa4, 0xb4, 0x28, 0xb5, 0x58, 0x1f, + 0x6e, 0xb3, 0x6e, 0x72, 0x7e, 0x71, 0x6e, 0x7e, 0xb1, 0x7e, 0x05, 0xc2, 0x8f, 0x60, 0x0f, 0x26, + 0xb1, 0x81, 0xfd, 0x62, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xfd, 0x40, 0x02, 0x6f, 0x42, 0x01, + 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -111,6 +116,20 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.Announcements) > 0 { + for iNdEx := len(m.Announcements) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Announcements[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } return len(dAtA) - i, nil } @@ -132,6 +151,12 @@ func (m *GenesisState) Size() (n int) { } var l int _ = l + if len(m.Announcements) > 0 { + for _, e := range m.Announcements { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } return n } @@ -172,6 +197,40 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Announcements", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Announcements = append(m.Announcements, &GenesisAnnouncement{}) + if err := m.Announcements[len(m.Announcements)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenesis(dAtA[iNdEx:]) diff --git a/x/announce/types/types.pb.go b/x/announce/types/types.pb.go index 8ae06ee..1e8d9a6 100644 --- a/x/announce/types/types.pb.go +++ b/x/announce/types/types.pb.go @@ -73,8 +73,6 @@ var xxx_messageInfo_StorageMetadata proto.InternalMessageInfo type StoredAnnouncement struct { // location where signatures will be stored StorageLocation string `protobuf:"bytes,1,opt,name=storage_location,json=storageLocation,proto3" json:"storage_location,omitempty"` - // signed validator announcement - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` } func (m *StoredAnnouncement) Reset() { *m = StoredAnnouncement{} } @@ -158,35 +156,83 @@ func (m *StoredAnnouncements) XXX_DiscardUnknown() { var xxx_messageInfo_StoredAnnouncements proto.InternalMessageInfo +// Genesis helper type for Hyperlane's Announcement. +type GenesisAnnouncement struct { + Announcement *StoredAnnouncement `protobuf:"bytes,1,opt,name=announcement,proto3" json:"announcement,omitempty"` + // The validator (in eth address format) that announced + Validator []byte `protobuf:"bytes,2,opt,name=validator,proto3" json:"validator,omitempty"` +} + +func (m *GenesisAnnouncement) Reset() { *m = GenesisAnnouncement{} } +func (m *GenesisAnnouncement) String() string { return proto.CompactTextString(m) } +func (*GenesisAnnouncement) ProtoMessage() {} +func (*GenesisAnnouncement) Descriptor() ([]byte, []int) { + return fileDescriptor_26474efeff56f239, []int{3} +} + +func (m *GenesisAnnouncement) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} + +func (m *GenesisAnnouncement) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisAnnouncement.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} + +func (m *GenesisAnnouncement) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisAnnouncement.Merge(m, src) +} + +func (m *GenesisAnnouncement) XXX_Size() int { + return m.Size() +} + +func (m *GenesisAnnouncement) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisAnnouncement.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisAnnouncement proto.InternalMessageInfo + func init() { proto.RegisterType((*StorageMetadata)(nil), "hyperlane.announce.v1.StorageMetadata") proto.RegisterType((*StoredAnnouncement)(nil), "hyperlane.announce.v1.StoredAnnouncement") proto.RegisterType((*StoredAnnouncements)(nil), "hyperlane.announce.v1.StoredAnnouncements") + proto.RegisterType((*GenesisAnnouncement)(nil), "hyperlane.announce.v1.GenesisAnnouncement") } func init() { proto.RegisterFile("hyperlane/announce/v1/types.proto", fileDescriptor_26474efeff56f239) } var fileDescriptor_26474efeff56f239 = []byte{ - // 300 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x91, 0xbf, 0x4e, 0x02, 0x41, - 0x10, 0xc6, 0x6f, 0xd5, 0x18, 0x59, 0x49, 0x30, 0xab, 0x26, 0x84, 0x98, 0x15, 0xa9, 0xa0, 0x60, - 0x37, 0x48, 0x67, 0x87, 0xb5, 0x34, 0x67, 0xa7, 0x85, 0x59, 0x8e, 0xc9, 0x82, 0xe1, 0x76, 0xc8, - 0xed, 0x72, 0x91, 0x37, 0xb0, 0xf4, 0x11, 0x7c, 0x1c, 0x4b, 0x4a, 0x4b, 0x73, 0xf7, 0x22, 0xe6, - 0xfe, 0x78, 0x68, 0xb0, 0x9b, 0xfd, 0xf2, 0xcd, 0xf7, 0x9b, 0x9d, 0xa1, 0x57, 0xb3, 0xf5, 0x12, - 0xa2, 0x85, 0x32, 0x20, 0x95, 0x31, 0xb8, 0x32, 0x01, 0xc8, 0x78, 0x20, 0xdd, 0x7a, 0x09, 0x56, - 0x2c, 0x23, 0x74, 0xc8, 0xce, 0x2b, 0x8b, 0xf8, 0xb1, 0x88, 0x78, 0xd0, 0x3a, 0xd3, 0xa8, 0x31, - 0x77, 0xc8, 0xac, 0x2a, 0xcc, 0x9d, 0x21, 0x6d, 0xdc, 0x3b, 0x8c, 0x94, 0x86, 0x31, 0x38, 0x35, - 0x55, 0x4e, 0xb1, 0x16, 0x3d, 0x0a, 0xcb, 0xba, 0x49, 0xda, 0xfb, 0xdd, 0x9a, 0x5f, 0xbd, 0x6f, - 0x0e, 0x5e, 0xdf, 0x2f, 0xbd, 0x4e, 0x40, 0x59, 0xd6, 0x04, 0xd3, 0x51, 0x99, 0x1f, 0x82, 0x71, - 0xac, 0x47, 0x4f, 0x6c, 0x11, 0xf5, 0xb4, 0xc0, 0x40, 0xb9, 0x39, 0x9a, 0x26, 0x69, 0x93, 0x6e, - 0xcd, 0x6f, 0x94, 0xfa, 0x5d, 0x29, 0xb3, 0x0b, 0x5a, 0xb3, 0x73, 0x6d, 0x94, 0x5b, 0x45, 0xd0, - 0xdc, 0x6b, 0x93, 0x6e, 0xdd, 0xdf, 0x0a, 0x25, 0xe4, 0x99, 0x9e, 0xee, 0x42, 0x2c, 0x1b, 0xd3, - 0xba, 0xfa, 0x25, 0xe4, 0x13, 0x1e, 0x5f, 0xf7, 0xc4, 0xbf, 0x9f, 0x16, 0xbb, 0x09, 0xfe, 0x9f, - 0xf6, 0x82, 0x75, 0xfb, 0xf8, 0x91, 0x70, 0xb2, 0x49, 0x38, 0xf9, 0x4a, 0x38, 0x79, 0x4b, 0xb9, - 0xb7, 0x49, 0xb9, 0xf7, 0x99, 0x72, 0xef, 0x61, 0xa4, 0xe7, 0x6e, 0xb6, 0x9a, 0x88, 0x00, 0x43, - 0x69, 0x5d, 0xa4, 0x8c, 0x86, 0x05, 0xc6, 0xd0, 0x8f, 0xc1, 0x64, 0xb3, 0x5a, 0x59, 0x71, 0xfb, - 0x01, 0xda, 0x10, 0xad, 0x7c, 0xd9, 0x1e, 0x26, 0xbf, 0xca, 0xe4, 0x30, 0xdf, 0xf4, 0xf0, 0x3b, - 0x00, 0x00, 0xff, 0xff, 0x13, 0x67, 0xf8, 0x26, 0xbb, 0x01, 0x00, 0x00, + // 322 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x92, 0xb1, 0x4e, 0x02, 0x41, + 0x10, 0x86, 0x6f, 0xd5, 0x18, 0x59, 0x49, 0x30, 0x87, 0x26, 0x84, 0x98, 0x15, 0xa9, 0xa0, 0x60, + 0x37, 0x48, 0x67, 0x87, 0x89, 0xb1, 0x91, 0xe6, 0xec, 0xb4, 0x30, 0xcb, 0x31, 0x39, 0xce, 0xdc, + 0xed, 0x90, 0xdd, 0xe5, 0x22, 0x6f, 0x40, 0xe9, 0x23, 0xf8, 0x38, 0x96, 0x94, 0x96, 0x06, 0x5e, + 0xc4, 0x70, 0xac, 0x20, 0xc1, 0xce, 0x6e, 0xee, 0xcf, 0x3f, 0xdf, 0xff, 0x5f, 0x76, 0xe8, 0xe5, + 0x70, 0x32, 0x02, 0x9d, 0x48, 0x05, 0x42, 0x2a, 0x85, 0x63, 0x15, 0x82, 0xc8, 0xda, 0xc2, 0x4e, + 0x46, 0x60, 0xf8, 0x48, 0xa3, 0x45, 0xff, 0x6c, 0x6d, 0xe1, 0x3f, 0x16, 0x9e, 0xb5, 0xab, 0xa7, + 0x11, 0x46, 0x98, 0x3b, 0xc4, 0x72, 0x5a, 0x99, 0xeb, 0x1d, 0x5a, 0x7a, 0xb0, 0xa8, 0x65, 0x04, + 0x3d, 0xb0, 0x72, 0x20, 0xad, 0xf4, 0xab, 0xf4, 0x28, 0x75, 0x73, 0x85, 0xd4, 0xf6, 0x1b, 0x85, + 0x60, 0xfd, 0x7d, 0x7d, 0x30, 0x7d, 0xbf, 0xf0, 0xea, 0xb7, 0xd4, 0x5f, 0x2e, 0xc1, 0xa0, 0xeb, + 0xf8, 0x29, 0x28, 0xeb, 0x37, 0xe9, 0x89, 0x59, 0xa1, 0x9e, 0x13, 0x0c, 0xa5, 0x8d, 0x51, 0x55, + 0x48, 0x8d, 0x34, 0x0a, 0x41, 0xc9, 0xe9, 0xf7, 0x4e, 0x76, 0x98, 0x17, 0x5a, 0xde, 0xc5, 0x18, + 0xbf, 0x47, 0x8b, 0xf2, 0x97, 0x90, 0x77, 0x38, 0xbe, 0x6a, 0xf2, 0x3f, 0x7f, 0x8b, 0xef, 0x12, + 0x82, 0xad, 0x75, 0x97, 0x35, 0x25, 0xb4, 0x7c, 0x07, 0x0a, 0x4c, 0x6c, 0xb6, 0x4a, 0xef, 0x86, + 0x91, 0x7f, 0x84, 0xf9, 0xe7, 0xb4, 0x90, 0xc9, 0x24, 0x1e, 0x48, 0x8b, 0xba, 0xb2, 0x57, 0x23, + 0x8d, 0x62, 0xb0, 0x11, 0x56, 0x55, 0x6e, 0x9e, 0x3e, 0xe6, 0x8c, 0xcc, 0xe6, 0x8c, 0x7c, 0xcd, + 0x19, 0x79, 0x5b, 0x30, 0x6f, 0xb6, 0x60, 0xde, 0xe7, 0x82, 0x79, 0x8f, 0xdd, 0x28, 0xb6, 0xc3, + 0x71, 0x9f, 0x87, 0x98, 0x0a, 0x63, 0xb5, 0x54, 0x11, 0x24, 0x98, 0x41, 0x2b, 0x03, 0x65, 0xc7, + 0x1a, 0x8c, 0x58, 0xb7, 0x6a, 0x85, 0x68, 0x52, 0x34, 0xe2, 0x75, 0x73, 0x05, 0xf9, 0x09, 0xf4, + 0x0f, 0xf3, 0x67, 0xed, 0x7c, 0x07, 0x00, 0x00, 0xff, 0xff, 0x5e, 0xd6, 0xdd, 0x09, 0x28, 0x02, + 0x00, 0x00, } func (m *StorageMetadata) Marshal() (dAtA []byte, err error) { @@ -241,13 +287,6 @@ func (m *StoredAnnouncement) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.Signature) > 0 { - i -= len(m.Signature) - copy(dAtA[i:], m.Signature) - i = encodeVarintTypes(dAtA, i, uint64(len(m.Signature))) - i-- - dAtA[i] = 0x12 - } if len(m.StorageLocation) > 0 { i -= len(m.StorageLocation) copy(dAtA[i:], m.StorageLocation) @@ -295,6 +334,48 @@ func (m *StoredAnnouncements) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *GenesisAnnouncement) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GenesisAnnouncement) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisAnnouncement) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Validator) > 0 { + i -= len(m.Validator) + copy(dAtA[i:], m.Validator) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Validator))) + i-- + dAtA[i] = 0x12 + } + if m.Announcement != nil { + { + size, err := m.Announcement.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { offset -= sovTypes(v) base := offset @@ -332,10 +413,6 @@ func (m *StoredAnnouncement) Size() (n int) { if l > 0 { n += 1 + l + sovTypes(uint64(l)) } - l = len(m.Signature) - if l > 0 { - n += 1 + l + sovTypes(uint64(l)) - } return n } @@ -354,6 +431,23 @@ func (m *StoredAnnouncements) Size() (n int) { return n } +func (m *GenesisAnnouncement) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Announcement != nil { + l = m.Announcement.Size() + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Validator) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + func sovTypes(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -506,11 +600,62 @@ func (m *StoredAnnouncement) Unmarshal(dAtA []byte) error { } m.StorageLocation = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 2: + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} + +func (m *StoredAnnouncements) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: StoredAnnouncements: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: StoredAnnouncements: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signature", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Announcement", wireType) } - var byteLen int + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTypes @@ -520,24 +665,24 @@ func (m *StoredAnnouncement) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - byteLen |= int(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - if byteLen < 0 { + if msglen < 0 { return ErrInvalidLengthTypes } - postIndex := iNdEx + byteLen + postIndex := iNdEx + msglen if postIndex < 0 { return ErrInvalidLengthTypes } if postIndex > l { return io.ErrUnexpectedEOF } - m.Signature = append(m.Signature[:0], dAtA[iNdEx:postIndex]...) - if m.Signature == nil { - m.Signature = []byte{} + m.Announcement = append(m.Announcement, &StoredAnnouncement{}) + if err := m.Announcement[len(m.Announcement)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err } iNdEx = postIndex default: @@ -562,7 +707,7 @@ func (m *StoredAnnouncement) Unmarshal(dAtA []byte) error { return nil } -func (m *StoredAnnouncements) Unmarshal(dAtA []byte) error { +func (m *GenesisAnnouncement) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -585,10 +730,10 @@ func (m *StoredAnnouncements) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: StoredAnnouncements: wiretype end group for non-group") + return fmt.Errorf("proto: GenesisAnnouncement: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: StoredAnnouncements: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: GenesisAnnouncement: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -620,11 +765,47 @@ func (m *StoredAnnouncements) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Announcement = append(m.Announcement, &StoredAnnouncement{}) - if err := m.Announcement[len(m.Announcement)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if m.Announcement == nil { + m.Announcement = &StoredAnnouncement{} + } + if err := m.Announcement.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validator", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Validator = append(m.Validator[:0], dAtA[iNdEx:postIndex]...) + if m.Validator == nil { + m.Validator = []byte{} + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) diff --git a/x/mailbox/keeper/keeper.go b/x/mailbox/keeper/keeper.go index 0c62fc2..db78c7f 100644 --- a/x/mailbox/keeper/keeper.go +++ b/x/mailbox/keeper/keeper.go @@ -19,9 +19,7 @@ import ( "github.com/strangelove-ventures/hyperlane-cosmos/x/mailbox/types" ) -var ( - _ ReadOnlyMailboxKeeper = (*Keeper)(nil) -) +var _ ReadOnlyMailboxKeeper = (*Keeper)(nil) type Keeper struct { // implements gRPC QueryServer interface