diff --git a/app/app.go b/app/app.go index e07388ec8..1da8f2343 100644 --- a/app/app.go +++ b/app/app.go @@ -12,6 +12,9 @@ import ( v502 "github.com/neutron-org/neutron/v5/app/upgrades/v5.0.2" dynamicfeestypes "github.com/neutron-org/neutron/v5/x/dynamicfees/types" + stateverifier "github.com/neutron-org/neutron/v5/x/state-verifier" + svkeeper "github.com/neutron-org/neutron/v5/x/state-verifier/keeper" + stateverifiertypes "github.com/neutron-org/neutron/v5/x/state-verifier/types" "github.com/skip-mev/feemarket/x/feemarket" feemarketkeeper "github.com/skip-mev/feemarket/x/feemarket/keeper" @@ -394,6 +397,8 @@ type App struct { InterchainTxsKeeper interchaintxskeeper.Keeper ContractManagerKeeper contractmanagermodulekeeper.Keeper + StateVerifierKeeper *svkeeper.Keeper + ConsensusParamsKeeper consensusparamkeeper.Keeper WasmKeeper wasmkeeper.Keeper @@ -489,7 +494,7 @@ func New( interchainqueriesmoduletypes.StoreKey, contractmanagermoduletypes.StoreKey, interchaintxstypes.StoreKey, wasmtypes.StoreKey, feetypes.StoreKey, feeburnertypes.StoreKey, adminmoduletypes.StoreKey, ccvconsumertypes.StoreKey, tokenfactorytypes.StoreKey, pfmtypes.StoreKey, crontypes.StoreKey, ibcratelimittypes.ModuleName, ibchookstypes.StoreKey, consensusparamtypes.StoreKey, crisistypes.StoreKey, dextypes.StoreKey, auctiontypes.StoreKey, - oracletypes.StoreKey, marketmaptypes.StoreKey, feemarkettypes.StoreKey, dynamicfeestypes.StoreKey, globalfeetypes.StoreKey, + oracletypes.StoreKey, marketmaptypes.StoreKey, feemarkettypes.StoreKey, dynamicfeestypes.StoreKey, globalfeetypes.StoreKey, stateverifiertypes.StoreKey, ) tkeys := storetypes.NewTransientStoreKeys(paramstypes.TStoreKey, dextypes.TStoreKey) memKeys := storetypes.NewMemoryStoreKeys(capabilitytypes.MemStoreKey, feetypes.MemStoreKey) @@ -653,6 +658,8 @@ func New( app.GlobalFeeKeeper = globalfeekeeper.NewKeeper(appCodec, keys[globalfeetypes.StoreKey], authtypes.NewModuleAddress(adminmoduletypes.ModuleName).String()) + app.StateVerifierKeeper = svkeeper.NewKeeper(appCodec, keys[stateverifiertypes.StoreKey], runtime.ProvideCometInfoService(), runtime.ProvideHeaderInfoService(nil), authtypes.NewModuleAddress(adminmoduletypes.ModuleName).String()) + // Create evidence Keeper for to register the IBC light client misbehaviour evidence route evidenceKeeper := evidencekeeper.NewKeeper( appCodec, runtime.NewKVStoreService(keys[evidencetypes.StoreKey]), &app.ConsumerKeeper, app.SlashingKeeper, @@ -931,6 +938,7 @@ func New( consensus.NewAppModule(appCodec, app.ConsensusParamsKeeper), // always be last to make sure that it checks for all invariants and not only part of them crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants, app.GetSubspace(crisistypes.ModuleName)), + stateverifier.NewAppModule(appCodec, app.StateVerifierKeeper), ) app.mm.SetOrderPreBlockers( @@ -976,6 +984,7 @@ func New( feemarkettypes.ModuleName, dextypes.ModuleName, consensusparamtypes.ModuleName, + stateverifiertypes.ModuleName, ) app.mm.SetOrderEndBlockers( @@ -1013,6 +1022,7 @@ func New( feemarkettypes.ModuleName, dextypes.ModuleName, consensusparamtypes.ModuleName, + stateverifiertypes.ModuleName, ) // NOTE: The genutils module must occur after staking so that pools are @@ -1056,6 +1066,7 @@ func New( dextypes.ModuleName, dynamicfeestypes.ModuleName, consensusparamtypes.ModuleName, + stateverifiertypes.ModuleName, ) app.mm.RegisterInvariants(&app.CrisisKeeper) diff --git a/docs/static/swagger.yaml b/docs/static/swagger.yaml index c1c094a97..b31dea7db 100644 --- a/docs/static/swagger.yaml +++ b/docs/static/swagger.yaml @@ -19635,6 +19635,11 @@ definitions: type: array type: object type: object + neutron.state_verifier.v1.QueryVerifyStateValuesResponse: + properties: + valid: + type: boolean + type: object osmosis.tokenfactory.Params: description: Params defines the parameters for the tokenfactory module. properties: @@ -45443,6 +45448,47 @@ paths: type: object tags: - Query + /neutron/state-verifier/verify_state_values: + get: + operationId: VerifyStateValues + parameters: + - format: uint64 + in: query + name: height + required: false + type: string + responses: + '200': + description: A successful response. + schema: + properties: + valid: + type: boolean + type: object + default: + description: An unexpected error response. + schema: + properties: + code: + format: int32 + type: integer + details: + items: + properties: + type_url: + type: string + value: + format: byte + type: string + type: object + type: array + error: + type: string + message: + type: string + type: object + tags: + - Query /osmosis/tokenfactory/v1beta1/denoms/factory/{creator}/{subdenom}/authority_metadata: get: operationId: DenomAuthorityMetadata diff --git a/proto/neutron/state_verifier/v1/genesis.proto b/proto/neutron/state_verifier/v1/genesis.proto new file mode 100644 index 000000000..d6ef33a7b --- /dev/null +++ b/proto/neutron/state_verifier/v1/genesis.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; +package neutron.state_verifier.v1; + +import "ibc/lightclients/tendermint/v1/tendermint.proto"; + +option go_package = "github.com/neutron-org/neutron/v5/x/state-verifier/types"; + +// ConsensusState describes a "light" consensus state of Neutron at a particular height +message ConsensusState { + int64 height = 1; + ibc.lightclients.tendermint.v1.ConsensusState cs = 2; +} + +message GenesisState { + repeated ConsensusState states = 1; +} diff --git a/proto/neutron/state_verifier/v1/query.proto b/proto/neutron/state_verifier/v1/query.proto new file mode 100644 index 000000000..8f86bf5e6 --- /dev/null +++ b/proto/neutron/state_verifier/v1/query.proto @@ -0,0 +1,23 @@ +syntax = "proto3"; +package neutron.state_verifier.v1; + +import "google/api/annotations.proto"; +import "neutron/interchainqueries/tx.proto"; + +option go_package = "github.com/neutron-org/neutron/v5/x/state-verifier/types"; + +service Query { + rpc VerifyStateValues(QueryVerifyStateValuesRequest) returns (QueryVerifyStateValuesResponse) { + option (google.api.http).get = "/neutron/state-verifier/verify_state_values"; + } +} + +// QueryVerifyStateValuesRequest describes a structure to verify storage values from Neutron state from a particular height in the past +message QueryVerifyStateValuesRequest { + uint64 height = 1; + repeated neutron.interchainqueries.StorageValue storage_values = 2; +} + +message QueryVerifyStateValuesResponse { + bool valid = 1; +} diff --git a/third_party/proto/ibc/lightclients/tendermint/v1/tendermint.proto b/third_party/proto/ibc/lightclients/tendermint/v1/tendermint.proto new file mode 100644 index 000000000..7dec438f1 --- /dev/null +++ b/third_party/proto/ibc/lightclients/tendermint/v1/tendermint.proto @@ -0,0 +1,101 @@ +syntax = "proto3"; + +package ibc.lightclients.tendermint.v1; + +option go_package = "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint;tendermint"; + +import "tendermint/types/validator.proto"; +import "tendermint/types/types.proto"; +import "cosmos/ics23/v1/proofs.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; +import "ibc/core/client/v1/client.proto"; +import "ibc/core/commitment/v1/commitment.proto"; +import "gogoproto/gogo.proto"; + +// ClientState from Tendermint tracks the current validator set, latest height, +// and a possible frozen height. +message ClientState { + option (gogoproto.goproto_getters) = false; + + string chain_id = 1; + Fraction trust_level = 2 [(gogoproto.nullable) = false]; + // duration of the period since the LastestTimestamp during which the + // submitted headers are valid for upgrade + google.protobuf.Duration trusting_period = 3 [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; + // duration of the staking unbonding period + google.protobuf.Duration unbonding_period = 4 [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; + // defines how much new (untrusted) header's Time can drift into the future. + google.protobuf.Duration max_clock_drift = 5 [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; + // Block height when the client was frozen due to a misbehaviour + ibc.core.client.v1.Height frozen_height = 6 [(gogoproto.nullable) = false]; + // Latest height the client was updated to + ibc.core.client.v1.Height latest_height = 7 [(gogoproto.nullable) = false]; + + // Proof specifications used in verifying counterparty state + repeated cosmos.ics23.v1.ProofSpec proof_specs = 8; + + // Path at which next upgraded client will be committed. + // Each element corresponds to the key for a single CommitmentProof in the + // chained proof. NOTE: ClientState must stored under + // `{upgradePath}/{upgradeHeight}/clientState` ConsensusState must be stored + // under `{upgradepath}/{upgradeHeight}/consensusState` For SDK chains using + // the default upgrade module, upgrade_path should be []string{"upgrade", + // "upgradedIBCState"}` + repeated string upgrade_path = 9; + + // allow_update_after_expiry is deprecated + bool allow_update_after_expiry = 10 [deprecated = true]; + // allow_update_after_misbehaviour is deprecated + bool allow_update_after_misbehaviour = 11 [deprecated = true]; +} + +// ConsensusState defines the consensus state from Tendermint. +message ConsensusState { + option (gogoproto.goproto_getters) = false; + + // timestamp that corresponds to the block height in which the ConsensusState + // was stored. + google.protobuf.Timestamp timestamp = 1 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + // commitment root (i.e app hash) + ibc.core.commitment.v1.MerkleRoot root = 2 [(gogoproto.nullable) = false]; + bytes next_validators_hash = 3 [(gogoproto.casttype) = "github.com/cometbft/cometbft/libs/bytes.HexBytes"]; +} + +// Misbehaviour is a wrapper over two conflicting Headers +// that implements Misbehaviour interface expected by ICS-02 +message Misbehaviour { + option (gogoproto.goproto_getters) = false; + + // ClientID is deprecated + string client_id = 1 [deprecated = true]; + Header header_1 = 2 [(gogoproto.customname) = "Header1"]; + Header header_2 = 3 [(gogoproto.customname) = "Header2"]; +} + +// Header defines the Tendermint client consensus Header. +// It encapsulates all the information necessary to update from a trusted +// Tendermint ConsensusState. The inclusion of TrustedHeight and +// TrustedValidators allows this update to process correctly, so long as the +// ConsensusState for the TrustedHeight exists, this removes race conditions +// among relayers The SignedHeader and ValidatorSet are the new untrusted update +// fields for the client. The TrustedHeight is the height of a stored +// ConsensusState on the client that will be used to verify the new untrusted +// header. The Trusted ConsensusState must be within the unbonding period of +// current time in order to correctly verify, and the TrustedValidators must +// hash to TrustedConsensusState.NextValidatorsHash since that is the last +// trusted validator set at the TrustedHeight. +message Header { + .tendermint.types.SignedHeader signed_header = 1 [(gogoproto.embed) = true]; + + .tendermint.types.ValidatorSet validator_set = 2; + ibc.core.client.v1.Height trusted_height = 3 [(gogoproto.nullable) = false]; + .tendermint.types.ValidatorSet trusted_validators = 4; +} + +// Fraction defines the protobuf message type for tmmath.Fraction that only +// supports positive values. +message Fraction { + uint64 numerator = 1; + uint64 denominator = 2; +} \ No newline at end of file diff --git a/utils/storageverification/errors.go b/utils/storageverification/errors.go new file mode 100644 index 000000000..80386c10a --- /dev/null +++ b/utils/storageverification/errors.go @@ -0,0 +1,11 @@ +package storageverification + +import "cosmossdk.io/errors" + +const StateVerificationCodespace = "state_verification" + +var ( + ErrInvalidType = errors.Register(StateVerificationCodespace, 1, "invalid type") + ErrInvalidStorageValue = errors.Register(StateVerificationCodespace, 2, "failed to check storage value") + ErrInvalidProof = errors.Register(StateVerificationCodespace, 3, "merkle proof is invalid") +) diff --git a/utils/storageverification/verify.go b/utils/storageverification/verify.go new file mode 100644 index 000000000..a17d14bce --- /dev/null +++ b/utils/storageverification/verify.go @@ -0,0 +1,50 @@ +package storageverification + +import ( + "cosmossdk.io/errors" + ibccommitmenttypes "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" + "github.com/cosmos/ibc-go/v8/modules/core/exported" + ics23 "github.com/cosmos/ics23/go" + + "github.com/neutron-org/neutron/v5/x/interchainqueries/types" +) + +type VerifyCallback func(index int) error + +// VerifyStorageValues verifies stValues slice against proof using proofSpecs +// A caller can provide verifyCallback method that will be called for each storage value from the slice with an index of the value in the slice +// to do any additional user-defined checks of storage values +func VerifyStorageValues(stValues []*types.StorageValue, root exported.Root, proofSpecs []*ics23.ProofSpec, verifyCallback VerifyCallback) error { + for index, value := range stValues { + proof, err := ibccommitmenttypes.ConvertProofs(value.Proof) + if err != nil { + return errors.Wrapf(ErrInvalidType, "failed to convert crypto.ProofOps to MerkleProof: %v", err) + } + + if verifyCallback != nil { + if err := verifyCallback(index); err != nil { + return errors.Wrapf(ErrInvalidStorageValue, err.Error()) + } + } + + path := ibccommitmenttypes.NewMerklePath(value.StoragePrefix, string(value.Key)) + // identify what kind proofs (non-existence proof always has *ics23.CommitmentProof_Nonexist as the first item) we got + // and call corresponding method to verify it + switch proof.GetProofs()[0].GetProof().(type) { + // we can get non-existence proof if someone queried some key which is not exists in the storage on remote chain + case *ics23.CommitmentProof_Nonexist: + if err := proof.VerifyNonMembership(proofSpecs, root, path); err != nil { + return errors.Wrapf(ErrInvalidProof, "failed to verify proof: %v", err) + } + value.Value = nil + case *ics23.CommitmentProof_Exist: + if err := proof.VerifyMembership(proofSpecs, root, path, value.Value); err != nil { + return errors.Wrapf(ErrInvalidProof, "failed to verify proof: %v", err) + } + default: + return errors.Wrapf(ErrInvalidProof, "unknown proof type %T", proof.GetProofs()[0].GetProof()) + } + } + + return nil +} diff --git a/wasmbinding/stargate_allowlist.go b/wasmbinding/stargate_allowlist.go index 1364c94a4..00702a2b1 100644 --- a/wasmbinding/stargate_allowlist.go +++ b/wasmbinding/stargate_allowlist.go @@ -13,13 +13,13 @@ import ( marketmaptypes "github.com/skip-mev/slinky/x/marketmap/types" oracletypes "github.com/skip-mev/slinky/x/oracle/types" - dynamicfeestypes "github.com/neutron-org/neutron/v5/x/dynamicfees/types" - crontypes "github.com/neutron-org/neutron/v5/x/cron/types" dextypes "github.com/neutron-org/neutron/v5/x/dex/types" + dynamicfeestypes "github.com/neutron-org/neutron/v5/x/dynamicfees/types" feeburnertypes "github.com/neutron-org/neutron/v5/x/feeburner/types" interchainqueriestypes "github.com/neutron-org/neutron/v5/x/interchainqueries/types" interchaintxstypes "github.com/neutron-org/neutron/v5/x/interchaintxs/types" + stateverifiertypes "github.com/neutron-org/neutron/v5/x/state-verifier/types" tokenfactorytypes "github.com/neutron-org/neutron/v5/x/tokenfactory/types" ) @@ -118,5 +118,8 @@ func AcceptedStargateQueries() wasmkeeper.AcceptedQueries { // dynamicfees "neutron.dynamicfees.v1.Query/Params": &dynamicfeestypes.QueryParamsResponse{}, + + // state verifier + "/neutron.state_verifier.v1.Query/VerifyStateValues": &stateverifiertypes.QueryVerifyStateValuesResponse{}, } } diff --git a/x/dex/keeper/msg_server_test.go b/x/dex/keeper/msg_server_test.go index 5fb64f8d6..adc1efedf 100644 --- a/x/dex/keeper/msg_server_test.go +++ b/x/dex/keeper/msg_server_test.go @@ -7,6 +7,7 @@ import ( "time" abci "github.com/cometbft/cometbft/abci/types" + "github.com/cosmos/cosmos-sdk/baseapp" "github.com/stretchr/testify/require" sdkmath "cosmossdk.io/math" @@ -1520,6 +1521,11 @@ func (s *DexTestSuite) nextBlockWithTime(blockTime time.Time) { func (s *DexTestSuite) beginBlockWithTime(blockTime time.Time) { s.Ctx = s.Ctx.WithBlockTime(blockTime) + // fill in empty CometBFT info just to avoid nil pointer panics (we don't care about validity of the info in these tests) + s.Ctx = s.Ctx.WithCometInfo(baseapp.NewBlockInfo(nil, nil, nil, abci.CommitInfo{ + Round: 0, + Votes: nil, + })) _, err := s.App.BeginBlocker(s.Ctx) s.NoError(err) } diff --git a/x/interchainqueries/keeper/keeper_test.go b/x/interchainqueries/keeper/keeper_test.go index 9ac2b5228..fafb48f77 100644 --- a/x/interchainqueries/keeper/keeper_test.go +++ b/x/interchainqueries/keeper/keeper_test.go @@ -989,7 +989,7 @@ func (suite *KeeperTestSuite) TestSubmitInterchainQueryResult() { }, } }, - iqtypes.ErrInvalidType, + iqtypes.ErrInvalidSubmittedResult, }, { "non-registered key in KV result", @@ -1239,7 +1239,7 @@ func (suite *KeeperTestSuite) TestSubmitInterchainQueryResult() { }, } }, - iqtypes.ErrInvalidProof, + iqtypes.ErrInvalidSubmittedResult, }, { "query result height is too old", diff --git a/x/interchainqueries/keeper/msg_server.go b/x/interchainqueries/keeper/msg_server.go index 50f30fa97..f92811f29 100644 --- a/x/interchainqueries/keeper/msg_server.go +++ b/x/interchainqueries/keeper/msg_server.go @@ -15,9 +15,8 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ibcclienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" //nolint:staticcheck ibcconnectiontypes "github.com/cosmos/ibc-go/v8/modules/core/03-connection/types" - ibccommitmenttypes "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" - ics23 "github.com/cosmos/ics23/go" + "github.com/neutron-org/neutron/v5/utils/storageverification" "github.com/neutron-org/neutron/v5/x/interchainqueries/types" ) @@ -235,43 +234,18 @@ func (m msgServer) SubmitQueryResult(goCtx context.Context, msg *types.MsgSubmit return nil, err } - for index, result := range msg.Result.KvResults { - proof, err := ibccommitmenttypes.ConvertProofs(result.Proof) - if err != nil { - ctx.Logger().Debug("SubmitQueryResult: failed to ConvertProofs", - "error", err, "query", query, "message", msg) - return nil, errors.Wrapf(types.ErrInvalidType, "failed to convert crypto.ProofOps to MerkleProof: %v", err) + if err := storageverification.VerifyStorageValues(msg.Result.KvResults, consensusState.GetRoot(), clientState.ProofSpecs, func(index int) error { + if !bytes.Equal(msg.Result.KvResults[index].Key, query.Keys[index].Key) { + return errors.Wrapf(types.ErrInvalidSubmittedResult, "KV key from result is not equal to registered query key: %v != %v", msg.Result.KvResults[index].Key, query.Keys[index].Key) } - if !bytes.Equal(result.Key, query.Keys[index].Key) { - return nil, errors.Wrapf(types.ErrInvalidSubmittedResult, "KV key from result is not equal to registered query key: %v != %v", result.Key, query.Keys[index].Key) + if msg.Result.KvResults[index].StoragePrefix != query.Keys[index].Path { + return errors.Wrapf(types.ErrInvalidSubmittedResult, "KV path from result is not equal to registered query storage prefix: %v != %v", msg.Result.KvResults[index].StoragePrefix, query.Keys[index].Path) } - if result.StoragePrefix != query.Keys[index].Path { - return nil, errors.Wrapf(types.ErrInvalidSubmittedResult, "KV path from result is not equal to registered query storage prefix: %v != %v", result.StoragePrefix, query.Keys[index].Path) - } - - path := ibccommitmenttypes.NewMerklePath(result.StoragePrefix, string(result.Key)) - // identify what kind proofs (non-existence proof always has *ics23.CommitmentProof_Nonexist as the first item) we got - // and call corresponding method to verify it - switch proof.GetProofs()[0].GetProof().(type) { - // we can get non-existence proof if someone queried some key which is not exists in the storage on remote chain - case *ics23.CommitmentProof_Nonexist: - if err := proof.VerifyNonMembership(clientState.ProofSpecs, consensusState.GetRoot(), path); err != nil { - ctx.Logger().Debug("SubmitQueryResult: failed to VerifyNonMembership", - "error", err, "query", query, "message", msg, "path", path) - return nil, errors.Wrapf(types.ErrInvalidProof, "failed to verify proof: %v", err) - } - result.Value = nil - case *ics23.CommitmentProof_Exist: - if err := proof.VerifyMembership(clientState.ProofSpecs, consensusState.GetRoot(), path, result.Value); err != nil { - ctx.Logger().Debug("SubmitQueryResult: failed to VerifyMembership", - "error", err, "query", query, "message", msg, "path", path) - return nil, errors.Wrapf(types.ErrInvalidProof, "failed to verify proof: %v", err) - } - default: - return nil, errors.Wrapf(types.ErrInvalidProof, "unknown proof type %T", proof.GetProofs()[0].GetProof()) - } + return nil + }); err != nil { + return nil, errors.Wrapf(types.ErrInvalidSubmittedResult, "failed to verify submitted result: %v", err) } if err = m.saveKVQueryResult(ctx, query, msg.Result); err != nil { diff --git a/x/state-verifier/README.md b/x/state-verifier/README.md new file mode 100644 index 000000000..88214dcc4 --- /dev/null +++ b/x/state-verifier/README.md @@ -0,0 +1,33 @@ +# Overview + +The State Verifier module allows to verify that some `storage values` were indeed present on a particular `block height` in the chain. + +The idea is the similar how Neutron's KV ICQ works: each `StorageValue` in Cosmos SDK is stored in [KV-IAVL storage](https://github.com/cosmos/iavl). +And to be more precise it's stored in a structure called [`MerkleTree`](https://github.com/cosmos/cosmos-sdk/blob/ae77f0080a724b159233bd9b289b2e91c0de21b5/docs/interfaces/lite/specification.md). +The tree allows to compose `Proof` for `key` and `value` pairs that can prove two things using `RootHash` of the tree: +* `key` and `value` are present in the tree; +* `key` is not present in the tree. + +Cosmos blockchain's storage is stored as a different tree for each block. +That means we can prove that a particular `KV` pair is really present (or not present) in the storage at a particular block height. + +See [Neutron's ICQ relayer implementation](https://github.com/neutron-org/neutron-query-relayer/blob/4542045ab24d2735890e70d4dc525677d5f30c8a/internal/proof/proof_impl/get_storage_values.go#L11) if you want to know how to query KV-proofs + +# Implementation + +### BeginBlocker +In each block the module's `BeginBlocker` is being called, and it saves `ConsensusState` of the current block height in the storage to use it for verification of storage values later: + +```go +consensusState := tendermint.ConsensusState{ + Timestamp: ctx.BlockTime(), // current block time + Root: ibccommitmenttypes.NewMerkleRoot(headerInfo.AppHash), // .AppHash for the previous block + NextValidatorsHash: cometInfo.GetValidatorsHash(), // hash of the validator set for the next block +} +``` + +For verification only `.Root` (`header.AppHash`) is used, but it's good to save all the values just in case and do not leave them empty. + +### VerifyStateValues query +The main query of the module that accepts slice of `[]StorageValue` structures and `blockHeight` on which those `StorageValues` are present. +The module verifies the values and returns an error if values cannot be verified `{valid: true}` structure if values are valid. \ No newline at end of file diff --git a/x/state-verifier/genesis.go b/x/state-verifier/genesis.go new file mode 100644 index 000000000..0a73afffb --- /dev/null +++ b/x/state-verifier/genesis.go @@ -0,0 +1,32 @@ +package stateverifier + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/neutron-org/neutron/v5/x/state-verifier/keeper" + "github.com/neutron-org/neutron/v5/x/state-verifier/types" +) + +// InitGenesis initializes the module's state from a provided genesis state. +func InitGenesis(ctx sdk.Context, k *keeper.Keeper, genState types.GenesisState) { + // this line is used by starport scaffolding # genesis/module/init + for _, state := range genState.States { + if err := k.WriteConsensusState(ctx, state.Height, *state.Cs); err != nil { + panic(err) + } + } +} + +// ExportGenesis returns the module's exported genesis +func ExportGenesis(ctx sdk.Context, k *keeper.Keeper) *types.GenesisState { + genesis := types.DefaultGenesis() + + allCs, err := k.GetAllConsensusStates(ctx) + if err != nil { + panic(err) + } + + genesis.States = append(genesis.States, allCs...) + + return genesis +} diff --git a/x/state-verifier/genesis_test.go b/x/state-verifier/genesis_test.go new file mode 100644 index 000000000..1fc461e69 --- /dev/null +++ b/x/state-verifier/genesis_test.go @@ -0,0 +1,67 @@ +package stateverifier_test + +import ( + "testing" + "time" + + ibccommitmenttypes "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" + tendermint "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" + "github.com/stretchr/testify/suite" + + "github.com/neutron-org/neutron/v5/testutil/apptesting" + stateverifier "github.com/neutron-org/neutron/v5/x/state-verifier" + "github.com/neutron-org/neutron/v5/x/state-verifier/types" +) + +type GenesisTestSuite struct { + apptesting.KeeperTestHelper +} + +func TestGenesisTestSuite(t *testing.T) { + suite.Run(t, new(GenesisTestSuite)) +} + +func (suite *GenesisTestSuite) SetupTest() { + suite.Setup() +} + +func (suite *GenesisTestSuite) TestInitExportGenesis() { + states := []*types.ConsensusState{ + { + Height: 1, + Cs: &tendermint.ConsensusState{ + Timestamp: time.Now().UTC(), + Root: ibccommitmenttypes.MerkleRoot{Hash: []byte("MerkleRoot")}, + NextValidatorsHash: []byte("qqqqqqqqq"), + }, + }, + { + Height: 2, + Cs: &tendermint.ConsensusState{ + Timestamp: time.Now().UTC(), + Root: ibccommitmenttypes.MerkleRoot{Hash: []byte("oafpaosfsdf")}, + NextValidatorsHash: []byte("sdfsdfsdf"), + }, + }, + { + Height: 3, + Cs: &tendermint.ConsensusState{ + Timestamp: time.Now().UTC(), + Root: ibccommitmenttypes.MerkleRoot{Hash: []byte("okjdfhjsdfsdf")}, + NextValidatorsHash: []byte("irhweiriweyrwe"), + }, + }, + } + suite.SetupTest() + k := suite.App.StateVerifierKeeper + + initialGenesis := types.GenesisState{ + States: states, + } + + stateverifier.InitGenesis(suite.Ctx, k, initialGenesis) + + exportedGenesis := stateverifier.ExportGenesis(suite.Ctx, k) + + suite.Require().EqualValues(initialGenesis, *exportedGenesis) +} diff --git a/x/state-verifier/keeper/keeper.go b/x/state-verifier/keeper/keeper.go new file mode 100644 index 000000000..187b9a40a --- /dev/null +++ b/x/state-verifier/keeper/keeper.go @@ -0,0 +1,131 @@ +package keeper + +import ( + "fmt" + + "cosmossdk.io/core/comet" + "cosmossdk.io/core/header" + "cosmossdk.io/errors" + "cosmossdk.io/log" + "cosmossdk.io/store/prefix" + storetypes "cosmossdk.io/store/types" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + ibccommitmenttypes "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" + tendermint "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" + + "github.com/neutron-org/neutron/v5/utils/storageverification" + icqtypes "github.com/neutron-org/neutron/v5/x/interchainqueries/types" + "github.com/neutron-org/neutron/v5/x/state-verifier/types" +) + +type ( + Keeper struct { + cdc codec.BinaryCodec + storeKey storetypes.StoreKey + cometInfo comet.BlockInfoService + headerInfo header.Service + authority string + } +) + +func NewKeeper( + cdc codec.BinaryCodec, + storeKey storetypes.StoreKey, + cometInfo comet.BlockInfoService, + headerInfo header.Service, + authority string, +) *Keeper { + return &Keeper{ + cdc: cdc, + storeKey: storeKey, + authority: authority, + headerInfo: headerInfo, + cometInfo: cometInfo, + } +} + +func (k *Keeper) GetAuthority() string { + return k.authority +} + +func (k *Keeper) Logger(ctx sdk.Context) log.Logger { + return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) +} + +// SaveConsensusState extracts info about the current header from the context, composes ConsensusState structure with that info +// and saves the structure to the state +func (k *Keeper) SaveConsensusState(ctx sdk.Context) error { + headerInfo := k.headerInfo.GetHeaderInfo(ctx) + cometInfo := k.cometInfo.GetCometBlockInfo(ctx) + + cs := tendermint.ConsensusState{ + Timestamp: ctx.BlockTime(), + Root: ibccommitmenttypes.NewMerkleRoot(headerInfo.AppHash), + NextValidatorsHash: cometInfo.GetValidatorsHash(), + } + + return k.WriteConsensusState(ctx, ctx.BlockHeight(), cs) +} + +// WriteConsensusState writes ConsensusState structure and corresponding height into the storage +func (k *Keeper) WriteConsensusState(ctx sdk.Context, height int64, cs tendermint.ConsensusState) error { + store := ctx.KVStore(k.storeKey) + key := types.GetConsensusStateKey(height) + + csBz, err := k.cdc.Marshal(&cs) + if err != nil { + return errors.Wrapf(sdkerrors.ErrJSONMarshal, err.Error()) + } + + store.Set(key, csBz) + + return nil +} + +// Verify verifies that provided `values` are actually present on Neutron blockchain at `blockHeight` +func (k *Keeper) Verify(ctx sdk.Context, blockHeight int64, values []*icqtypes.StorageValue) error { + store := ctx.KVStore(k.storeKey) + + // we need to use consensus state from the next height (N + 1), cause that consensus state contains .AppHash (Merkle Root) of the state for `blockHeight` (N) + csBz := store.Get(types.GetConsensusStateKey(blockHeight + 1)) + if csBz == nil { + return errors.Wrap(sdkerrors.ErrKeyNotFound, fmt.Sprintf("consensus state for block %d not found", blockHeight)) + } + + var cs tendermint.ConsensusState + if err := k.cdc.Unmarshal(csBz, &cs); err != nil { + return errors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) + } + + if err := storageverification.VerifyStorageValues(values, cs.Root, ibccommitmenttypes.GetSDKSpecs(), nil); err != nil { + return errors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) + } + + return nil +} + +// GetAllConsensusStates returns ALL consensus states that are present in the storage +// Pagination is not needed here because the method is used to export state to genesis +func (k *Keeper) GetAllConsensusStates(ctx sdk.Context) ([]*types.ConsensusState, error) { + var ( + store = prefix.NewStore(ctx.KVStore(k.storeKey), types.ConsensusStateKey) + states []*types.ConsensusState + ) + + iterator := storetypes.KVStorePrefixIterator(store, []byte{}) + defer iterator.Close() + + for ; iterator.Valid(); iterator.Next() { + cs := tendermint.ConsensusState{} + k.cdc.MustUnmarshal(iterator.Value(), &cs) + height := int64(sdk.BigEndianToUint64(iterator.Key())) + states = append(states, &types.ConsensusState{ + Height: height, + Cs: &cs, + }) + } + + return states, nil +} diff --git a/x/state-verifier/keeper/keeper_test.go b/x/state-verifier/keeper/keeper_test.go new file mode 100644 index 000000000..d6c052d2e --- /dev/null +++ b/x/state-verifier/keeper/keeper_test.go @@ -0,0 +1,182 @@ +package keeper_test + +import ( + "fmt" + "testing" + + "cosmossdk.io/math" + wasmKeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" + "github.com/cometbft/cometbft/abci/types" + "github.com/cometbft/cometbft/proto/tendermint/crypto" + sdk "github.com/cosmos/cosmos-sdk/types" + ibctypes "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" + host "github.com/cosmos/ibc-go/v8/modules/core/24-host" + ibchost "github.com/cosmos/ibc-go/v8/modules/core/exported" + "github.com/stretchr/testify/suite" + + "github.com/neutron-org/neutron/v5/app/params" + "github.com/neutron-org/neutron/v5/testutil" + iqtypes "github.com/neutron-org/neutron/v5/x/interchainqueries/types" +) + +var reflectContractPath = "../../../wasmbinding/testdata/reflect.wasm" + +type KeeperTestSuite struct { + testutil.IBCConnectionTestSuite +} + +func (suite *KeeperTestSuite) TestVerifyValue() { + tests := []struct { + name string + malleate func(sender string, ctx sdk.Context) ([]*iqtypes.StorageValue, int64, error) + }{ + { + name: "valid KV storage proof", + malleate: func(sender string, ctx sdk.Context) ([]*iqtypes.StorageValue, int64, error) { + clientKey := host.FullClientStateKey(suite.Path.EndpointA.ClientID) + + resp, err := suite.ChainA.App.Query(ctx, &types.RequestQuery{ + Path: fmt.Sprintf("store/%s/key", ibchost.StoreKey), + Height: suite.ChainA.LastHeader.Header.Height - 1, + Data: clientKey, + Prove: true, + }) + suite.Require().NoError(err) + + return []*iqtypes.StorageValue{{ + Key: resp.Key, + Proof: resp.ProofOps, + Value: resp.Value, + StoragePrefix: ibchost.StoreKey, + }}, resp.Height, nil + }, + }, + { + name: "empty KV storage proof", + malleate: func(sender string, ctx sdk.Context) ([]*iqtypes.StorageValue, int64, error) { + clientKey := host.FullClientStateKey(suite.Path.EndpointA.ClientID) + + resp, err := suite.ChainA.App.Query(ctx, &types.RequestQuery{ + Path: fmt.Sprintf("store/%s/key", ibchost.StoreKey), + Height: suite.ChainA.LastHeader.Header.Height - 1, + Data: clientKey, + Prove: true, + }) + suite.Require().NoError(err) + + return []*iqtypes.StorageValue{{ + Key: resp.Key, + Proof: nil, + Value: resp.Value, + StoragePrefix: ibchost.StoreKey, + }}, resp.Height, ibctypes.ErrInvalidMerkleProof + }, + }, + { + name: "invalid KV storage proof", + malleate: func(sender string, ctx sdk.Context) ([]*iqtypes.StorageValue, int64, error) { + clientKey := host.FullClientStateKey(suite.Path.EndpointA.ClientID) + + resp, err := suite.ChainA.App.Query(ctx, &types.RequestQuery{ + Path: fmt.Sprintf("store/%s/key", ibchost.StoreKey), + Height: suite.ChainA.LastHeader.Header.Height - 1, + Data: clientKey, + Prove: true, + }) + suite.Require().NoError(err) + + return []*iqtypes.StorageValue{{ + Key: resp.Key, + Proof: &crypto.ProofOps{Ops: []crypto.ProofOp{{Type: "dasfsdf", Key: []byte("sffgsdf"), Data: []byte("sfdsdfs")}}}, + Value: resp.Value, + StoragePrefix: ibchost.StoreKey, + }}, resp.Height, ibctypes.ErrInvalidMerkleProof + }, + }, + { + name: "invalid height for proof", + malleate: func(sender string, ctx sdk.Context) ([]*iqtypes.StorageValue, int64, error) { + clientKey := host.FullClientStateKey(suite.Path.EndpointA.ClientID) + + resp, err := suite.ChainA.App.Query(ctx, &types.RequestQuery{ + Path: fmt.Sprintf("store/%s/key", ibchost.StoreKey), + Height: suite.ChainA.LastHeader.Header.Height - 1, + Data: clientKey, + Prove: true, + }) + suite.Require().NoError(err) + + return []*iqtypes.StorageValue{{ + Key: resp.Key, + Proof: resp.ProofOps, + Value: resp.Value, + StoragePrefix: ibchost.StoreKey, + }}, resp.Height - 2, fmt.Errorf("Please ensure proof was submitted with correct proofHeight and to the correct chain.") //nolint:revive + }, + }, + { + name: "invalid storage prefix", + malleate: func(sender string, ctx sdk.Context) ([]*iqtypes.StorageValue, int64, error) { + clientKey := host.FullClientStateKey(suite.Path.EndpointA.ClientID) + + resp, err := suite.ChainA.App.Query(ctx, &types.RequestQuery{ + Path: fmt.Sprintf("store/%s/key", ibchost.StoreKey), + Height: suite.ChainA.LastHeader.Header.Height - 1, + Data: clientKey, + Prove: true, + }) + suite.Require().NoError(err) + + return []*iqtypes.StorageValue{{ + Key: resp.Key, + Proof: resp.ProofOps, + Value: resp.Value, + StoragePrefix: "kekekek", + }}, resp.Height, fmt.Errorf("Please ensure the path and value are both correct.") //nolint:revive + }, + }, + } + + for i, tc := range tests { + tt := tc + suite.Run(fmt.Sprintf("Case %s, %d/%d tests", tt.name, i+1, len(tests)), func() { + suite.SetupTest() + + var ( + ctx = suite.ChainA.GetContext() + contractOwner = wasmKeeper.RandomAccountAddress(suite.T()) + ) + + // Store code and instantiate reflect contract. + codeID := suite.StoreTestCode(ctx, contractOwner, reflectContractPath) + contractAddress := suite.InstantiateTestContract(ctx, contractOwner, codeID) + suite.Require().NotEmpty(contractAddress) + + err := testutil.SetupICAPath(suite.Path, contractAddress.String()) + suite.Require().NoError(err) + + // Top up contract address with native coins for deposit + senderAddress := suite.ChainA.SenderAccounts[0].SenderAccount.GetAddress() + suite.TopUpWallet(ctx, senderAddress, contractAddress) + + stValues, height, expectedError := tt.malleate(contractAddress.String(), ctx) + + if expectedError != nil { + suite.Require().ErrorContains(suite.GetNeutronZoneApp(suite.ChainA).StateVerifierKeeper.Verify(ctx, height, stValues), expectedError.Error()) + } else { + suite.Require().NoError(suite.GetNeutronZoneApp(suite.ChainA).StateVerifierKeeper.Verify(ctx, height, stValues)) + } + }) + } +} + +func (suite *KeeperTestSuite) TopUpWallet(ctx sdk.Context, sender, contractAddress sdk.AccAddress) { + coinsAmnt := sdk.NewCoins(sdk.NewCoin(params.DefaultDenom, math.NewInt(int64(1_000_000)))) + bankKeeper := suite.GetNeutronZoneApp(suite.ChainA).BankKeeper + err := bankKeeper.SendCoins(ctx, sender, contractAddress, coinsAmnt) + suite.Require().NoError(err) +} + +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(KeeperTestSuite)) +} diff --git a/x/state-verifier/keeper/query.go b/x/state-verifier/keeper/query.go new file mode 100644 index 000000000..a21e8f804 --- /dev/null +++ b/x/state-verifier/keeper/query.go @@ -0,0 +1,18 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/neutron-org/neutron/v5/x/state-verifier/types" +) + +// VerifyStateValues implements `VerifyStateValues` gRPC query to verify storage values +func (k *Keeper) VerifyStateValues(ctx context.Context, request *types.QueryVerifyStateValuesRequest) (*types.QueryVerifyStateValuesResponse, error) { + if err := k.Verify(sdk.UnwrapSDKContext(ctx), int64(request.Height), request.StorageValues); err != nil { + return nil, err + } + + return &types.QueryVerifyStateValuesResponse{Valid: true}, nil +} diff --git a/x/state-verifier/module.go b/x/state-verifier/module.go new file mode 100644 index 000000000..6cb0e965f --- /dev/null +++ b/x/state-verifier/module.go @@ -0,0 +1,157 @@ +package stateverifier + +import ( + "context" + "encoding/json" + "fmt" + + "cosmossdk.io/core/appmodule" + + "github.com/gorilla/mux" + + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + + abci "github.com/cometbft/cometbft/abci/types" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + + "github.com/neutron-org/neutron/v5/x/state-verifier/keeper" + "github.com/neutron-org/neutron/v5/x/state-verifier/types" +) + +var ( + _ appmodule.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} +) + +// ---------------------------------------------------------------------------- +// AppModuleBasic +// ---------------------------------------------------------------------------- + +// AppModuleBasic implements the AppModuleBasic interface that defines the independent methods a Cosmos SDK module needs to implement. +type AppModuleBasic struct { + cdc codec.BinaryCodec +} + +func (a AppModuleBasic) RegisterRESTRoutes(_ client.Context, _ *mux.Router) { +} + +func NewAppModuleBasic(cdc codec.BinaryCodec) AppModuleBasic { + return AppModuleBasic{cdc: cdc} +} + +// Name returns the name of the module as a string +func (AppModuleBasic) Name() string { + return types.ModuleName +} + +// RegisterLegacyAminoCodec registers the amino codec for the module, which is used to marshal and unmarshal structs to/from []byte in order to persist them in the module's KVStore +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterCodec(cdc) +} + +// RegisterInterfaces registers a module's interface types and their concrete implementations as proto.Message +func (a AppModuleBasic) RegisterInterfaces(reg cdctypes.InterfaceRegistry) { + types.RegisterInterfaces(reg) +} + +// DefaultGenesis returns a default GenesisState for the module, marshalled to json.RawMessage. The default GenesisState need to be defined by the module developer and is primarily used for testing +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + return cdc.MustMarshalJSON(types.DefaultGenesis()) +} + +// ValidateGenesis used to validate the GenesisState, given in its json.RawMessage form +func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, _ client.TxEncodingConfig, bz json.RawMessage) error { + var genState types.GenesisState + if err := cdc.UnmarshalJSON(bz, &genState); err != nil { + return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) + } + return genState.Validate() +} + +// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the module +func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { + err := types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)) + if err != nil { + panic(err) + } +} + +// Do not expose any CLI commands for this module + +func (a AppModuleBasic) GetTxCmd() *cobra.Command { + return &cobra.Command{} +} + +func (a AppModuleBasic) GetQueryCmd() *cobra.Command { + return &cobra.Command{} +} + +// ---------------------------------------------------------------------------- +// AppModule +// ---------------------------------------------------------------------------- +var _ appmodule.AppModule = AppModule{} + +// AppModule implements the AppModule interface that defines the inter-dependent methods that modules need to implement +type AppModule struct { + AppModuleBasic + + keeper *keeper.Keeper +} + +func NewAppModule( + cdc codec.Codec, + keeper *keeper.Keeper, +) AppModule { + return AppModule{ + AppModuleBasic: NewAppModuleBasic(cdc), + keeper: keeper, + } +} + +// IsOnePerModuleType implements the depinject.OnePerModuleType interface. +func (am AppModule) IsOnePerModuleType() { // marker +} + +// IsAppModule implements the appmodule.AppModule interface. +func (am AppModule) IsAppModule() { // marker +} + +// RegisterServices registers a gRPC query service to respond to the module-specific gRPC queries +func (am AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterQueryServer(cfg.QueryServer(), am.keeper) + // types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) +} + +// RegisterInvariants registers the invariants of the module. If an invariant deviates from its predicted value, the InvariantRegistry triggers appropriate logic (most often the chain will be halted) +func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {} + +// InitGenesis performs the module's genesis initialization. It returns no validator updates. +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, gs json.RawMessage) []abci.ValidatorUpdate { + var genState types.GenesisState + // Initialize global index to index in genesis state + cdc.MustUnmarshalJSON(gs, &genState) + + InitGenesis(ctx, am.keeper, genState) + + return []abci.ValidatorUpdate{} +} + +// ExportGenesis returns the module's exported genesis state as raw JSON bytes. +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { + genState := ExportGenesis(ctx, am.keeper) + return cdc.MustMarshalJSON(genState) +} + +// ConsensusVersion is a sequence number for state-breaking change of the module. It should be incremented on each consensus-breaking change introduced by the module. To avoid wrong/empty versions, the initial version should be set to 1 +func (AppModule) ConsensusVersion() uint64 { return types.ConsensusVersion } + +// BeginBlock contains the logic that is automatically triggered at the beginning of each block +func (am AppModule) BeginBlock(ctx context.Context) error { + return am.keeper.SaveConsensusState(sdk.UnwrapSDKContext(ctx)) +} diff --git a/x/state-verifier/types/codec.go b/x/state-verifier/types/codec.go new file mode 100644 index 000000000..847679bb4 --- /dev/null +++ b/x/state-verifier/types/codec.go @@ -0,0 +1,16 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func RegisterCodec(_ *codec.LegacyAmino) { +} + +func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { + registry.RegisterImplementations( + (*sdk.Msg)(nil), + ) +} diff --git a/x/state-verifier/types/constants.go b/x/state-verifier/types/constants.go new file mode 100644 index 000000000..6bad94d03 --- /dev/null +++ b/x/state-verifier/types/constants.go @@ -0,0 +1,3 @@ +package types + +const ConsensusVersion = 1 diff --git a/x/state-verifier/types/genesis.go b/x/state-verifier/types/genesis.go new file mode 100644 index 000000000..315d5df0a --- /dev/null +++ b/x/state-verifier/types/genesis.go @@ -0,0 +1,12 @@ +package types + +// DefaultGenesis returns the default genesis state +func DefaultGenesis() *GenesisState { + return &GenesisState{} +} + +// Validate performs basic genesis state validation returning an error upon any +// failure. +func (gs GenesisState) Validate() error { + return nil +} diff --git a/x/state-verifier/types/genesis.pb.go b/x/state-verifier/types/genesis.pb.go new file mode 100644 index 000000000..75bb7cf35 --- /dev/null +++ b/x/state-verifier/types/genesis.pb.go @@ -0,0 +1,551 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: neutron/state_verifier/v1/genesis.proto + +package types + +import ( + fmt "fmt" + proto "github.com/cosmos/gogoproto/proto" + _07_tendermint "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// ConsensusState describes a "light" consensus state of Neutron at a particular height +type ConsensusState struct { + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Cs *_07_tendermint.ConsensusState `protobuf:"bytes,2,opt,name=cs,proto3" json:"cs,omitempty"` +} + +func (m *ConsensusState) Reset() { *m = ConsensusState{} } +func (m *ConsensusState) String() string { return proto.CompactTextString(m) } +func (*ConsensusState) ProtoMessage() {} +func (*ConsensusState) Descriptor() ([]byte, []int) { + return fileDescriptor_12c2ac447c18f7c3, []int{0} +} +func (m *ConsensusState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ConsensusState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ConsensusState.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 *ConsensusState) XXX_Merge(src proto.Message) { + xxx_messageInfo_ConsensusState.Merge(m, src) +} +func (m *ConsensusState) XXX_Size() int { + return m.Size() +} +func (m *ConsensusState) XXX_DiscardUnknown() { + xxx_messageInfo_ConsensusState.DiscardUnknown(m) +} + +var xxx_messageInfo_ConsensusState proto.InternalMessageInfo + +func (m *ConsensusState) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *ConsensusState) GetCs() *_07_tendermint.ConsensusState { + if m != nil { + return m.Cs + } + return nil +} + +type GenesisState struct { + States []*ConsensusState `protobuf:"bytes,1,rep,name=states,proto3" json:"states,omitempty"` +} + +func (m *GenesisState) Reset() { *m = GenesisState{} } +func (m *GenesisState) String() string { return proto.CompactTextString(m) } +func (*GenesisState) ProtoMessage() {} +func (*GenesisState) Descriptor() ([]byte, []int) { + return fileDescriptor_12c2ac447c18f7c3, []int{1} +} +func (m *GenesisState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisState.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 *GenesisState) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisState.Merge(m, src) +} +func (m *GenesisState) XXX_Size() int { + return m.Size() +} +func (m *GenesisState) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisState.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisState proto.InternalMessageInfo + +func (m *GenesisState) GetStates() []*ConsensusState { + if m != nil { + return m.States + } + return nil +} + +func init() { + proto.RegisterType((*ConsensusState)(nil), "neutron.state_verifier.v1.ConsensusState") + proto.RegisterType((*GenesisState)(nil), "neutron.state_verifier.v1.GenesisState") +} + +func init() { + proto.RegisterFile("neutron/state_verifier/v1/genesis.proto", fileDescriptor_12c2ac447c18f7c3) +} + +var fileDescriptor_12c2ac447c18f7c3 = []byte{ + // 274 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0xd0, 0xb1, 0x4e, 0xc3, 0x30, + 0x10, 0x06, 0xe0, 0x3a, 0x95, 0x32, 0xb8, 0x88, 0x21, 0x03, 0x0a, 0x0c, 0x56, 0xd4, 0x85, 0x30, + 0xd4, 0x56, 0x8a, 0x90, 0x98, 0x90, 0x80, 0x81, 0x99, 0xb0, 0xb1, 0x20, 0x62, 0x8e, 0xc4, 0x52, + 0x6b, 0x57, 0x3e, 0xc7, 0x82, 0xb7, 0xe0, 0xb1, 0x18, 0x3b, 0x32, 0xa2, 0xe4, 0x45, 0x50, 0x9a, + 0x00, 0x2d, 0x12, 0x9b, 0x4f, 0x3a, 0x7f, 0x77, 0xf7, 0xd3, 0x63, 0x0d, 0xb5, 0xb3, 0x46, 0x0b, + 0x74, 0x8f, 0x0e, 0x1e, 0x3c, 0x58, 0xf5, 0xac, 0xc0, 0x0a, 0x9f, 0x89, 0x12, 0x34, 0xa0, 0x42, + 0xbe, 0xb2, 0xc6, 0x99, 0xe8, 0x70, 0x68, 0xe4, 0xbb, 0x8d, 0xdc, 0x67, 0x47, 0x42, 0x15, 0x52, + 0x2c, 0x54, 0x59, 0x39, 0xb9, 0x50, 0xa0, 0x1d, 0x0a, 0x07, 0xfa, 0x09, 0xec, 0x52, 0x69, 0xd7, + 0x41, 0xbf, 0x55, 0x6f, 0x4d, 0x2b, 0xba, 0x7f, 0x6d, 0x34, 0x82, 0xc6, 0x1a, 0xef, 0x3a, 0x2e, + 0x3a, 0xa0, 0x61, 0x05, 0x9d, 0x10, 0x93, 0x84, 0xa4, 0xe3, 0x7c, 0xa8, 0xa2, 0x0b, 0x1a, 0x48, + 0x8c, 0x83, 0x84, 0xa4, 0x93, 0x39, 0xe7, 0xaa, 0x90, 0x7c, 0x7b, 0x0e, 0xdf, 0x92, 0x7d, 0xc6, + 0x77, 0xcd, 0x3c, 0x90, 0x38, 0xbd, 0xa5, 0x7b, 0x37, 0xfd, 0x19, 0xfd, 0x9c, 0x4b, 0x1a, 0x6e, + 0xf6, 0xc7, 0x98, 0x24, 0xe3, 0x74, 0x32, 0x3f, 0xe1, 0xff, 0x9e, 0xf5, 0x97, 0x1b, 0x3e, 0x5e, + 0xe5, 0xef, 0x0d, 0x23, 0xeb, 0x86, 0x91, 0xcf, 0x86, 0x91, 0xb7, 0x96, 0x8d, 0xd6, 0x2d, 0x1b, + 0x7d, 0xb4, 0x6c, 0x74, 0x7f, 0x5e, 0x2a, 0x57, 0xd5, 0x05, 0x97, 0x66, 0x29, 0x06, 0x76, 0x66, + 0x6c, 0xf9, 0xfd, 0x16, 0xfe, 0x4c, 0xbc, 0xf4, 0x39, 0xcf, 0x7e, 0x72, 0x76, 0xaf, 0x2b, 0xc0, + 0x22, 0xdc, 0xe4, 0x72, 0xfa, 0x15, 0x00, 0x00, 0xff, 0xff, 0x2c, 0xbb, 0x34, 0x4c, 0x8e, 0x01, + 0x00, 0x00, +} + +func (m *ConsensusState) 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 *ConsensusState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ConsensusState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Cs != nil { + { + size, err := m.Cs.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.Height != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *GenesisState) 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 *GenesisState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.States) > 0 { + for iNdEx := len(m.States) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.States[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 +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *ConsensusState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovGenesis(uint64(m.Height)) + } + if m.Cs != nil { + l = m.Cs.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + return n +} + +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.States) > 0 { + for _, e := range m.States { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *ConsensusState) 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 ErrIntOverflowGenesis + } + 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: ConsensusState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ConsensusState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Cs", 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 + } + if m.Cs == nil { + m.Cs = &_07_tendermint.ConsensusState{} + } + if err := m.Cs.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GenesisState) 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 ErrIntOverflowGenesis + } + 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: GenesisState: wiretype end group for non-group") + } + if fieldNum <= 0 { + 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 States", 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.States = append(m.States, &ConsensusState{}) + if err := m.States[len(m.States)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/state-verifier/types/keys.go b/x/state-verifier/types/keys.go new file mode 100644 index 000000000..fbe933b08 --- /dev/null +++ b/x/state-verifier/types/keys.go @@ -0,0 +1,23 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/types" +) + +const ( + // ModuleName defines the module name + ModuleName = "state-verifier" + + // StoreKey defines the primary module store key + StoreKey = ModuleName +) + +const ( + prefixConsensusStateKey = iota + 1 +) + +var ConsensusStateKey = []byte{prefixConsensusStateKey} + +func GetConsensusStateKey(height int64) []byte { + return append(ConsensusStateKey, types.Uint64ToBigEndian(uint64(height))...) +} diff --git a/x/state-verifier/types/query.pb.go b/x/state-verifier/types/query.pb.go new file mode 100644 index 000000000..a4c48ea58 --- /dev/null +++ b/x/state-verifier/types/query.pb.go @@ -0,0 +1,623 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: neutron/state_verifier/v1/query.proto + +package types + +import ( + context "context" + fmt "fmt" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + types "github.com/neutron-org/neutron/v5/x/interchainqueries/types" + _ "google.golang.org/genproto/googleapis/api/annotations" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// QueryVerifyStateValuesRequest describes a structure to verify storage values from Neutron state from a particular height in the past +type QueryVerifyStateValuesRequest struct { + Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + StorageValues []*types.StorageValue `protobuf:"bytes,2,rep,name=storage_values,json=storageValues,proto3" json:"storage_values,omitempty"` +} + +func (m *QueryVerifyStateValuesRequest) Reset() { *m = QueryVerifyStateValuesRequest{} } +func (m *QueryVerifyStateValuesRequest) String() string { return proto.CompactTextString(m) } +func (*QueryVerifyStateValuesRequest) ProtoMessage() {} +func (*QueryVerifyStateValuesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_57fce5d311842a25, []int{0} +} +func (m *QueryVerifyStateValuesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryVerifyStateValuesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryVerifyStateValuesRequest.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 *QueryVerifyStateValuesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryVerifyStateValuesRequest.Merge(m, src) +} +func (m *QueryVerifyStateValuesRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryVerifyStateValuesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryVerifyStateValuesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryVerifyStateValuesRequest proto.InternalMessageInfo + +func (m *QueryVerifyStateValuesRequest) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *QueryVerifyStateValuesRequest) GetStorageValues() []*types.StorageValue { + if m != nil { + return m.StorageValues + } + return nil +} + +type QueryVerifyStateValuesResponse struct { + Valid bool `protobuf:"varint,1,opt,name=valid,proto3" json:"valid,omitempty"` +} + +func (m *QueryVerifyStateValuesResponse) Reset() { *m = QueryVerifyStateValuesResponse{} } +func (m *QueryVerifyStateValuesResponse) String() string { return proto.CompactTextString(m) } +func (*QueryVerifyStateValuesResponse) ProtoMessage() {} +func (*QueryVerifyStateValuesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_57fce5d311842a25, []int{1} +} +func (m *QueryVerifyStateValuesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryVerifyStateValuesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryVerifyStateValuesResponse.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 *QueryVerifyStateValuesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryVerifyStateValuesResponse.Merge(m, src) +} +func (m *QueryVerifyStateValuesResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryVerifyStateValuesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryVerifyStateValuesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryVerifyStateValuesResponse proto.InternalMessageInfo + +func (m *QueryVerifyStateValuesResponse) GetValid() bool { + if m != nil { + return m.Valid + } + return false +} + +func init() { + proto.RegisterType((*QueryVerifyStateValuesRequest)(nil), "neutron.state_verifier.v1.QueryVerifyStateValuesRequest") + proto.RegisterType((*QueryVerifyStateValuesResponse)(nil), "neutron.state_verifier.v1.QueryVerifyStateValuesResponse") +} + +func init() { + proto.RegisterFile("neutron/state_verifier/v1/query.proto", fileDescriptor_57fce5d311842a25) +} + +var fileDescriptor_57fce5d311842a25 = []byte{ + // 353 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x91, 0xc1, 0x4a, 0x2b, 0x31, + 0x14, 0x86, 0x9b, 0xde, 0xdb, 0x72, 0xc9, 0xe5, 0x5e, 0x70, 0x10, 0xa9, 0x45, 0x87, 0x32, 0x20, + 0x16, 0xa4, 0x09, 0x6d, 0x51, 0xea, 0xd6, 0x07, 0x10, 0x9c, 0x42, 0x17, 0x6e, 0x4a, 0x5a, 0x8f, + 0x33, 0x81, 0x9a, 0x4c, 0x93, 0xcc, 0xd0, 0x6e, 0xdd, 0xb8, 0x15, 0x7c, 0x1e, 0xd7, 0xba, 0x2c, + 0xb8, 0x71, 0x29, 0xad, 0x0f, 0x22, 0x93, 0x69, 0xd5, 0x5a, 0xea, 0xc2, 0xe5, 0x81, 0xf3, 0x7d, + 0xff, 0x9f, 0x1c, 0xbc, 0x27, 0x20, 0x36, 0x4a, 0x0a, 0xaa, 0x0d, 0x33, 0xd0, 0x4d, 0x40, 0xf1, + 0x4b, 0x0e, 0x8a, 0x26, 0x75, 0x3a, 0x8c, 0x41, 0x8d, 0x49, 0xa4, 0xa4, 0x91, 0xce, 0xf6, 0x7c, + 0x8d, 0x2c, 0xaf, 0x91, 0xa4, 0x5e, 0xde, 0x09, 0xa4, 0x0c, 0x06, 0x40, 0x59, 0xc4, 0x29, 0x13, + 0x42, 0x1a, 0x66, 0xb8, 0x14, 0x3a, 0x03, 0xcb, 0xde, 0xc2, 0xcf, 0x85, 0x01, 0xd5, 0x0f, 0x19, + 0x17, 0xa9, 0x97, 0x83, 0xa6, 0x66, 0x94, 0xed, 0x78, 0x37, 0x08, 0xef, 0x9e, 0xa5, 0x61, 0x9d, + 0x54, 0x3b, 0x6e, 0xa7, 0x11, 0x1d, 0x36, 0x88, 0x41, 0xfb, 0x30, 0x8c, 0x41, 0x1b, 0x67, 0x0b, + 0x17, 0x43, 0xe0, 0x41, 0x68, 0x4a, 0xa8, 0x82, 0xaa, 0xbf, 0xfd, 0xf9, 0xe4, 0x9c, 0xe2, 0xff, + 0xda, 0x48, 0xc5, 0x02, 0xe8, 0x26, 0x16, 0x28, 0xe5, 0x2b, 0xbf, 0xaa, 0x7f, 0x1b, 0xfb, 0x64, + 0xd1, 0x77, 0x25, 0x96, 0xb4, 0x33, 0xc0, 0x06, 0xf8, 0xff, 0xf4, 0xa7, 0x49, 0x7b, 0x47, 0xd8, + 0x5d, 0x57, 0x44, 0x47, 0x52, 0x68, 0x70, 0x36, 0x71, 0x21, 0x61, 0x03, 0x7e, 0x61, 0x8b, 0xfc, + 0xf1, 0xb3, 0xa1, 0xf1, 0x80, 0x70, 0xc1, 0x82, 0xce, 0x3d, 0xc2, 0x1b, 0x2b, 0xb4, 0xd3, 0x22, + 0x6b, 0xff, 0x8f, 0x7c, 0xfb, 0xf2, 0xf2, 0xf1, 0x0f, 0xc8, 0xac, 0xaa, 0xd7, 0xbc, 0x7e, 0x7a, + 0xbd, 0xcb, 0xd7, 0x9c, 0x03, 0xba, 0x74, 0xe3, 0xda, 0xc7, 0x8d, 0x2d, 0xda, 0x9d, 0x8b, 0x2d, + 0x7c, 0xe2, 0x3f, 0x4e, 0x5d, 0x34, 0x99, 0xba, 0xe8, 0x65, 0xea, 0xa2, 0xdb, 0x99, 0x9b, 0x9b, + 0xcc, 0xdc, 0xdc, 0xf3, 0xcc, 0xcd, 0x9d, 0xb7, 0x02, 0x6e, 0xc2, 0xb8, 0x47, 0xfa, 0xf2, 0x6a, + 0x21, 0xac, 0x49, 0x15, 0xbc, 0xcb, 0x93, 0x43, 0x3a, 0xfa, 0x9a, 0x60, 0xc6, 0x11, 0xe8, 0x5e, + 0xd1, 0x9e, 0xb9, 0xf9, 0x16, 0x00, 0x00, 0xff, 0xff, 0x90, 0xd2, 0x13, 0x46, 0x6c, 0x02, 0x00, + 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + VerifyStateValues(ctx context.Context, in *QueryVerifyStateValuesRequest, opts ...grpc.CallOption) (*QueryVerifyStateValuesResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) VerifyStateValues(ctx context.Context, in *QueryVerifyStateValuesRequest, opts ...grpc.CallOption) (*QueryVerifyStateValuesResponse, error) { + out := new(QueryVerifyStateValuesResponse) + err := c.cc.Invoke(ctx, "/neutron.state_verifier.v1.Query/VerifyStateValues", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + VerifyStateValues(context.Context, *QueryVerifyStateValuesRequest) (*QueryVerifyStateValuesResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) VerifyStateValues(ctx context.Context, req *QueryVerifyStateValuesRequest) (*QueryVerifyStateValuesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method VerifyStateValues not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_VerifyStateValues_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryVerifyStateValuesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).VerifyStateValues(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/neutron.state_verifier.v1.Query/VerifyStateValues", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).VerifyStateValues(ctx, req.(*QueryVerifyStateValuesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "neutron.state_verifier.v1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "VerifyStateValues", + Handler: _Query_VerifyStateValues_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "neutron/state_verifier/v1/query.proto", +} + +func (m *QueryVerifyStateValuesRequest) 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 *QueryVerifyStateValuesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryVerifyStateValuesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.StorageValues) > 0 { + for iNdEx := len(m.StorageValues) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.StorageValues[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.Height != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryVerifyStateValuesResponse) 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 *QueryVerifyStateValuesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryVerifyStateValuesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Valid { + i-- + if m.Valid { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryVerifyStateValuesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovQuery(uint64(m.Height)) + } + if len(m.StorageValues) > 0 { + for _, e := range m.StorageValues { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + +func (m *QueryVerifyStateValuesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Valid { + n += 2 + } + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QueryVerifyStateValuesRequest) 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 ErrIntOverflowQuery + } + 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: QueryVerifyStateValuesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryVerifyStateValuesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StorageValues", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.StorageValues = append(m.StorageValues, &types.StorageValue{}) + if err := m.StorageValues[len(m.StorageValues)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryVerifyStateValuesResponse) 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 ErrIntOverflowQuery + } + 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: QueryVerifyStateValuesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryVerifyStateValuesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Valid", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Valid = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipQuery(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthQuery + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupQuery + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthQuery + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/state-verifier/types/query.pb.gw.go b/x/state-verifier/types/query.pb.gw.go new file mode 100644 index 000000000..51ec48b3b --- /dev/null +++ b/x/state-verifier/types/query.pb.gw.go @@ -0,0 +1,171 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: neutron/state_verifier/v1/query.proto + +/* +Package types is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package types + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage +var _ = metadata.Join + +var ( + filter_Query_VerifyStateValues_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_VerifyStateValues_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryVerifyStateValuesRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_VerifyStateValues_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.VerifyStateValues(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_VerifyStateValues_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryVerifyStateValuesRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_VerifyStateValues_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.VerifyStateValues(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_VerifyStateValues_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_VerifyStateValues_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_VerifyStateValues_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterQueryHandler(ctx, mux, conn) +} + +// RegisterQueryHandler registers the http handlers for service Query to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) +} + +// RegisterQueryHandlerClient registers the http handlers for service Query +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "QueryClient" to call the correct interceptors. +func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + + mux.Handle("GET", pattern_Query_VerifyStateValues_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_VerifyStateValues_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_VerifyStateValues_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_VerifyStateValues_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"neutron", "state-verifier", "verify_state_values"}, "", runtime.AssumeColonVerbOpt(false))) +) + +var ( + forward_Query_VerifyStateValues_0 = runtime.ForwardResponseMessage +)