From e425ddc2a4aa3f7b8f594c84c98936a648f7df0a Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Thu, 4 Jun 2026 20:15:09 +0530 Subject: [PATCH 1/5] feat(utils): per-namespace canonicalization helpers for keys Shared canonical string forms for ballot/storage keys, keyed by CAIP-2 namespace: eip155 addresses -> EIP-55, eip155 hashes -> 0x-lowercase, solana -> base58 preserved (case-significant) / hex lowercased, other -> trimmed. Strict variants reject malformed input; lenient variants fall back to trimmed input on the vote-ingress path that must never drop a vote. Foundation for the ballot-key and token-key canonicalization fixes. --- utils/canonical.go | 201 ++++++++++++++++++++++++++++++++++++++++ utils/canonical_test.go | 136 +++++++++++++++++++++++++++ 2 files changed, 337 insertions(+) create mode 100644 utils/canonical.go create mode 100644 utils/canonical_test.go diff --git a/utils/canonical.go b/utils/canonical.go new file mode 100644 index 000000000..64c5bc62f --- /dev/null +++ b/utils/canonical.go @@ -0,0 +1,201 @@ +package utils + +import ( + "encoding/hex" + "fmt" + "strings" + + ethcommon "github.com/ethereum/go-ethereum/common" + "github.com/mr-tron/base58" +) + +// Per-CAIP-2-namespace canonical forms for ballot/storage keys: eip155 +// addresses → EIP-55, eip155 hashes → 0x-lowercase, solana → base58 preserved +// (case-significant) / hex lowercased, other → trimmed. One form per value so +// encoding variance can't fragment votes or duplicate rows. +const ( + namespaceEVM = "eip155" + namespaceSolana = "solana" +) + +const base58Alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" + +// CAIP2Namespace returns the namespace component of a CAIP-2 chain id +// ("eip155:1" → "eip155"). Returns "" when the id has no namespace. +func CAIP2Namespace(chain string) string { + parts := strings.SplitN(strings.TrimSpace(chain), ":", 2) + if len(parts) != 2 { + return "" + } + return parts[0] +} + +func isHexString(s string) bool { + if s == "" { + return false + } + _, err := hex.DecodeString(s) + return err == nil +} + +func isBase58String(s string) bool { + if s == "" { + return false + } + for _, c := range s { + if !strings.ContainsRune(base58Alphabet, c) { + return false + } + } + return true +} + +// strip0x removes a leading "0x"/"0X" and reports whether one was present. +func strip0x(s string) (string, bool) { + if len(s) >= 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X') { + return s[2:], true + } + return s, false +} + +// CanonicalizeEVMAddress validates s as a 20-byte hex address (with or +// without 0x) and returns the EIP-55 checksummed, 0x-prefixed form. +func CanonicalizeEVMAddress(s string) (string, error) { + s = strings.TrimSpace(s) + if !ethcommon.IsHexAddress(s) { + return "", fmt.Errorf("invalid EVM address %q: must be 20-byte hex", s) + } + return ethcommon.HexToAddress(s).Hex(), nil +} + +// CanonicalizeEVMHash validates s as a 32-byte hex hash (with or without 0x) +// and returns the 0x-prefixed lowercase form. +func CanonicalizeEVMHash(s string) (string, error) { + s = strings.TrimSpace(s) + body, _ := strip0x(s) + if len(body) != 64 || !isHexString(body) { + return "", fmt.Errorf("invalid EVM tx hash %q: must be 32-byte hex", s) + } + return "0x" + strings.ToLower(body), nil +} + +// CanonicalizeHexBlob lenient-canonicalizes free-length hex payloads +// (raw_payload, verification_data): valid hex (with or without 0x, even +// length) → 0x-prefixed lowercase; anything else is returned trimmed as-is. +func CanonicalizeHexBlob(s string) string { + s = strings.TrimSpace(s) + if s == "" { + return "" + } + body, _ := strip0x(s) + if len(body)%2 == 0 && isHexString(body) { + return "0x" + strings.ToLower(body) + } + return s +} + +// canonicalizeSolanaValue: hex inputs lowercase (0x kept); base58 inputs are +// charset-validated and preserved as-is (base58 is case-significant — +// lowercasing would corrupt the value). +func canonicalizeSolanaValue(s string) (string, error) { + s = strings.TrimSpace(s) + if body, had0x := strip0x(s); had0x && len(body)%2 == 0 && isHexString(body) { + return "0x" + strings.ToLower(body), nil + } + if isBase58String(s) { + return s, nil + } + return "", fmt.Errorf("invalid solana value %q: neither 0x-hex nor base58", s) +} + +// canonicalizeSolanaTxHash additionally unifies base58-encoded 64-byte +// signatures into 0x-lowercase-hex, matching the form the reference client +// submits, so hex and base58 encodings of the same signature converge. +func canonicalizeSolanaTxHash(s string) (string, error) { + canon, err := canonicalizeSolanaValue(s) + if err != nil { + return "", err + } + if strings.HasPrefix(canon, "0x") { + return canon, nil + } + if raw, decErr := base58.Decode(canon); decErr == nil && len(raw) == 64 { + return "0x" + hex.EncodeToString(raw), nil + } + return canon, nil +} + +// CanonicalizeAddressByNamespace canonicalizes an address for the given +// CAIP-2 chain. Empty input passes through (optional fields). +func CanonicalizeAddressByNamespace(chain, addr string) (string, error) { + addr = strings.TrimSpace(addr) + if addr == "" { + return "", nil + } + switch CAIP2Namespace(chain) { + case namespaceEVM: + return CanonicalizeEVMAddress(addr) + case namespaceSolana: + return canonicalizeSolanaValue(addr) + default: + return addr, nil + } +} + +// CanonicalizeTxHashByNamespace canonicalizes a transaction hash/signature +// for the given CAIP-2 chain. Empty input passes through (e.g. failed +// outbound observations carry no hash). +func CanonicalizeTxHashByNamespace(chain, txHash string) (string, error) { + txHash = strings.TrimSpace(txHash) + if txHash == "" { + return "", nil + } + switch CAIP2Namespace(chain) { + case namespaceEVM: + return CanonicalizeEVMHash(txHash) + case namespaceSolana: + return canonicalizeSolanaTxHash(txHash) + default: + return txHash, nil + } +} + +// Lenient variants for the vote-ingress / key-derivation path: canonical form +// when the value parses, trimmed input otherwise (never an error). Used there +// because that path must never drop a vote — a malformed inbound still has to +// produce an on-chain UTX record (with a failed PCTx / revert), and +// execution-level validation, not key derivation, is what rejects it. Honest +// observers of the same value still converge (same trimmed string), and the +// injective hashFields digest keeps even malformed values collision-safe. +// Strict (error-returning) variants are for admin/config paths where bad input +// should be rejected before it is persisted. + +// LenientCanonicalizeAddress canonicalizes addr for chain, falling back to +// the trimmed input when it does not parse. +func LenientCanonicalizeAddress(chain, addr string) string { + canon, err := CanonicalizeAddressByNamespace(chain, addr) + if err != nil { + return strings.TrimSpace(addr) + } + return canon +} + +// LenientCanonicalizeTxHash canonicalizes txHash for chain, falling back to +// the trimmed input when it does not parse. +func LenientCanonicalizeTxHash(chain, txHash string) string { + canon, err := CanonicalizeTxHashByNamespace(chain, txHash) + if err != nil { + return strings.TrimSpace(txHash) + } + return canon +} + +// LenientCanonicalizeEVMAddress canonicalizes a Push-Chain (EVM) address to +// EIP-55, falling back to the trimmed input when it does not parse. +func LenientCanonicalizeEVMAddress(addr string) string { + canon, err := CanonicalizeEVMAddress(addr) + if err != nil { + return strings.TrimSpace(addr) + } + return canon +} diff --git a/utils/canonical_test.go b/utils/canonical_test.go new file mode 100644 index 000000000..15ba309eb --- /dev/null +++ b/utils/canonical_test.go @@ -0,0 +1,136 @@ +package utils_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/pushchain/push-chain-node/utils" +) + +const ( + eip55Addr = "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed" + lowerAddr = "0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed" + upperAddr = "0X5AAEB6053F3E94C9B9A09F33669435E7EF1BEAED" + noPfxAddr = "5aaeb6053f3e94c9b9a09f33669435e7ef1beaed" + mixedHash = "0xB28F49668e7e76dc96D7aaBE5b7f63FEcfbd1c3574774c05e8204e749fd96fbd" + lowerHash = "0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd" + noPfxHash = "b28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd" + solPubkey = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" + solSig = "5j7s6NiJS3JAkvgkoc18WVAsiSaci2pxB2A6ueCJP4tprA2TFg9wSyTLeYouxPBJEMzJinENTkpA52YStRW5Dia7" +) + +func TestCanonicalizeEVMAddress_EquivalentEncodingsConverge(t *testing.T) { + for _, in := range []string{eip55Addr, lowerAddr, upperAddr, noPfxAddr, " " + eip55Addr + " "} { + got, err := utils.CanonicalizeEVMAddress(in) + require.NoError(t, err, "input %q", in) + require.Equal(t, eip55Addr, got, "input %q must canonicalize to EIP-55", in) + } +} + +func TestCanonicalizeEVMAddress_RejectsMalformed(t *testing.T) { + for _, in := range []string{"", "0x12", "0xZZaeb6053f3e94c9b9a09f33669435e7ef1beaed", lowerAddr + "ab", "not-an-address"} { + _, err := utils.CanonicalizeEVMAddress(in) + require.Error(t, err, "input %q must be rejected", in) + } +} + +func TestCanonicalizeEVMHash_EquivalentEncodingsConverge(t *testing.T) { + upper0X := "0X" + "B28F49668E7E76DC96D7AABE5B7F63FECFBD1C3574774C05E8204E749FD96FBD" + for _, in := range []string{mixedHash, lowerHash, noPfxHash, upper0X, " " + lowerHash + " "} { + got, err := utils.CanonicalizeEVMHash(in) + require.NoError(t, err, "input %q", in) + require.Equal(t, lowerHash, got, "input %q must canonicalize to 0x-lowercase", in) + } +} + +func TestCanonicalizeEVMHash_Keeps0xPrefix(t *testing.T) { + got, err := utils.CanonicalizeEVMHash(noPfxHash) + require.NoError(t, err) + require.Equal(t, "0x", got[:2], "canonical hash form must keep the 0x prefix") +} + +func TestCanonicalizeEVMHash_RejectsMalformed(t *testing.T) { + for _, in := range []string{"", "0x1234", lowerHash + "00", "0xZZ" + noPfxHash[2:]} { + _, err := utils.CanonicalizeEVMHash(in) + require.Error(t, err, "input %q must be rejected", in) + } +} + +func TestCanonicalizeAddressByNamespace_Solana_PreservesBase58Case(t *testing.T) { + got, err := utils.CanonicalizeAddressByNamespace("solana:mainnet", solPubkey) + require.NoError(t, err) + require.Equal(t, solPubkey, got, "base58 pubkeys are case-significant and must not be altered") +} + +func TestCanonicalizeAddressByNamespace_Solana_HexLowercased(t *testing.T) { + got, err := utils.CanonicalizeAddressByNamespace("solana:devnet", "0xABCDEF12") + require.NoError(t, err) + require.Equal(t, "0xabcdef12", got) +} + +func TestCanonicalizeAddressByNamespace_EVM(t *testing.T) { + got, err := utils.CanonicalizeAddressByNamespace("eip155:1", lowerAddr) + require.NoError(t, err) + require.Equal(t, eip55Addr, got) +} + +func TestCanonicalizeAddressByNamespace_EmptyPassthrough(t *testing.T) { + got, err := utils.CanonicalizeAddressByNamespace("eip155:1", "") + require.NoError(t, err) + require.Equal(t, "", got) +} + +func TestCanonicalizeAddressByNamespace_UnknownNamespaceTrims(t *testing.T) { + got, err := utils.CanonicalizeAddressByNamespace("cosmos:push", " push1abc ") + require.NoError(t, err) + require.Equal(t, "push1abc", got) +} + +func TestCanonicalizeTxHashByNamespace_EVM(t *testing.T) { + got, err := utils.CanonicalizeTxHashByNamespace("eip155:11155111", mixedHash) + require.NoError(t, err) + require.Equal(t, lowerHash, got) +} + +func TestCanonicalizeTxHashByNamespace_Solana_Base58SigConvergesWithHex(t *testing.T) { + // The reference client converts base58 signatures to 0x-hex before + // submitting; a client submitting raw base58 must land on the same form. + fromB58, err := utils.CanonicalizeTxHashByNamespace("solana:devnet", solSig) + require.NoError(t, err) + require.Equal(t, "0x", fromB58[:2], "64-byte base58 signature should converge to 0x-hex") + require.Len(t, fromB58, 2+128) + + again, err := utils.CanonicalizeTxHashByNamespace("solana:devnet", fromB58) + require.NoError(t, err) + require.Equal(t, fromB58, again, "canonicalization must be idempotent") +} + +func TestCanonicalizeTxHashByNamespace_Solana_NonSigBase58Preserved(t *testing.T) { + // 32-byte base58 values (pubkey-length) are not signatures; preserved as-is. + got, err := utils.CanonicalizeTxHashByNamespace("solana:devnet", solPubkey) + require.NoError(t, err) + require.Equal(t, solPubkey, got) +} + +func TestCanonicalizeTxHashByNamespace_EmptyPassthrough(t *testing.T) { + got, err := utils.CanonicalizeTxHashByNamespace("eip155:1", "") + require.NoError(t, err) + require.Equal(t, "", got) +} + +func TestCanonicalizeHexBlob(t *testing.T) { + require.Equal(t, "0xabcd12", utils.CanonicalizeHexBlob("0xABCD12")) + require.Equal(t, "0xabcd12", utils.CanonicalizeHexBlob("ABCD12")) + require.Equal(t, "", utils.CanonicalizeHexBlob(" ")) + // Non-hex content is preserved trimmed, never mangled. + require.Equal(t, "not-hex", utils.CanonicalizeHexBlob(" not-hex ")) + // Odd-length hex strings are not valid byte blobs; preserved. + require.Equal(t, "0xabc", utils.CanonicalizeHexBlob("0xabc")) +} + +func TestCAIP2Namespace(t *testing.T) { + require.Equal(t, "eip155", utils.CAIP2Namespace("eip155:1")) + require.Equal(t, "solana", utils.CAIP2Namespace("solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1")) + require.Equal(t, "", utils.CAIP2Namespace("no-colon")) +} From b59db53c274cfc78ac21a764667fb868f805a492 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Thu, 4 Jun 2026 20:15:20 +0530 Subject: [PATCH 2/5] fix(uregistry): canonicalize token addresses in storage keys [F-2026-17022] GetTokenConfigsStorageKey canonicalizes the address per CAIP-2 namespace (EIP-55 for eip155), making the storage key the single canonical chokepoint for add/update/remove/get. The PRC20 reverse index moves from lowercase to EIP-55 and GetTokenConfigByPRC20 canonicalizes its query identically. TokenConfig/NativeRepresentation ValidateBasic enforce parseable addresses, so case-variant duplicate registrations collide on the canonical key and are rejected. --- .../keeper/canonical_token_key_test.go | 101 ++++++++++++++++++ x/uregistry/keeper/keeper.go | 23 +++- x/uregistry/types/keys.go | 20 +++- .../types/msg_add_token_config_test.go | 4 +- .../types/msg_update_token_config_test.go | 4 +- .../types/native_represenation_test.go | 4 +- x/uregistry/types/native_representation.go | 10 ++ x/uregistry/types/token_config.go | 9 ++ x/uregistry/types/token_config_test.go | 12 +-- 9 files changed, 167 insertions(+), 20 deletions(-) create mode 100644 x/uregistry/keeper/canonical_token_key_test.go diff --git a/x/uregistry/keeper/canonical_token_key_test.go b/x/uregistry/keeper/canonical_token_key_test.go new file mode 100644 index 000000000..1e30dacec --- /dev/null +++ b/x/uregistry/keeper/canonical_token_key_test.go @@ -0,0 +1,101 @@ +package keeper_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/pushchain/push-chain-node/x/uregistry/types" +) + +// Regression suite for case-canonical token storage keys: the same logical +// EVM address in any case/prefix variant must always resolve to one row, +// while case-significant solana base58 addresses are preserved verbatim. + +const ( + canonChainEVM = "eip155:11155111" + canonChainSol = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1" + + // EIP-55 canonical form + variants of the same 20 bytes. + tokenEIP55 = "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238" + tokenLower = "0x1c7d4b196cb0c7b01d743fbc6116a902379c7238" + tokenUpper = "0X1C7D4B196CB0C7B01D743FBC6116A902379C7238" + + prc20EIP55 = "0x387b9C8Db60E74999aAAC5A2b7825b400F12d68E" + prc20Lower = "0x387b9c8db60e74999aaac5a2b7825b400f12d68e" + + solMint = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" +) + +func TestTokenStorageKey_CaseVariantsConverge(t *testing.T) { + want := types.GetTokenConfigsStorageKey(canonChainEVM, tokenEIP55) + for _, variant := range []string{tokenLower, tokenUpper, " " + tokenEIP55 + " "} { + require.Equal(t, want, types.GetTokenConfigsStorageKey(canonChainEVM, variant), + "variant %q must map to the canonical storage key", variant) + } + require.Contains(t, want, tokenEIP55, "canonical key embeds the EIP-55 form") +} + +func TestTokenStorageKey_SolanaBase58Preserved(t *testing.T) { + key := types.GetTokenConfigsStorageKey(canonChainSol, solMint) + require.Contains(t, key, solMint, "base58 mint must be preserved byte-for-byte (case-significant)") +} + +func TestGetTokenConfig_CrossCaseLookup(t *testing.T) { + ctx, k, _ := setupPRC20Keeper(t) + + // Registered with lowercase; readable via any variant. + cfg := makeTokenCfg(canonChainEVM, tokenLower, prc20EIP55) + require.NoError(t, k.TokenConfigs.Set(ctx, types.GetTokenConfigsStorageKey(cfg.Chain, cfg.Address), cfg)) + + for _, variant := range []string{tokenEIP55, tokenLower, tokenUpper} { + got, err := k.GetTokenConfig(ctx, canonChainEVM, variant) + require.NoError(t, err, "lookup with %q must hit the canonical row", variant) + require.Equal(t, tokenLower, got.Address) + } +} + +func TestAddTokenConfig_DuplicateCaseVariantRejected(t *testing.T) { + ctx, k, _ := setupPRC20Keeper(t) + + // AddTokenConfig requires the chain to be registered. + require.NoError(t, k.ChainConfigs.Set(ctx, canonChainEVM, types.ChainConfig{Chain: canonChainEVM})) + + first := makeTokenCfg(canonChainEVM, tokenEIP55, prc20EIP55) + require.NoError(t, k.AddTokenConfig(ctx, &first)) + + // Same address, different case → same canonical key → duplicate. + dup := makeTokenCfg(canonChainEVM, tokenLower, prc20EIP55) + err := k.AddTokenConfig(ctx, &dup) + require.Error(t, err) + require.Contains(t, err.Error(), "already exists", + "case-variant duplicate registration must collide on the canonical key") +} + +func TestRemoveTokenConfig_CrossCaseRemoval(t *testing.T) { + ctx, k, _ := setupPRC20Keeper(t) + require.NoError(t, k.ChainConfigs.Set(ctx, canonChainEVM, types.ChainConfig{Chain: canonChainEVM})) + + cfg := makeTokenCfg(canonChainEVM, tokenEIP55, prc20EIP55) + require.NoError(t, k.AddTokenConfig(ctx, &cfg)) + + // Remove using the all-lowercase variant — must target the same row. + require.NoError(t, k.RemoveTokenConfig(ctx, canonChainEVM, tokenLower)) + + _, err := k.GetTokenConfig(ctx, canonChainEVM, tokenEIP55) + require.Error(t, err, "row must be gone regardless of removal-key casing") +} + +func TestGetTokenConfigByPRC20_RealHexEIP55Index(t *testing.T) { + ctx, k, _ := setupPRC20Keeper(t) + + // Stored with lowercase PRC20 — index canonicalizes to EIP-55. + cfg := makeTokenCfg(canonChainEVM, tokenEIP55, prc20Lower) + require.NoError(t, k.TokenConfigs.Set(ctx, types.GetTokenConfigsStorageKey(cfg.Chain, cfg.Address), cfg)) + + for _, query := range []string{prc20EIP55, prc20Lower, "0X387B9C8DB60E74999AAAC5A2B7825B400F12D68E"} { + got, err := k.GetTokenConfigByPRC20(ctx, canonChainEVM, query) + require.NoError(t, err, "PRC20 lookup with %q must resolve via EIP-55 index", query) + require.Equal(t, tokenEIP55, got.Address) + } +} diff --git a/x/uregistry/keeper/keeper.go b/x/uregistry/keeper/keeper.go index b4388d13d..5ca94c248 100755 --- a/x/uregistry/keeper/keeper.go +++ b/x/uregistry/keeper/keeper.go @@ -17,11 +17,12 @@ import ( "cosmossdk.io/collections/indexes" storetypes "cosmossdk.io/core/store" "cosmossdk.io/log" + "github.com/pushchain/push-chain-node/utils" "github.com/pushchain/push-chain-node/x/uregistry/types" ) -// TokenConfigIndexes: PRC20Index maps lowercased PRC20 contract address → -// token storage key for O(1) GetTokenConfigByPRC20. Rows without +// TokenConfigIndexes: PRC20Index maps canonical (EIP-55) PRC20 contract +// address → token storage key for O(1) GetTokenConfigByPRC20. Rows without // NativeRepresentation index under the empty-string sentinel which is never // queried. Framework auto-maintains on every Set/Remove. type TokenConfigIndexes struct { @@ -32,6 +33,17 @@ func (t TokenConfigIndexes) IndexesList() []collections.Index[string, types.Toke return []collections.Index[string, types.TokenConfig]{t.PRC20Index} } +// canonicalPRC20 returns the EIP-55 form of a PRC20 address (PRC20s are EVM). +// Lenient (falls back to lowercase-trim) so index writes never fail; strict +// enforcement is in NativeRepresentation.ValidateBasic. +func canonicalPRC20(addr string) string { + canon, err := utils.CanonicalizeEVMAddress(addr) + if err != nil { + return strings.ToLower(strings.TrimSpace(addr)) + } + return canon +} + func newTokenConfigIndexes(sb *collections.SchemaBuilder) TokenConfigIndexes { return TokenConfigIndexes{ PRC20Index: indexes.NewMulti( @@ -41,7 +53,7 @@ func newTokenConfigIndexes(sb *collections.SchemaBuilder) TokenConfigIndexes { if v.NativeRepresentation == nil || v.NativeRepresentation.ContractAddress == "" { return "", nil // sentinel — non-PRC20 rows } - return strings.ToLower(v.NativeRepresentation.ContractAddress), nil + return canonicalPRC20(v.NativeRepresentation.ContractAddress), nil }, ), } @@ -233,10 +245,11 @@ func (k Keeper) GetTokenConfigByPRC20( prc20Addr string, ) (types.TokenConfig, error) { - prc20Addr = strings.ToLower(strings.TrimSpace(prc20Addr)) - if prc20Addr == "" { + if strings.TrimSpace(prc20Addr) == "" { return types.TokenConfig{}, fmt.Errorf("prc20 address is empty") } + // Same canonical form as the index function, so any case variant hits the row. + prc20Addr = canonicalPRC20(prc20Addr) // PRC20 addresses are globally unique by construction; MatchExact returns at most one. iter, err := k.TokenConfigs.Indexes.PRC20Index.MatchExact(ctx, prc20Addr) diff --git a/x/uregistry/types/keys.go b/x/uregistry/types/keys.go index ea13eec77..257ad8134 100755 --- a/x/uregistry/types/keys.go +++ b/x/uregistry/types/keys.go @@ -5,6 +5,8 @@ import ( "strings" "cosmossdk.io/collections" + + "github.com/pushchain/push-chain-node/utils" ) var ( @@ -26,7 +28,7 @@ var ( // TokenConfigsName is the name of the tokenConfigs collection. TokenConfigsName = "token_configs" - // PRC20Index secondary index on TokenConfigs: lowercased PRC20 → storage key. + // PRC20Index secondary index on TokenConfigs: canonical (EIP-55) PRC20 → storage key. PRC20IndexKey = collections.NewPrefix(3) PRC20IndexName = "prc20_index" ) @@ -39,7 +41,19 @@ const ( QuerierRoute = ModuleName ) -// GetTokenConfigsStorageKey returns the storage key for token config storage in the format "chain:address". +// GetTokenConfigsStorageKey builds the "chain:address" key with the address +// canonicalized per namespace, so case variants map to one row. Strict format +// enforcement is in TokenConfig.ValidateBasic. func GetTokenConfigsStorageKey(chain, address string) string { - return fmt.Sprintf("%s:%s", chain, strings.TrimSpace(address)) + return fmt.Sprintf("%s:%s", chain, CanonicalTokenAddress(chain, address)) +} + +// CanonicalTokenAddress is the lenient canonicalizer used for key paths: +// canonical form when the address parses, trimmed input otherwise. +func CanonicalTokenAddress(chain, address string) string { + canon, err := utils.CanonicalizeAddressByNamespace(chain, address) + if err != nil { + return strings.TrimSpace(address) + } + return canon } diff --git a/x/uregistry/types/msg_add_token_config_test.go b/x/uregistry/types/msg_add_token_config_test.go index dd8e64666..b4b5f1cd8 100644 --- a/x/uregistry/types/msg_add_token_config_test.go +++ b/x/uregistry/types/msg_add_token_config_test.go @@ -13,7 +13,7 @@ func TestMsgAddTokenConfig_ValidateBasic(t *testing.T) { validTokenConfig := &types.TokenConfig{ Chain: "eip155:1", - Address: "0xabc123", + Address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", Name: "USD Coin", Symbol: "USDC", Decimals: 6, @@ -28,7 +28,7 @@ func TestMsgAddTokenConfig_ValidateBasic(t *testing.T) { invalidTokenConfig := &types.TokenConfig{ Chain: "", // invalid - Address: "0xabc123", + Address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", Name: "USD Coin", Symbol: "USDC", Decimals: 6, diff --git a/x/uregistry/types/msg_update_token_config_test.go b/x/uregistry/types/msg_update_token_config_test.go index 97c9cff94..5cbe78c17 100644 --- a/x/uregistry/types/msg_update_token_config_test.go +++ b/x/uregistry/types/msg_update_token_config_test.go @@ -13,7 +13,7 @@ func TestMsgUpdateTokenConfig_ValidateBasic(t *testing.T) { validTokenConfig := &types.TokenConfig{ Chain: "eip155:1", - Address: "0xabc123", + Address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", Name: "USD Coin", Symbol: "USDC", Decimals: 6, @@ -28,7 +28,7 @@ func TestMsgUpdateTokenConfig_ValidateBasic(t *testing.T) { invalidTokenConfig := &types.TokenConfig{ Chain: "", // invalid - Address: "0xabc123", + Address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", Name: "USD Coin", Symbol: "USDC", Decimals: 6, diff --git a/x/uregistry/types/native_represenation_test.go b/x/uregistry/types/native_represenation_test.go index aa603fcde..1196a1df8 100644 --- a/x/uregistry/types/native_represenation_test.go +++ b/x/uregistry/types/native_represenation_test.go @@ -34,7 +34,7 @@ func TestNativeRepresentation_ValidateBasic(t *testing.T) { name: "valid - only contract_address set with 0x", nativeRep: types.NativeRepresentation{ Denom: "", - ContractAddress: "0xabc123def4567890", + ContractAddress: "0x387b9C8Db60E74999aAAC5A2b7825b400F12d68E", }, expectErr: false, }, @@ -42,7 +42,7 @@ func TestNativeRepresentation_ValidateBasic(t *testing.T) { name: "valid - both denom and contract_address set", nativeRep: types.NativeRepresentation{ Denom: "uatom", - ContractAddress: "0xdeadbeefcafebabe", + ContractAddress: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238", }, expectErr: false, }, diff --git a/x/uregistry/types/native_representation.go b/x/uregistry/types/native_representation.go index 597de4d19..242f524e7 100644 --- a/x/uregistry/types/native_representation.go +++ b/x/uregistry/types/native_representation.go @@ -6,6 +6,8 @@ import ( "cosmossdk.io/errors" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + "github.com/pushchain/push-chain-node/utils" ) // Stringer method for NativeRepresentation @@ -30,5 +32,13 @@ func (p NativeRepresentation) ValidateBasic() error { return errors.Wrap(sdkerrors.ErrInvalidRequest, "contract_address must start with 0x") } + // PRC20s live on Push Chain (EVM): must be a parseable 20-byte hex address + // so the PRC20 reverse index always carries the canonical EIP-55 form. + if p.ContractAddress != "" { + if _, err := utils.CanonicalizeEVMAddress(p.ContractAddress); err != nil { + return errors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid contract_address: %s", err) + } + } + return nil } diff --git a/x/uregistry/types/token_config.go b/x/uregistry/types/token_config.go index db46ff1d5..7483a11f7 100644 --- a/x/uregistry/types/token_config.go +++ b/x/uregistry/types/token_config.go @@ -6,6 +6,8 @@ import ( "cosmossdk.io/errors" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + "github.com/pushchain/push-chain-node/utils" ) // Stringer method for TokenConfig @@ -27,6 +29,13 @@ func (p TokenConfig) ValidateBasic() error { return errors.Wrap(sdkerrors.ErrInvalidRequest, "token contract address cannot be empty") } + // Enforce a parseable address for the chain's namespace (e.g. 20-byte hex + // for eip155, base58 for solana) so every registration lands on the + // canonical storage key. + if _, err := utils.CanonicalizeAddressByNamespace(p.Chain, p.Address); err != nil { + return errors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid token address for chain %s: %s", p.Chain, err) + } + if strings.TrimSpace(p.Name) == "" { return errors.Wrap(sdkerrors.ErrInvalidRequest, "token name cannot be empty") } diff --git a/x/uregistry/types/token_config_test.go b/x/uregistry/types/token_config_test.go index b2b6d8d22..c1cc24629 100644 --- a/x/uregistry/types/token_config_test.go +++ b/x/uregistry/types/token_config_test.go @@ -23,7 +23,7 @@ func TestTokenConfig_ValidateBasic(t *testing.T) { name: "valid token config", config: types.TokenConfig{ Chain: "eip155:1", - Address: "0xabc123", + Address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", Name: "USD Coin", Symbol: "USDC", Decimals: 6, @@ -38,7 +38,7 @@ func TestTokenConfig_ValidateBasic(t *testing.T) { name: "missing chain", config: types.TokenConfig{ Chain: "", - Address: "0xabc123", + Address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", Name: "USD Coin", Symbol: "USDC", Decimals: 6, @@ -68,7 +68,7 @@ func TestTokenConfig_ValidateBasic(t *testing.T) { name: "zero decimals", config: types.TokenConfig{ Chain: "eip155:1", - Address: "0xabc123", + Address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", Name: "USD Coin", Symbol: "USDC", Decimals: 0, @@ -83,7 +83,7 @@ func TestTokenConfig_ValidateBasic(t *testing.T) { name: "invalid token type", config: types.TokenConfig{ Chain: "eip155:1", - Address: "0xabc123", + Address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", Name: "USD Coin", Symbol: "USDC", Decimals: 6, @@ -98,7 +98,7 @@ func TestTokenConfig_ValidateBasic(t *testing.T) { name: "missing liquidity cap", config: types.TokenConfig{ Chain: "eip155:1", - Address: "0xabc123", + Address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", Name: "USD Coin", Symbol: "USDC", Decimals: 6, @@ -113,7 +113,7 @@ func TestTokenConfig_ValidateBasic(t *testing.T) { name: "invalid native representation contract address", config: types.TokenConfig{ Chain: "eip155:1", - Address: "0xabc123", + Address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", Name: "USD Coin", Symbol: "USDC", Decimals: 6, From bccba5a9d424cf8c660707cddbed86fdf521f880 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Thu, 4 Jun 2026 20:15:37 +0530 Subject: [PATCH 3/5] fix(utss): canonicalize fund-migration txHash before ballot key [F-2026-17041] VoteFundMigration canonicalizes the observed txHash against the migration's chain namespace before deriving the ballot key, so equivalent hash encodings from different validators aggregate on one ballot instead of fragmenting. Adds MsgVoteFundMigration.ValidateBasic. --- test/integration/utss/fund_migration_test.go | 62 ++++++++++++++++++-- x/utss/keeper/msg_vote_fund_migration.go | 8 +++ x/utss/types/msg_vote_fund_migration.go | 28 +++++++++ 3 files changed, 92 insertions(+), 6 deletions(-) create mode 100644 x/utss/types/msg_vote_fund_migration.go diff --git a/test/integration/utss/fund_migration_test.go b/test/integration/utss/fund_migration_test.go index 36f7877a4..ad43c0096 100644 --- a/test/integration/utss/fund_migration_test.go +++ b/test/integration/utss/fund_migration_test.go @@ -272,7 +272,7 @@ func TestVoteFundMigration(t *testing.T) { migrationId, err := app.UtssKeeper.InitiateFundMigration(ctx, oldKeyId, testChain) require.NoError(t, err) - txHash := "0xdeadbeef1234567890" + txHash := "0xdeadbeef12345678deadbeef12345678deadbeef12345678deadbeef12345678" // Vote with all validators (2/3 quorum needed, so 3 votes for 3 validators) for i, val := range universalVals { @@ -320,7 +320,7 @@ func TestVoteFundMigration(t *testing.T) { migrationId, err := app.UtssKeeper.InitiateFundMigration(ctx, oldKeyId, testChain) require.NoError(t, err) - txHash := "0xfailedtx" + txHash := "" // Vote failure with all validators for _, val := range universalVals { @@ -338,7 +338,7 @@ func TestVoteFundMigration(t *testing.T) { app, ctx, universalVals, _ := setupFundMigrationTest(t, 3, false) valAddr, _ := sdk.ValAddressFromBech32(universalVals[0]) - err := app.UtssKeeper.VoteFundMigration(ctx, valAddr, 999, "0xtx", true) + err := app.UtssKeeper.VoteFundMigration(ctx, valAddr, 999, "0x1111111111111111111111111111111111111111111111111111111111111111", true) require.ErrorContains(t, err, "not found") }) @@ -351,12 +351,12 @@ func TestVoteFundMigration(t *testing.T) { // Finalize it first for _, val := range universalVals { valAddr, _ := sdk.ValAddressFromBech32(val) - _ = app.UtssKeeper.VoteFundMigration(ctx, valAddr, migrationId, "0xtx", true) + _ = app.UtssKeeper.VoteFundMigration(ctx, valAddr, migrationId, "0x1111111111111111111111111111111111111111111111111111111111111111", true) } // Try to vote again valAddr, _ := sdk.ValAddressFromBech32(universalVals[0]) - err = app.UtssKeeper.VoteFundMigration(ctx, valAddr, migrationId, "0xtx2", true) + err = app.UtssKeeper.VoteFundMigration(ctx, valAddr, migrationId, "0x2222222222222222222222222222222222222222222222222222222222222222", true) require.ErrorContains(t, err, "already finalized") }) } @@ -391,7 +391,7 @@ func TestFundMigrationQueries(t *testing.T) { // Finalize it for _, val := range universalVals { valAddr, _ := sdk.ValAddressFromBech32(val) - _ = app.UtssKeeper.VoteFundMigration(ctx, valAddr, migrationId, "0xtx", true) + _ = app.UtssKeeper.VoteFundMigration(ctx, valAddr, migrationId, "0x1111111111111111111111111111111111111111111111111111111111111111", true) } // Should be removed from pending @@ -403,3 +403,53 @@ func TestFundMigrationQueries(t *testing.T) { require.Equal(t, 0, pendingCount) }) } + +// TestVoteFundMigration_EquivalentHashEncodingsConverge is the F-2026-17041 +// regression: three validators submit the SAME migration tx hash in three +// different encodings (EIP-55-style mixed case, lowercase, no 0x prefix). +// Canonicalization in VoteFundMigration must land all votes on ONE ballot, +// finalizing the migration — pre-fix each encoding produced its own ballot +// and quorum never formed. +func TestVoteFundMigration_EquivalentHashEncodingsConverge(t *testing.T) { + app, ctx, universalVals, oldKeyId := setupFundMigrationTest(t, 3, false) + + migrationId, err := app.UtssKeeper.InitiateFundMigration(ctx, oldKeyId, testChain) + require.NoError(t, err) + + canonical := "0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd" + encodings := []string{ + "0xB28F49668E7E76DC96D7AABE5B7F63FECFBD1C3574774C05E8204E749FD96FBD", // uppercase + "0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd", // lowercase + "b28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd", // no prefix + } + require.Len(t, universalVals, 3) + + for i, val := range universalVals { + valAddr, err := sdk.ValAddressFromBech32(val) + require.NoError(t, err) + require.NoError(t, app.UtssKeeper.VoteFundMigration(ctx, valAddr, migrationId, encodings[i], true), + "vote %d with encoding %q must be accepted", i, encodings[i]) + } + + // All three encodings converged on one ballot → quorum reached → COMPLETED. + migration, err := app.UtssKeeper.FundMigrations.Get(ctx, migrationId) + require.NoError(t, err) + require.Equal(t, utsstypes.FundMigrationStatus_FUND_MIGRATION_STATUS_COMPLETED, migration.Status, + "equivalent encodings must aggregate on one ballot and finalize") + require.Equal(t, canonical, migration.TxHash, + "stored tx hash must be the canonical 0x-lowercase form") +} + +// TestVoteFundMigration_MalformedHashRejected: strict per-namespace +// validation rejects garbage hashes for EVM chains instead of keying a +// ballot off them. +func TestVoteFundMigration_MalformedHashRejected(t *testing.T) { + app, ctx, universalVals, oldKeyId := setupFundMigrationTest(t, 3, false) + + migrationId, err := app.UtssKeeper.InitiateFundMigration(ctx, oldKeyId, testChain) + require.NoError(t, err) + + valAddr, _ := sdk.ValAddressFromBech32(universalVals[0]) + err = app.UtssKeeper.VoteFundMigration(ctx, valAddr, migrationId, "0xnot-a-real-hash", true) + require.ErrorContains(t, err, "invalid tx hash") +} diff --git a/x/utss/keeper/msg_vote_fund_migration.go b/x/utss/keeper/msg_vote_fund_migration.go index 00292c2db..8bbd1a6d5 100644 --- a/x/utss/keeper/msg_vote_fund_migration.go +++ b/x/utss/keeper/msg_vote_fund_migration.go @@ -6,6 +6,7 @@ import ( "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/pushchain/push-chain-node/utils" "github.com/pushchain/push-chain-node/x/utss/types" ) @@ -28,6 +29,13 @@ func (k Keeper) VoteFundMigration( return fmt.Errorf("fund migration %d is already finalized (status: %s)", migrationId, migration.Status.String()) } + // Canonicalize the observed txHash for the migration's chain so encoding + // variants (case, 0x prefix) from different validators land on one ballot. + txHash, err = utils.CanonicalizeTxHashByNamespace(migration.Chain, txHash) + if err != nil { + return fmt.Errorf("invalid tx hash for chain %s: %w", migration.Chain, err) + } + k.Logger().Info("fund migration vote received", "migration_id", migrationId, "validator", universalValidator.String(), diff --git a/x/utss/types/msg_vote_fund_migration.go b/x/utss/types/msg_vote_fund_migration.go new file mode 100644 index 000000000..d06739a28 --- /dev/null +++ b/x/utss/types/msg_vote_fund_migration.go @@ -0,0 +1,28 @@ +package types + +import ( + "strings" + + "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +var _ sdk.Msg = &MsgVoteFundMigration{} + +// ValidateBasic does a sanity check on the provided data. +func (msg *MsgVoteFundMigration) ValidateBasic() error { + if _, err := sdk.AccAddressFromBech32(msg.Signer); err != nil { + return errors.Wrap(err, "invalid signer address") + } + if msg.MigrationId == 0 { + return errors.Wrap(sdkerrors.ErrInvalidRequest, "migration_id is required") + } + // A successful migration observation must carry the external tx hash. + // Canonicalization (per the migration's chain namespace) happens in the + // keeper, where the chain is known. + if msg.Success && strings.TrimSpace(msg.TxHash) == "" { + return errors.Wrap(sdkerrors.ErrInvalidRequest, "tx_hash is required when success is true") + } + return nil +} From 47af110c1c10d91f4fcd771acaf6b38e0640ec1c Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Thu, 4 Jun 2026 20:15:53 +0530 Subject: [PATCH 4/5] fix(uexecutor): canonical voting digests for inbound/outbound ballots [F-2026-16039, F-2026-16632] Replace full-proto-Marshal ballot identity with explicit injective digests (hashFields: sha256 over per-field sha256 hex digests joined by ':'), domain-separated via collections prefixes so inbound vs outbound keys stay disjoint in the shared Ballots map. The inbound digest covers every execution-relevant field except universal_payload (recomputed on-chain from raw_payload); the outbound digest covers all observation fields. Inbound fields are canonicalized at vote / admin-revert ingress and the key functions self-canonicalize, so stored state, UTX keys and registry lookups all converge on one representation per logical event. Because the digests are one-way, the ballot terminal hook now locates the audit-trail entry by scanning PendingInbounds for the ballot id instead of decoding the inbound back out of the id. Existing test assertions updated for the canonical (EIP-55 / lowercase-hash) stored forms. --- .../uexecutor/execute_inbound_gas_test.go | 5 +- .../inbound_ballot_convergence_test.go | 180 +++++++++++ test/integration/uexecutor/query_v2_test.go | 3 +- .../uexecutor/rescue_funds_test.go | 5 +- .../uexecutor/revert_stuck_inbound_test.go | 11 +- x/uexecutor/keeper/admin_revert.go | 4 + x/uexecutor/keeper/ballot_hooks.go | 54 ++-- x/uexecutor/keeper/msg_vote_inbound.go | 4 + x/uexecutor/keeper/msg_vote_outbound.go | 8 + x/uexecutor/types/inbound.go | 22 ++ x/uexecutor/types/keys.go | 89 +++++- x/uexecutor/types/keys_canonical_test.go | 293 ++++++++++++++++++ 12 files changed, 623 insertions(+), 55 deletions(-) create mode 100644 test/integration/uexecutor/inbound_ballot_convergence_test.go create mode 100644 x/uexecutor/types/keys_canonical_test.go diff --git a/test/integration/uexecutor/execute_inbound_gas_test.go b/test/integration/uexecutor/execute_inbound_gas_test.go index 67b82107d..b01de0073 100644 --- a/test/integration/uexecutor/execute_inbound_gas_test.go +++ b/test/integration/uexecutor/execute_inbound_gas_test.go @@ -11,6 +11,7 @@ import ( "github.com/pushchain/push-chain-node/app" utils "github.com/pushchain/push-chain-node/test/utils" + chainutils "github.com/pushchain/push-chain-node/utils" uexecutortypes "github.com/pushchain/push-chain-node/x/uexecutor/types" uregistrytypes "github.com/pushchain/push-chain-node/x/uregistry/types" uvalidatortypes "github.com/pushchain/push-chain-node/x/uvalidator/types" @@ -348,7 +349,9 @@ func TestInboundGas(t *testing.T) { for _, ob := range utx.OutboundTx { if ob.TxType == uexecutortypes.TxType_INBOUND_REVERT { - require.Equal(t, inbound.Sender, ob.Recipient, + // Stored inbound fields are canonicalized at vote ingress, so the + // fallback recipient is the EIP-55 form of the sender. + require.Equal(t, chainutils.LenientCanonicalizeEVMAddress(inbound.Sender), ob.Recipient, "revert outbound recipient should fall back to Sender when RevertInstructions is nil") return } diff --git a/test/integration/uexecutor/inbound_ballot_convergence_test.go b/test/integration/uexecutor/inbound_ballot_convergence_test.go new file mode 100644 index 000000000..12a27633a --- /dev/null +++ b/test/integration/uexecutor/inbound_ballot_convergence_test.go @@ -0,0 +1,180 @@ +package integrationtest + +import ( + "strings" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + + utils "github.com/pushchain/push-chain-node/test/utils" + uexecutortypes "github.com/pushchain/push-chain-node/x/uexecutor/types" + uvalidatortypes "github.com/pushchain/push-chain-node/x/uvalidator/types" +) + +// Ballot-convergence regression: validators observing the SAME bridge event +// but submitting different string encodings (EIP-55 vs lowercase vs +// 0X-uppercase) must aggregate on ONE ballot and finalize. Pre-fix, the +// ballot key hashed the full proto encoding, so each encoding variant +// produced its own ballot and quorum never formed. +func TestVoteInbound_EncodingVariantsConvergeOnOneBallot(t *testing.T) { + app, ctx, vals, baseInbound, coreVals := setupInboundBridgeTest(t, 4) + + // Same logical event in three different encodings. + const txLower = "0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd" + variants := make([]uexecutortypes.Inbound, 3) + for i := range variants { + v := *baseInbound + v.RevertInstructions = &uexecutortypes.RevertInstructions{ + FundRecipient: baseInbound.RevertInstructions.FundRecipient, + } + variants[i] = v + } + + // Voter 0: all lowercase. + variants[0].TxHash = txLower + variants[0].Sender = strings.ToLower(baseInbound.Sender) + variants[0].AssetAddr = strings.ToLower(baseInbound.AssetAddr) + variants[0].Recipient = strings.ToLower(baseInbound.Recipient) + variants[0].RevertInstructions.FundRecipient = strings.ToLower(baseInbound.RevertInstructions.FundRecipient) + + // Voter 1: as produced by the EVM client (EIP-55 mixed case). + variants[1].TxHash = "0xB28F49668E7E76DC96D7AABE5B7F63FECFBD1C3574774C05E8204E749FD96FBD" + + // Voter 2: 0X-uppercase everything. + variants[2].TxHash = "0X" + strings.ToUpper(txLower[2:]) + variants[2].Sender = "0X" + strings.ToUpper(baseInbound.Sender[2:]) + variants[2].AssetAddr = "0X" + strings.ToUpper(baseInbound.AssetAddr[2:]) + + // Vote with 3 of 4 validators (votesNeeded = (2*4)/3+1 = 3), each using a + // different encoding of the same event. + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(coreVals[i].OperatorAddress) + require.NoError(t, err) + coreValAcc := sdk.AccAddress(valAddr).String() + + require.NoError(t, utils.ExecVoteInbound(t, ctx, app, vals[i], coreValAcc, &variants[i]), + "vote %d with encoding variant must be accepted", i) + + // Mid-flight (after the first two votes): the audit trail must show a + // SINGLE variant — both encodings recorded as the same observation. + if i == 1 { + utxKey := uexecutortypes.GetInboundUniversalTxKey(variants[0]) + entry, err := app.UexecutorKeeper.PendingInbounds.Get(ctx, utxKey) + require.NoError(t, err) + require.Len(t, entry.Variants, 1, + "different encodings of the same event must record as ONE variant, not fragment") + require.Len(t, entry.Variants[0].Voters, 2) + } + } + + // Quorum reached on the single converged ballot → inbound executed. + isPending, err := app.UexecutorKeeper.IsPendingInbound(ctx, variants[2]) + require.NoError(t, err) + require.False(t, isPending, "ballot must finalize — encodings converged on one ballot") + + // Exactly one UTX exists, under the canonical key, regardless of which + // encoding is used to derive it. + utxCount := 0 + require.NoError(t, app.UexecutorKeeper.UniversalTx.Walk(ctx, nil, func(_ string, _ uexecutortypes.UniversalTx) (bool, error) { + utxCount++ + return false, nil + })) + require.Equal(t, 1, utxCount, "one event must yield exactly one UniversalTx") + + for i, v := range variants { + utx, found, err := app.UexecutorKeeper.GetUniversalTx(ctx, uexecutortypes.GetInboundUniversalTxKey(v)) + require.NoError(t, err) + require.True(t, found, "variant %d must derive the canonical UTX key", i) + // Stored inbound carries canonical forms (EIP-55 addresses, lowercase hash). + require.Equal(t, txLower, utx.InboundTx.TxHash) + require.Equal(t, baseInbound.AssetAddr, utx.InboundTx.AssetAddr, + "stored asset address must be the canonical EIP-55 form") + } +} + +// Outbound twin of the convergence test: three validators observe the same +// destination-chain tx but submit the hash in different encodings. The +// canonical outbound digest must aggregate them on one ballot and finalize. +func TestVoteOutbound_EncodingVariantsConvergeOnOneBallot(t *testing.T) { + app, ctx, _, utxId, outbound, coreVals := setupOutboundVotingTest(t, 4) + + const destLower = "0x46cec75af4cb022d4f234e4d4b9b35e3aae66048007a06a7c1de6b9b76d27a39" + encodings := []string{ + destLower, // canonical lowercase + "0x46CEC75AF4CB022D4F234E4D4B9B35E3AAE66048007A06A7C1DE6B9B76D27A39", // uppercase body + "46cec75af4cb022d4f234e4d4b9b35e3aae66048007a06a7c1de6b9b76d27a39", // no prefix + } + + for i := 0; i < 3; i++ { + valAddr, err := sdk.ValAddressFromBech32(coreVals[i].OperatorAddress) + require.NoError(t, err) + + obs := uexecutortypes.OutboundObservation{ + Success: true, + BlockHeight: 42, + TxHash: encodings[i], + GasFeeUsed: outbound.GasFee, + } + require.NoError(t, app.UexecutorKeeper.VoteOutbound(ctx, valAddr, utxId, outbound.Id, obs), + "vote %d with encoding %q must be accepted", i, encodings[i]) + } + + // One ballot → quorum → outbound observed, with the canonical hash stored. + utx, _, err := app.UexecutorKeeper.GetUniversalTx(ctx, utxId) + require.NoError(t, err) + require.Equal(t, uexecutortypes.Status_OBSERVED, utx.OutboundTx[0].OutboundStatus, + "equivalent encodings must aggregate on one ballot and finalize") + require.NotNil(t, utx.OutboundTx[0].ObservedTx) + require.Equal(t, destLower, utx.OutboundTx[0].ObservedTx.TxHash, + "stored observation must carry the canonical 0x-lowercase hash") +} + +// TestInboundBallotKey_StoreAndFetchAcrossEncodings demonstrates the full +// key lifecycle: derive a ballot key from one encoding of an event, store a +// ballot under it, then derive the key again from a DIFFERENT encoding of the +// same event and fetch the stored ballot back. This is what lets a second +// validator's differently-encoded vote find the first validator's ballot. +func TestInboundBallotKey_StoreAndFetchAcrossEncodings(t *testing.T) { + chainApp, ctx, _, baseInbound, _ := setupInboundBridgeTest(t, 1) + + // Encoding A: all lowercase. Derive the key and store a ballot under it. + a := *baseInbound + a.TxHash = "0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd" + a.Sender = strings.ToLower(baseInbound.Sender) + a.AssetAddr = strings.ToLower(baseInbound.AssetAddr) + + keyA, err := uexecutortypes.GetInboundBallotKey(a) + require.NoError(t, err) + t.Logf("derived ballot key (encoding A) = %s", keyA) + + stored := uvalidatortypes.Ballot{ + Id: keyA, + BallotType: uvalidatortypes.BallotObservationType_BALLOT_OBSERVATION_TYPE_INBOUND_TX, + EligibleVoters: []string{"cosmosvaloper1aaa"}, + Votes: []uvalidatortypes.VoteResult{uvalidatortypes.VoteResult_VOTE_RESULT_SUCCESS}, + VotingThreshold: 1, + Status: uvalidatortypes.BallotStatus_BALLOT_STATUS_PENDING, + BlockHeightCreated: ctx.BlockHeight(), + BlockHeightExpiry: ctx.BlockHeight() + 100, + } + require.NoError(t, chainApp.UvalidatorKeeper.SetBallot(ctx, stored)) + + // Encoding B: 0X-uppercase tx hash, EIP-55 addresses — same logical event. + b := *baseInbound + b.TxHash = "0X" + strings.ToUpper(a.TxHash[2:]) + b.Sender = baseInbound.Sender + b.AssetAddr = baseInbound.AssetAddr + + keyB, err := uexecutortypes.GetInboundBallotKey(b) + require.NoError(t, err) + t.Logf("derived ballot key (encoding B) = %s", keyB) + + require.Equal(t, keyA, keyB, "different encodings of the same event derive the same key") + + // Fetch the ballot stored under encoding A's key, using encoding B's key. + fetched, err := chainApp.UvalidatorKeeper.GetBallot(ctx, keyB) + require.NoError(t, err) + require.Equal(t, keyA, fetched.Id, "encoding B's key fetches the ballot stored under encoding A") + require.Equal(t, uvalidatortypes.BallotStatus_BALLOT_STATUS_PENDING, fetched.Status) +} diff --git a/test/integration/uexecutor/query_v2_test.go b/test/integration/uexecutor/query_v2_test.go index 610925543..6fc447e53 100644 --- a/test/integration/uexecutor/query_v2_test.go +++ b/test/integration/uexecutor/query_v2_test.go @@ -9,6 +9,7 @@ import ( "google.golang.org/grpc/status" utils "github.com/pushchain/push-chain-node/test/utils" + chainutils "github.com/pushchain/push-chain-node/utils" uexecutorkeeper "github.com/pushchain/push-chain-node/x/uexecutor/keeper" uexecutortypes "github.com/pushchain/push-chain-node/x/uexecutor/types" typesv2 "github.com/pushchain/push-chain-node/x/uexecutor/typesv2" @@ -65,7 +66,7 @@ func TestGetUniversalTxV2(t *testing.T) { require.NotNil(t, utx.InboundTx) require.Equal(t, inbound.SourceChain, utx.InboundTx.SourceChain) require.Equal(t, inbound.TxHash, utx.InboundTx.TxHash) - require.Equal(t, inbound.Sender, utx.InboundTx.Sender) + require.Equal(t, chainutils.LenientCanonicalizeEVMAddress(inbound.Sender), utx.InboundTx.Sender) require.Equal(t, inbound.Amount, utx.InboundTx.Amount) require.Equal(t, inbound.AssetAddr, utx.InboundTx.AssetAddr) diff --git a/test/integration/uexecutor/rescue_funds_test.go b/test/integration/uexecutor/rescue_funds_test.go index 378d88b27..0fa054361 100644 --- a/test/integration/uexecutor/rescue_funds_test.go +++ b/test/integration/uexecutor/rescue_funds_test.go @@ -17,6 +17,7 @@ import ( "github.com/pushchain/push-chain-node/app" utils "github.com/pushchain/push-chain-node/test/utils" + chainutils "github.com/pushchain/push-chain-node/utils" uexecutortypes "github.com/pushchain/push-chain-node/x/uexecutor/types" ) @@ -80,7 +81,7 @@ func setupRescueFundsTest( *app.ChainApp, sdk.Context, []string, // universalVals - string, // utxId of the failed CEA UTX + string, // utxId of the failed CEA UTX []stakingtypes.Validator, ) { t.Helper() @@ -205,7 +206,7 @@ func TestRescueFunds(t *testing.T) { rescueOb := findRescueOutbound(utx) require.NotNil(t, rescueOb) // Falls back to original inbound sender - require.Equal(t, utils.GetDefaultAddresses().DefaultTestAddr, rescueOb.Recipient) + require.Equal(t, chainutils.LenientCanonicalizeEVMAddress(utils.GetDefaultAddresses().DefaultTestAddr), rescueOb.Recipient) }) t.Run("rescue is rejected for non-CEA inbound with no reverted auto-revert", func(t *testing.T) { diff --git a/test/integration/uexecutor/revert_stuck_inbound_test.go b/test/integration/uexecutor/revert_stuck_inbound_test.go index 74d26d3e8..d5dc8e8cc 100644 --- a/test/integration/uexecutor/revert_stuck_inbound_test.go +++ b/test/integration/uexecutor/revert_stuck_inbound_test.go @@ -8,6 +8,7 @@ import ( "github.com/pushchain/push-chain-node/app" utils "github.com/pushchain/push-chain-node/test/utils" + chainutils "github.com/pushchain/push-chain-node/utils" uexecutorkeeper "github.com/pushchain/push-chain-node/x/uexecutor/keeper" uexecutortypes "github.com/pushchain/push-chain-node/x/uexecutor/types" uregistrytypes "github.com/pushchain/push-chain-node/x/uregistry/types" @@ -41,9 +42,9 @@ func setupRevertStuckInbound(t *testing.T) (chainApp *app.ChainApp, ctx sdk.Cont usdcAddress := utils.GetDefaultAddresses().ExternalUSDCAddr tokenConfig := uregistrytypes.TokenConfig{ - Chain: "eip155:11155111", - Address: usdcAddress.String(), - Name: "USD Coin", Symbol: "USDC", Decimals: 6, Enabled: true, + Chain: "eip155:11155111", + Address: usdcAddress.String(), + Name: "USD Coin", Symbol: "USDC", Decimals: 6, Enabled: true, LiquidityCap: "1000000000000000000000000", TokenType: 1, NativeRepresentation: &uregistrytypes.NativeRepresentation{ ContractAddress: prc20Address.String(), @@ -130,7 +131,7 @@ func TestRevertStuckInbound_HappyPath_ExpiredBallot_CreatesRevertOutbound(t *tes "recipient must use RevertInstructions.FundRecipient when set") require.Equal(t, inbound.Amount, ob.Amount, "full amount refunded") require.Equal(t, inbound.AssetAddr, ob.ExternalAssetAddr, "external asset addr must match the original deposit asset") - require.Equal(t, inbound.Sender, ob.Sender, "sender field carries original depositor") + require.Equal(t, chainutils.LenientCanonicalizeEVMAddress(inbound.Sender), ob.Sender, "sender field carries original depositor") // --- PendingOutbounds index assertions --- pending, err := chainApp.UexecutorKeeper.PendingOutbounds.Get(ctx, ob.Id) @@ -157,7 +158,7 @@ func TestRevertStuckInbound_RecipientFallback_UsesSender(t *testing.T) { utx, _, _ := chainApp.UexecutorKeeper.GetUniversalTx(ctx, resp.UtxId) require.Len(t, utx.OutboundTx, 1) - require.Equal(t, inbound.Sender, utx.OutboundTx[0].Recipient, + require.Equal(t, chainutils.LenientCanonicalizeEVMAddress(inbound.Sender), utx.OutboundTx[0].Recipient, "with no RevertInstructions, refund goes to original sender") } diff --git a/x/uexecutor/keeper/admin_revert.go b/x/uexecutor/keeper/admin_revert.go index 2f77e52f8..d7a606941 100644 --- a/x/uexecutor/keeper/admin_revert.go +++ b/x/uexecutor/keeper/admin_revert.go @@ -26,6 +26,10 @@ import ( func (k Keeper) RevertStuckInbound(ctx context.Context, inbound types.Inbound) (utxId, outboundId string, err error) { sdkCtx := sdk.UnwrapSDKContext(ctx) + // Same canonical form as the vote path, so the admin-supplied payload + // derives the same ballot key / UTX key the votes did. + inbound.Canonicalize() + if vErr := inbound.ValidateBasic(); vErr != nil { return "", "", errors.Wrap(sdkErrors.ErrInvalidRequest, vErr.Error()) } diff --git a/x/uexecutor/keeper/ballot_hooks.go b/x/uexecutor/keeper/ballot_hooks.go index 23ebec19e..85e53c5e4 100644 --- a/x/uexecutor/keeper/ballot_hooks.go +++ b/x/uexecutor/keeper/ballot_hooks.go @@ -2,10 +2,7 @@ package keeper import ( "context" - "encoding/hex" - "errors" - "cosmossdk.io/collections" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/pushchain/push-chain-node/x/uexecutor/types" @@ -77,46 +74,41 @@ func (h BallotHooks) afterInboundBallotTerminal( ballotID string, status uvalidatortypes.BallotStatus, ) error { - // Decode ballot ID → Inbound (ballot ID for INBOUND_TX is hex(marshal(Inbound))). - bz, err := hex.DecodeString(ballotID) + // Ballot IDs are one-way canonical digests (not reversible), so locate + // the owning audit-trail entry by scanning PendingInbounds for the + // variant carrying this ballot ID. The pending set is small and + // transient, and this hook only fires on terminal transitions. + var ( + utxKey string + entry types.PendingInboundEntry + found bool + ) + err := h.k.PendingInbounds.Walk(ctx, nil, func(key string, e types.PendingInboundEntry) (bool, error) { + for _, v := range e.Variants { + if v.BallotId == ballotID { + utxKey, entry, found = key, e, true + return true, nil + } + } + return false, nil + }) if err != nil { - h.k.Logger().Warn("ballot terminal hook: cannot hex-decode inbound ballot id", - "ballot_id", ballotID, "err", err.Error()) - return nil + return err } - var inbound types.Inbound - if err := inbound.Unmarshal(bz); err != nil { - h.k.Logger().Warn("ballot terminal hook: cannot unmarshal inbound from ballot id", - "ballot_id", ballotID, "err", err.Error()) + if !found { + // Entry was already cleared (e.g. the consensus-success path in + // VoteInbound already removed it before this hook fires), or the + // ballot does not belong to a tracked inbound. Nothing to do. return nil } - utxKey := types.GetInboundUniversalTxKey(inbound) - - entry, err := h.k.PendingInbounds.Get(ctx, utxKey) - if err != nil { - if errors.Is(err, collections.ErrNotFound) { - // Entry was already cleared (e.g. the consensus-success path in - // VoteInbound already removed it before this hook fires). Nothing - // to do. - return nil - } - return err - } // Mark this variant's terminal status. - found := false for i := range entry.Variants { if entry.Variants[i].BallotId == ballotID { entry.Variants[i].TerminalStatus = status - found = true break } } - if !found { - h.k.Logger().Warn("ballot terminal hook: inbound variant not found in pending entry", - "ballot_id", ballotID, "utx_key", utxKey) - return nil - } // If any variant is still PENDING, persist the updated entry and wait. for _, v := range entry.Variants { diff --git a/x/uexecutor/keeper/msg_vote_inbound.go b/x/uexecutor/keeper/msg_vote_inbound.go index 0d584bf87..a20a2651d 100644 --- a/x/uexecutor/keeper/msg_vote_inbound.go +++ b/x/uexecutor/keeper/msg_vote_inbound.go @@ -16,6 +16,10 @@ import ( // query what happened to their cross-chain tx instead of having funds silently stuck // in the gateway contract. func (k Keeper) VoteInbound(ctx context.Context, universalValidator sdk.ValAddress, inbound types.Inbound) error { + // Canonicalize first so every derived key + the stored inbound use one + // representation per logical event. + inbound.Canonicalize() + k.Logger().Info("vote inbound received", "validator", universalValidator.String(), "source_chain", inbound.SourceChain, diff --git a/x/uexecutor/keeper/msg_vote_outbound.go b/x/uexecutor/keeper/msg_vote_outbound.go index 4b7a31b2a..ae9a5b726 100644 --- a/x/uexecutor/keeper/msg_vote_outbound.go +++ b/x/uexecutor/keeper/msg_vote_outbound.go @@ -3,8 +3,10 @@ package keeper import ( "context" "fmt" + "strings" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/pushchain/push-chain-node/utils" "github.com/pushchain/push-chain-node/x/uexecutor/types" ) @@ -51,6 +53,12 @@ func (k Keeper) VoteOutbound( return fmt.Errorf("outbound %s not found in UniversalTx %s", outboundId, utxId) } + // Canonicalize the observed tx hash for the destination chain so encoding + // variants of the same observation land on one ballot. + observedTx.TxHash = utils.LenientCanonicalizeTxHash(outbound.DestinationChain, observedTx.TxHash) + observedTx.GasFeeUsed = strings.TrimSpace(observedTx.GasFeeUsed) + observedTx.ErrorMsg = strings.TrimSpace(observedTx.ErrorMsg) + // Prevent double-finalization if outbound.OutboundStatus != types.Status_PENDING { k.Logger().Warn("vote outbound rejected: outbound already finalized", diff --git a/x/uexecutor/types/inbound.go b/x/uexecutor/types/inbound.go index b9b18af2a..c857d48ae 100644 --- a/x/uexecutor/types/inbound.go +++ b/x/uexecutor/types/inbound.go @@ -13,6 +13,28 @@ import ( const EvmZeroAddress = "0x0000000000000000000000000000000000000000" +// Canonicalize normalizes encoding-variant fields in place (per source-chain +// namespace) so the same event from any observer is byte-identical across +// ballot keys, UTX keys and registry lookups. Lenient (unparseable values are +// kept trimmed, never rejected) because the vote path must always record a +// UTX — execution-level validation rejects malformed inbounds later. +func (p *Inbound) Canonicalize() { + p.SourceChain = strings.TrimSpace(p.SourceChain) + p.TxHash = utils.LenientCanonicalizeTxHash(p.SourceChain, p.TxHash) + p.Sender = utils.LenientCanonicalizeAddress(p.SourceChain, p.Sender) + p.AssetAddr = utils.LenientCanonicalizeAddress(p.SourceChain, p.AssetAddr) + // Recipient lives on Push Chain (EVM) regardless of source chain. + p.Recipient = utils.LenientCanonicalizeEVMAddress(p.Recipient) + p.LogIndex = strings.TrimSpace(p.LogIndex) + p.Amount = strings.TrimSpace(p.Amount) + p.RawPayload = utils.CanonicalizeHexBlob(p.RawPayload) + p.VerificationData = utils.CanonicalizeHexBlob(p.VerificationData) + if p.RevertInstructions != nil { + // Refunds return to the source chain. + p.RevertInstructions.FundRecipient = utils.LenientCanonicalizeAddress(p.SourceChain, p.RevertInstructions.FundRecipient) + } +} + // NormalizeForTxType zeroes out fields that are irrelevant for the given TxType, // and decodes raw_payload into universal_payload for payload types. // This should be called by the core module after ballot finalization. diff --git a/x/uexecutor/types/keys.go b/x/uexecutor/types/keys.go index 036242ca7..23452ae20 100755 --- a/x/uexecutor/types/keys.go +++ b/x/uexecutor/types/keys.go @@ -4,8 +4,11 @@ import ( "crypto/sha256" "encoding/hex" fmt "fmt" + "strings" "cosmossdk.io/collections" + + "github.com/pushchain/push-chain-node/utils" ) var ( @@ -46,6 +49,13 @@ var ( // refund flow. See plan-pending-inbound-cleanup.md. ExpiredInboundsKey = collections.NewPrefix(8) ExpiredInboundsName = "expired_inbounds" + + // Domain separators for the canonical ballot-key digests. Hashed into the + // key preimage (never used as store prefixes); kept in this block so prefix + // numbers stay unique. They keep inbound vs outbound keys disjoint in the + // shared uvalidator Ballots map. + InboundBallotDomain = collections.NewPrefix(9) + OutboundBallotDomain = collections.NewPrefix(10) ) const ( @@ -56,18 +66,63 @@ const ( QuerierRoute = ModuleName ) +// GetInboundUniversalTxKey: UTX identity from canonical (source_chain, tx_hash, +// log_index). Canonicalizes locals; caller's inbound is not mutated. func GetInboundUniversalTxKey(inbound Inbound) string { - data := fmt.Sprintf("%s:%s:%s", inbound.SourceChain, inbound.TxHash, inbound.LogIndex) + chain := strings.TrimSpace(inbound.SourceChain) + txHash := utils.LenientCanonicalizeTxHash(chain, inbound.TxHash) + logIndex := strings.TrimSpace(inbound.LogIndex) + data := fmt.Sprintf("%s:%s:%s", chain, txHash, logIndex) hash := sha256.Sum256([]byte(data)) return hex.EncodeToString(hash[:]) // hash[:] converts [32]byte → []byte } +// hashFields = sha256( hex(sha256(domain)) : hex(sha256(f0)) : ... ). Per-field +// hashing makes it injective — a sub-hash can't contain ':', so no field value +// can shift a boundary and collide with a different tuple. +func hashFields(domain collections.Prefix, parts ...string) string { + hashed := make([]string, 0, len(parts)+1) + d := sha256.Sum256(domain.Bytes()) + hashed = append(hashed, hex.EncodeToString(d[:])) + for _, p := range parts { + sum := sha256.Sum256([]byte(p)) + hashed = append(hashed, hex.EncodeToString(sum[:])) + } + final := sha256.Sum256([]byte(strings.Join(hashed, ":"))) + return hex.EncodeToString(final[:]) +} + +// GetInboundBallotKey: versioned canonical digest over every execution- +// relevant field (so quorum implies agreement on the outcome), excluding +// universal_payload (recomputed on-chain from raw_payload). Self-canonicalizes, +// so any caller gets one ballot per logical event. func GetInboundBallotKey(inbound Inbound) (string, error) { - bz, err := inbound.Marshal() - if err != nil { - return "", err + chain := strings.TrimSpace(inbound.SourceChain) + + // nil RevertInstructions and an empty FundRecipient are semantically + // identical (revert falls back to sender) — digest them identically. + fundRecipient := "" + if inbound.RevertInstructions != nil { + fundRecipient = utils.LenientCanonicalizeAddress(chain, inbound.RevertInstructions.FundRecipient) } - return hex.EncodeToString(bz), nil + + return hashFields( + InboundBallotDomain, + chain, + utils.LenientCanonicalizeTxHash(chain, inbound.TxHash), + strings.TrimSpace(inbound.LogIndex), + utils.LenientCanonicalizeAddress(chain, inbound.Sender), + // Recipient lives on Push Chain (EVM) regardless of source chain. + utils.LenientCanonicalizeEVMAddress(inbound.Recipient), + strings.TrimSpace(inbound.Amount), + utils.LenientCanonicalizeAddress(chain, inbound.AssetAddr), + fmt.Sprintf("%d", inbound.TxType), + utils.CanonicalizeHexBlob(inbound.VerificationData), + fundRecipient, + fmt.Sprintf("%t", inbound.IsCEA), + utils.CanonicalizeHexBlob(inbound.RawPayload), + // universal_payload intentionally excluded (derived, ignored on-chain). + ), nil } func GetPcUniversalTxKey(pcCaip string, pc PCTx) string { @@ -76,21 +131,25 @@ func GetPcUniversalTxKey(pcCaip string, pc PCTx) string { return hex.EncodeToString(hash[:]) } +// GetOutboundBallotKey: versioned canonical digest over all observation fields +// (all consensus-critical — gas_fee_used drives the refund, error_msg must be +// agreed so no voter can inject unconsensused text). Caller canonicalizes +// tx_hash for the destination chain at vote ingress. func GetOutboundBallotKey( utxId string, outboundIndex string, observedTx OutboundObservation, ) (string, error) { - - bz, err := observedTx.Marshal() - if err != nil { - return "", err - } - - data := append([]byte(utxId+":"+outboundIndex+":"), bz...) - hash := sha256.Sum256(data) - - return hex.EncodeToString(hash[:]), nil + return hashFields( + OutboundBallotDomain, + utxId, + outboundIndex, + fmt.Sprintf("%t", observedTx.Success), + fmt.Sprintf("%d", observedTx.BlockHeight), + observedTx.TxHash, + observedTx.GasFeeUsed, + observedTx.ErrorMsg, + ), nil } // GetOutboundRevertId generates a deterministic outbound ID for an inbound-revert diff --git a/x/uexecutor/types/keys_canonical_test.go b/x/uexecutor/types/keys_canonical_test.go new file mode 100644 index 000000000..d48423404 --- /dev/null +++ b/x/uexecutor/types/keys_canonical_test.go @@ -0,0 +1,293 @@ +package types_test + +import ( + "crypto/sha256" + "encoding/hex" + "fmt" + "strings" + "testing" + + "cosmossdk.io/collections" + "github.com/stretchr/testify/require" + + "github.com/pushchain/push-chain-node/x/uexecutor/types" +) + +// recipeHashFields reproduces the production hashFields construction +// independently so the tests document (and pin) the exact algorithm: +// +// key = sha256( hex(sha256(domain.Bytes())) : hex(sha256(f0)) : ... ) +func recipeHashFields(domain collections.Prefix, parts ...string) string { + perField := make([]string, 0, len(parts)+1) + d := sha256.Sum256(domain.Bytes()) + perField = append(perField, hex.EncodeToString(d[:])) + for _, p := range parts { + s := sha256.Sum256([]byte(p)) + perField = append(perField, hex.EncodeToString(s[:])) + } + final := sha256.Sum256([]byte(strings.Join(perField, ":"))) + return hex.EncodeToString(final[:]) +} + +// Canonical voting digest suite: ballot identity must converge for encoding +// variants of the same event, diverge on any consensus-critical difference, +// and ignore the derived universal_payload. + +func canonInbound() types.Inbound { + return types.Inbound{ + SourceChain: "eip155:11155111", + TxHash: "0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd", + Sender: "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed", + Recipient: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238", + Amount: "1000000", + AssetAddr: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + LogIndex: "1", + TxType: types.TxType_FUNDS, + RevertInstructions: &types.RevertInstructions{ + FundRecipient: "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed", + }, + } +} + +// TestInboundBallotKey_GoldenValueAndRecipe shows exactly how an inbound +// ballot key is built and pins the resulting value. The fields below are +// already in canonical form, so canonicalization is a no-op and the recipe is +// transparent: hash each field, join the hex digests with ':', hash again. +func TestInboundBallotKey_GoldenValueAndRecipe(t *testing.T) { + in := types.Inbound{ + SourceChain: "eip155:11155111", + TxHash: "0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd", + Sender: "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed", + Recipient: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238", + Amount: "1000000", + AssetAddr: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + LogIndex: "1", + TxType: types.TxType_FUNDS, + RevertInstructions: &types.RevertInstructions{ + FundRecipient: "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed", + }, + } + + got, err := types.GetInboundBallotKey(in) + require.NoError(t, err) + t.Logf("inbound ballot key = %s", got) + + // 1. The exact pinned value (catches any accidental construction change). + require.Equal(t, + "1e7755fdc3d07f21b770f85a9de1cb62b740a8a4d7a38bae0a4a36fd809e2d30", + got, "inbound ballot key golden value changed — confirm the change is intentional") + + // 2. The same value, reproduced field-by-field via the documented recipe. + expected := recipeHashFields( + types.InboundBallotDomain, + in.SourceChain, + in.TxHash, + in.LogIndex, + in.Sender, + in.Recipient, + in.Amount, + in.AssetAddr, + fmt.Sprintf("%d", in.TxType), + in.VerificationData, // "" + in.RevertInstructions.FundRecipient, + fmt.Sprintf("%t", in.IsCEA), // false + in.RawPayload, // "" + ) + require.Equal(t, expected, got, "production key must equal the documented recipe") + require.Len(t, got, 64, "key is a hex-encoded sha256 digest") +} + +// TestOutboundBallotKey_GoldenValueAndRecipe is the outbound twin. +func TestOutboundBallotKey_GoldenValueAndRecipe(t *testing.T) { + obs := types.OutboundObservation{ + Success: true, + BlockHeight: 100, + TxHash: "0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd", + GasFeeUsed: "21000", + } + + got, err := types.GetOutboundBallotKey("utx-1", "ob-1", obs) + require.NoError(t, err) + t.Logf("outbound ballot key = %s", got) + + require.Equal(t, + "ac7ba6932ceec3e434947a96eabf1deb7a7d628d09691190244d5ed63ccb155a", + got, "outbound ballot key golden value changed — confirm the change is intentional") + + expected := recipeHashFields( + types.OutboundBallotDomain, + "utx-1", + "ob-1", + fmt.Sprintf("%t", obs.Success), + fmt.Sprintf("%d", obs.BlockHeight), + obs.TxHash, + obs.GasFeeUsed, + obs.ErrorMsg, // "" + ) + require.Equal(t, expected, got, "production key must equal the documented recipe") + require.Len(t, got, 64) +} + +func TestInboundBallotKey_EncodingVariantsConverge(t *testing.T) { + base := canonInbound() + base.Canonicalize() + baseKey, err := types.GetInboundBallotKey(base) + require.NoError(t, err) + + // Same logical event with every string field in a different encoding. + variant := canonInbound() + variant.TxHash = "0XB28F49668E7E76DC96D7AABE5B7F63FECFBD1C3574774C05E8204E749FD96FBD" + variant.Sender = "0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed" + variant.Recipient = "0X1C7D4B196CB0C7B01D743FBC6116A902379C7238" + variant.AssetAddr = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" + variant.RevertInstructions.FundRecipient = "0x5AAEB6053F3E94C9B9A09F33669435E7EF1BEAED" + variant.Canonicalize() + + variantKey, err := types.GetInboundBallotKey(variant) + require.NoError(t, err) + require.Equal(t, baseKey, variantKey, + "encoding variants of the same event must produce one ballot key") + + // And the UTX key converges as well (sibling site). + require.Equal(t, types.GetInboundUniversalTxKey(base), types.GetInboundUniversalTxKey(variant)) +} + +func TestInboundBallotKey_UniversalPayloadExcluded(t *testing.T) { + a := canonInbound() + a.Canonicalize() + keyNil, err := types.GetInboundBallotKey(a) + require.NoError(t, err) + + b := canonInbound() + b.UniversalPayload = &types.UniversalPayload{To: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238"} + b.Canonicalize() + keyPopulated, err := types.GetInboundBallotKey(b) + require.NoError(t, err) + + require.Equal(t, keyNil, keyPopulated, + "universal_payload is derived/ignored on-chain and must not affect ballot identity") +} + +func TestInboundBallotKey_NilAndEmptyRevertInstructionsConverge(t *testing.T) { + a := canonInbound() + a.RevertInstructions = nil + a.Canonicalize() + keyNil, _ := types.GetInboundBallotKey(a) + + b := canonInbound() + b.RevertInstructions = &types.RevertInstructions{FundRecipient: ""} + b.Canonicalize() + keyEmpty, _ := types.GetInboundBallotKey(b) + + require.Equal(t, keyNil, keyEmpty, + "nil revert_instructions and empty fund_recipient are semantically identical") +} + +func TestInboundBallotKey_ConsensusFieldsDiverge(t *testing.T) { + base := canonInbound() + base.Canonicalize() + baseKey, _ := types.GetInboundBallotKey(base) + + mutate := []func(*types.Inbound){ + func(i *types.Inbound) { i.Amount = "2000000" }, + func(i *types.Inbound) { i.Recipient = "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed" }, + func(i *types.Inbound) { i.AssetAddr = "0x387b9C8Db60E74999aAAC5A2b7825b400F12d68E" }, + func(i *types.Inbound) { i.LogIndex = "2" }, + func(i *types.Inbound) { i.TxType = types.TxType_GAS }, + func(i *types.Inbound) { i.IsCEA = true }, + func(i *types.Inbound) { i.RawPayload = "0xdeadbeef" }, + func(i *types.Inbound) { i.RevertInstructions.FundRecipient = "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238" }, + } + for n, m := range mutate { + v := canonInbound() + m(&v) + v.Canonicalize() + key, err := types.GetInboundBallotKey(v) + require.NoError(t, err) + require.NotEqual(t, baseKey, key, "mutation %d must change the ballot identity", n) + } +} + +func TestOutboundBallotKey_EncodingVariantsConverge(t *testing.T) { + // Hash canonicalization happens at vote ingress (per destination chain); + // digest over the canonical observation must converge. + obsA := types.OutboundObservation{Success: true, BlockHeight: 100, + TxHash: "0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd", GasFeeUsed: "21000"} + obsB := obsA + + keyA, err := types.GetOutboundBallotKey("utx-1", "ob-1", obsA) + require.NoError(t, err) + keyB, err := types.GetOutboundBallotKey("utx-1", "ob-1", obsB) + require.NoError(t, err) + require.Equal(t, keyA, keyB) +} + +func TestOutboundBallotKey_AllFieldsAreConsensusCritical(t *testing.T) { + base := types.OutboundObservation{Success: true, BlockHeight: 100, + TxHash: "0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd", GasFeeUsed: "21000"} + baseKey, _ := types.GetOutboundBallotKey("utx-1", "ob-1", base) + + mutations := []types.OutboundObservation{ + {Success: false, BlockHeight: 100, TxHash: base.TxHash, GasFeeUsed: "21000"}, + {Success: true, BlockHeight: 101, TxHash: base.TxHash, GasFeeUsed: "21000"}, + {Success: true, BlockHeight: 100, TxHash: "0x" + "11" + base.TxHash[4:], GasFeeUsed: "21000"}, + {Success: true, BlockHeight: 100, TxHash: base.TxHash, GasFeeUsed: "42000"}, + {Success: true, BlockHeight: 100, TxHash: base.TxHash, GasFeeUsed: "21000", ErrorMsg: "boom"}, + } + for n, obs := range mutations { + key, err := types.GetOutboundBallotKey("utx-1", "ob-1", obs) + require.NoError(t, err) + require.NotEqual(t, baseKey, key, "mutation %d must change the ballot identity", n) + } + + // Scoping fields too. + keyOtherUtx, _ := types.GetOutboundBallotKey("utx-2", "ob-1", base) + require.NotEqual(t, baseKey, keyOtherUtx) + keyOtherOb, _ := types.GetOutboundBallotKey("utx-1", "ob-2", base) + require.NotEqual(t, baseKey, keyOtherOb) +} + +func TestBallotKey_DomainSeparation(t *testing.T) { + // Inbound and outbound digests share the framing; the version-domain + // prefix must keep their key spaces disjoint. + in := canonInbound() + in.Canonicalize() + inKey, _ := types.GetInboundBallotKey(in) + outKey, _ := types.GetOutboundBallotKey("utx-1", "ob-1", types.OutboundObservation{Success: true, BlockHeight: 1, TxHash: in.TxHash, GasFeeUsed: "1"}) + require.NotEqual(t, inKey, outKey) + require.Len(t, inKey, 64, "sha256 hex digest") + require.Len(t, outKey, 64, "sha256 hex digest") +} + +func TestInboundCanonicalize_SolanaFieldsPreserved(t *testing.T) { + in := types.Inbound{ + SourceChain: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", + TxHash: "0xAB12CD34" + "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899aabbccdd", // 0x-hex form (client converts sigs) + Sender: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // base58 — case-significant + Recipient: "0x1c7d4b196cb0c7b01d743fbc6116a902379c7238", + AssetAddr: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", + LogIndex: "0", + Amount: "5", + TxType: types.TxType_FUNDS, + } + in.Canonicalize() + + require.Equal(t, "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", in.Sender, + "base58 sender must not be case-mangled") + require.Equal(t, "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", in.AssetAddr, + "base58 asset must not be case-mangled") + require.Equal(t, "0x", in.TxHash[:2]) + require.Equal(t, in.TxHash, "0x"+lowercase(in.TxHash[2:]), "hex tx hash lowercased") + require.Equal(t, "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238", in.Recipient, + "push-side recipient canonicalized to EIP-55") +} + +func lowercase(s string) string { + out := []rune(s) + for i, r := range out { + if r >= 'A' && r <= 'F' { + out[i] = r + 32 + } + } + return string(out) +} From ff7ed18ec173f34a1d5f8a0317cc2468b7acb939 Mon Sep 17 00:00:00 2001 From: Nilesh Gupta Date: Thu, 4 Jun 2026 20:16:13 +0530 Subject: [PATCH 5/5] feat(uexecutor): InboundKeys and OutboundBallotKey queries Let off-chain validators read the canonical UTX id + ballot ids from the chain rather than re-implementing the canonicalization/digest rules. InboundKeys(inbound) returns utx_id, ballot_id and the canonical inbound; OutboundBallotKey(utx_id, outbound_id, observed_tx) looks up the outbound's destination chain to canonicalize the observed hash, then returns the ballot id and canonical observation. Includes generated proto. --- api/uexecutor/v1/query.pulsar.go | 2692 ++++++++++++++++- api/uexecutor/v1/query_grpc.pb.go | 86 + proto/uexecutor/v1/query.proto | 39 + test/integration/uexecutor/query_keys_test.go | 135 + x/uexecutor/keeper/query_keys.go | 88 + x/uexecutor/types/query.pb.go | 1325 +++++++- x/uexecutor/types/query.pb.gw.go | 162 + 7 files changed, 4232 insertions(+), 295 deletions(-) create mode 100644 test/integration/uexecutor/query_keys_test.go create mode 100644 x/uexecutor/keeper/query_keys.go diff --git a/api/uexecutor/v1/query.pulsar.go b/api/uexecutor/v1/query.pulsar.go index f47b0f70a..66eb0136f 100644 --- a/api/uexecutor/v1/query.pulsar.go +++ b/api/uexecutor/v1/query.pulsar.go @@ -11209,6 +11209,2066 @@ func (x *fastReflection_QueryAllPendingOutboundsResponse) ProtoMethods() *protoi } } +var ( + md_QueryInboundKeysRequest protoreflect.MessageDescriptor + fd_QueryInboundKeysRequest_inbound protoreflect.FieldDescriptor +) + +func init() { + file_uexecutor_v1_query_proto_init() + md_QueryInboundKeysRequest = File_uexecutor_v1_query_proto.Messages().ByName("QueryInboundKeysRequest") + fd_QueryInboundKeysRequest_inbound = md_QueryInboundKeysRequest.Fields().ByName("inbound") +} + +var _ protoreflect.Message = (*fastReflection_QueryInboundKeysRequest)(nil) + +type fastReflection_QueryInboundKeysRequest QueryInboundKeysRequest + +func (x *QueryInboundKeysRequest) ProtoReflect() protoreflect.Message { + return (*fastReflection_QueryInboundKeysRequest)(x) +} + +func (x *QueryInboundKeysRequest) slowProtoReflect() protoreflect.Message { + mi := &file_uexecutor_v1_query_proto_msgTypes[23] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_QueryInboundKeysRequest_messageType fastReflection_QueryInboundKeysRequest_messageType +var _ protoreflect.MessageType = fastReflection_QueryInboundKeysRequest_messageType{} + +type fastReflection_QueryInboundKeysRequest_messageType struct{} + +func (x fastReflection_QueryInboundKeysRequest_messageType) Zero() protoreflect.Message { + return (*fastReflection_QueryInboundKeysRequest)(nil) +} +func (x fastReflection_QueryInboundKeysRequest_messageType) New() protoreflect.Message { + return new(fastReflection_QueryInboundKeysRequest) +} +func (x fastReflection_QueryInboundKeysRequest_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_QueryInboundKeysRequest +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_QueryInboundKeysRequest) Descriptor() protoreflect.MessageDescriptor { + return md_QueryInboundKeysRequest +} + +// Type returns the message type, which encapsulates both Go and protobuf +// type information. If the Go type information is not needed, +// it is recommended that the message descriptor be used instead. +func (x *fastReflection_QueryInboundKeysRequest) Type() protoreflect.MessageType { + return _fastReflection_QueryInboundKeysRequest_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_QueryInboundKeysRequest) New() protoreflect.Message { + return new(fastReflection_QueryInboundKeysRequest) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_QueryInboundKeysRequest) Interface() protoreflect.ProtoMessage { + return (*QueryInboundKeysRequest)(x) +} + +// Range iterates over every populated field in an undefined order, +// calling f for each field descriptor and value encountered. +// Range returns immediately if f returns false. +// While iterating, mutating operations may only be performed +// on the current field descriptor. +func (x *fastReflection_QueryInboundKeysRequest) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.Inbound != nil { + value := protoreflect.ValueOfMessage(x.Inbound.ProtoReflect()) + if !f(fd_QueryInboundKeysRequest_inbound, value) { + return + } + } +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_QueryInboundKeysRequest) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "uexecutor.v1.QueryInboundKeysRequest.inbound": + return x.Inbound != nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryInboundKeysRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryInboundKeysRequest does not contain field %s", fd.FullName())) + } +} + +// Clear clears the field such that a subsequent Has call reports false. +// +// Clearing an extension field clears both the extension type and value +// associated with the given field number. +// +// Clear is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryInboundKeysRequest) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "uexecutor.v1.QueryInboundKeysRequest.inbound": + x.Inbound = nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryInboundKeysRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryInboundKeysRequest does not contain field %s", fd.FullName())) + } +} + +// Get retrieves the value for a field. +// +// For unpopulated scalars, it returns the default value, where +// the default value of a bytes scalar is guaranteed to be a copy. +// For unpopulated composite types, it returns an empty, read-only view +// of the value; to obtain a mutable reference, use Mutable. +func (x *fastReflection_QueryInboundKeysRequest) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "uexecutor.v1.QueryInboundKeysRequest.inbound": + value := x.Inbound + return protoreflect.ValueOfMessage(value.ProtoReflect()) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryInboundKeysRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryInboundKeysRequest does not contain field %s", descriptor.FullName())) + } +} + +// Set stores the value for a field. +// +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType. +// When setting a composite type, it is unspecified whether the stored value +// aliases the source's memory in any way. If the composite value is an +// empty, read-only value, then it panics. +// +// Set is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryInboundKeysRequest) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "uexecutor.v1.QueryInboundKeysRequest.inbound": + x.Inbound = value.Message().Interface().(*Inbound) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryInboundKeysRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryInboundKeysRequest does not contain field %s", fd.FullName())) + } +} + +// Mutable returns a mutable reference to a composite type. +// +// If the field is unpopulated, it may allocate a composite value. +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType +// if not already stored. +// It panics if the field does not contain a composite type. +// +// Mutable is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryInboundKeysRequest) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.QueryInboundKeysRequest.inbound": + if x.Inbound == nil { + x.Inbound = new(Inbound) + } + return protoreflect.ValueOfMessage(x.Inbound.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryInboundKeysRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryInboundKeysRequest does not contain field %s", fd.FullName())) + } +} + +// NewField returns a new value that is assignable to the field +// for the given descriptor. For scalars, this returns the default value. +// For lists, maps, and messages, this returns a new, empty, mutable value. +func (x *fastReflection_QueryInboundKeysRequest) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.QueryInboundKeysRequest.inbound": + m := new(Inbound) + return protoreflect.ValueOfMessage(m.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryInboundKeysRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryInboundKeysRequest does not contain field %s", fd.FullName())) + } +} + +// WhichOneof reports which field within the oneof is populated, +// returning nil if none are populated. +// It panics if the oneof descriptor does not belong to this message. +func (x *fastReflection_QueryInboundKeysRequest) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in uexecutor.v1.QueryInboundKeysRequest", d.FullName())) + } + panic("unreachable") +} + +// GetUnknown retrieves the entire list of unknown fields. +// The caller may only mutate the contents of the RawFields +// if the mutated bytes are stored back into the message with SetUnknown. +func (x *fastReflection_QueryInboundKeysRequest) GetUnknown() protoreflect.RawFields { + return x.unknownFields +} + +// SetUnknown stores an entire list of unknown fields. +// The raw fields must be syntactically valid according to the wire format. +// An implementation may panic if this is not the case. +// Once stored, the caller must not mutate the content of the RawFields. +// An empty RawFields may be passed to clear the fields. +// +// SetUnknown is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryInboundKeysRequest) SetUnknown(fields protoreflect.RawFields) { + x.unknownFields = fields +} + +// IsValid reports whether the message is valid. +// +// An invalid message is an empty, read-only value. +// +// An invalid message often corresponds to a nil pointer of the concrete +// message type, but the details are implementation dependent. +// Validity is not part of the protobuf data model, and may not +// be preserved in marshaling or other operations. +func (x *fastReflection_QueryInboundKeysRequest) IsValid() bool { + return x != nil +} + +// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. +// This method may return nil. +// +// The returned methods type is identical to +// "google.golang.org/protobuf/runtime/protoiface".Methods. +// Consult the protoiface package documentation for details. +func (x *fastReflection_QueryInboundKeysRequest) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*QueryInboundKeysRequest) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + if x.Inbound != nil { + l = options.Size(x.Inbound) + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*QueryInboundKeysRequest) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if x.Inbound != nil { + encoded, err := options.Marshal(x.Inbound) + if err != nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, err + } + i -= len(encoded) + copy(dAtA[i:], encoded) + i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) + i-- + dAtA[i] = 0xa + } + if input.Buf != nil { + input.Buf = append(input.Buf, dAtA...) + } else { + input.Buf = dAtA + } + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { + x := input.Message.Interface().(*QueryInboundKeysRequest) + if x == nil { + return protoiface.UnmarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Flags: input.Flags, + }, nil + } + options := runtime.UnmarshalInputToOptions(input) + _ = options + dAtA := input.Buf + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, 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 protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryInboundKeysRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryInboundKeysRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Inbound", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if x.Inbound == nil { + x.Inbound = &Inbound{} + } + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.Inbound); err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + +var ( + md_QueryInboundKeysResponse protoreflect.MessageDescriptor + fd_QueryInboundKeysResponse_utx_id protoreflect.FieldDescriptor + fd_QueryInboundKeysResponse_ballot_id protoreflect.FieldDescriptor + fd_QueryInboundKeysResponse_canonical_inbound protoreflect.FieldDescriptor +) + +func init() { + file_uexecutor_v1_query_proto_init() + md_QueryInboundKeysResponse = File_uexecutor_v1_query_proto.Messages().ByName("QueryInboundKeysResponse") + fd_QueryInboundKeysResponse_utx_id = md_QueryInboundKeysResponse.Fields().ByName("utx_id") + fd_QueryInboundKeysResponse_ballot_id = md_QueryInboundKeysResponse.Fields().ByName("ballot_id") + fd_QueryInboundKeysResponse_canonical_inbound = md_QueryInboundKeysResponse.Fields().ByName("canonical_inbound") +} + +var _ protoreflect.Message = (*fastReflection_QueryInboundKeysResponse)(nil) + +type fastReflection_QueryInboundKeysResponse QueryInboundKeysResponse + +func (x *QueryInboundKeysResponse) ProtoReflect() protoreflect.Message { + return (*fastReflection_QueryInboundKeysResponse)(x) +} + +func (x *QueryInboundKeysResponse) slowProtoReflect() protoreflect.Message { + mi := &file_uexecutor_v1_query_proto_msgTypes[24] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_QueryInboundKeysResponse_messageType fastReflection_QueryInboundKeysResponse_messageType +var _ protoreflect.MessageType = fastReflection_QueryInboundKeysResponse_messageType{} + +type fastReflection_QueryInboundKeysResponse_messageType struct{} + +func (x fastReflection_QueryInboundKeysResponse_messageType) Zero() protoreflect.Message { + return (*fastReflection_QueryInboundKeysResponse)(nil) +} +func (x fastReflection_QueryInboundKeysResponse_messageType) New() protoreflect.Message { + return new(fastReflection_QueryInboundKeysResponse) +} +func (x fastReflection_QueryInboundKeysResponse_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_QueryInboundKeysResponse +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_QueryInboundKeysResponse) Descriptor() protoreflect.MessageDescriptor { + return md_QueryInboundKeysResponse +} + +// Type returns the message type, which encapsulates both Go and protobuf +// type information. If the Go type information is not needed, +// it is recommended that the message descriptor be used instead. +func (x *fastReflection_QueryInboundKeysResponse) Type() protoreflect.MessageType { + return _fastReflection_QueryInboundKeysResponse_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_QueryInboundKeysResponse) New() protoreflect.Message { + return new(fastReflection_QueryInboundKeysResponse) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_QueryInboundKeysResponse) Interface() protoreflect.ProtoMessage { + return (*QueryInboundKeysResponse)(x) +} + +// Range iterates over every populated field in an undefined order, +// calling f for each field descriptor and value encountered. +// Range returns immediately if f returns false. +// While iterating, mutating operations may only be performed +// on the current field descriptor. +func (x *fastReflection_QueryInboundKeysResponse) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.UtxId != "" { + value := protoreflect.ValueOfString(x.UtxId) + if !f(fd_QueryInboundKeysResponse_utx_id, value) { + return + } + } + if x.BallotId != "" { + value := protoreflect.ValueOfString(x.BallotId) + if !f(fd_QueryInboundKeysResponse_ballot_id, value) { + return + } + } + if x.CanonicalInbound != nil { + value := protoreflect.ValueOfMessage(x.CanonicalInbound.ProtoReflect()) + if !f(fd_QueryInboundKeysResponse_canonical_inbound, value) { + return + } + } +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_QueryInboundKeysResponse) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "uexecutor.v1.QueryInboundKeysResponse.utx_id": + return x.UtxId != "" + case "uexecutor.v1.QueryInboundKeysResponse.ballot_id": + return x.BallotId != "" + case "uexecutor.v1.QueryInboundKeysResponse.canonical_inbound": + return x.CanonicalInbound != nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryInboundKeysResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryInboundKeysResponse does not contain field %s", fd.FullName())) + } +} + +// Clear clears the field such that a subsequent Has call reports false. +// +// Clearing an extension field clears both the extension type and value +// associated with the given field number. +// +// Clear is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryInboundKeysResponse) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "uexecutor.v1.QueryInboundKeysResponse.utx_id": + x.UtxId = "" + case "uexecutor.v1.QueryInboundKeysResponse.ballot_id": + x.BallotId = "" + case "uexecutor.v1.QueryInboundKeysResponse.canonical_inbound": + x.CanonicalInbound = nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryInboundKeysResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryInboundKeysResponse does not contain field %s", fd.FullName())) + } +} + +// Get retrieves the value for a field. +// +// For unpopulated scalars, it returns the default value, where +// the default value of a bytes scalar is guaranteed to be a copy. +// For unpopulated composite types, it returns an empty, read-only view +// of the value; to obtain a mutable reference, use Mutable. +func (x *fastReflection_QueryInboundKeysResponse) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "uexecutor.v1.QueryInboundKeysResponse.utx_id": + value := x.UtxId + return protoreflect.ValueOfString(value) + case "uexecutor.v1.QueryInboundKeysResponse.ballot_id": + value := x.BallotId + return protoreflect.ValueOfString(value) + case "uexecutor.v1.QueryInboundKeysResponse.canonical_inbound": + value := x.CanonicalInbound + return protoreflect.ValueOfMessage(value.ProtoReflect()) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryInboundKeysResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryInboundKeysResponse does not contain field %s", descriptor.FullName())) + } +} + +// Set stores the value for a field. +// +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType. +// When setting a composite type, it is unspecified whether the stored value +// aliases the source's memory in any way. If the composite value is an +// empty, read-only value, then it panics. +// +// Set is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryInboundKeysResponse) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "uexecutor.v1.QueryInboundKeysResponse.utx_id": + x.UtxId = value.Interface().(string) + case "uexecutor.v1.QueryInboundKeysResponse.ballot_id": + x.BallotId = value.Interface().(string) + case "uexecutor.v1.QueryInboundKeysResponse.canonical_inbound": + x.CanonicalInbound = value.Message().Interface().(*Inbound) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryInboundKeysResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryInboundKeysResponse does not contain field %s", fd.FullName())) + } +} + +// Mutable returns a mutable reference to a composite type. +// +// If the field is unpopulated, it may allocate a composite value. +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType +// if not already stored. +// It panics if the field does not contain a composite type. +// +// Mutable is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryInboundKeysResponse) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.QueryInboundKeysResponse.canonical_inbound": + if x.CanonicalInbound == nil { + x.CanonicalInbound = new(Inbound) + } + return protoreflect.ValueOfMessage(x.CanonicalInbound.ProtoReflect()) + case "uexecutor.v1.QueryInboundKeysResponse.utx_id": + panic(fmt.Errorf("field utx_id of message uexecutor.v1.QueryInboundKeysResponse is not mutable")) + case "uexecutor.v1.QueryInboundKeysResponse.ballot_id": + panic(fmt.Errorf("field ballot_id of message uexecutor.v1.QueryInboundKeysResponse is not mutable")) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryInboundKeysResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryInboundKeysResponse does not contain field %s", fd.FullName())) + } +} + +// NewField returns a new value that is assignable to the field +// for the given descriptor. For scalars, this returns the default value. +// For lists, maps, and messages, this returns a new, empty, mutable value. +func (x *fastReflection_QueryInboundKeysResponse) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.QueryInboundKeysResponse.utx_id": + return protoreflect.ValueOfString("") + case "uexecutor.v1.QueryInboundKeysResponse.ballot_id": + return protoreflect.ValueOfString("") + case "uexecutor.v1.QueryInboundKeysResponse.canonical_inbound": + m := new(Inbound) + return protoreflect.ValueOfMessage(m.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryInboundKeysResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryInboundKeysResponse does not contain field %s", fd.FullName())) + } +} + +// WhichOneof reports which field within the oneof is populated, +// returning nil if none are populated. +// It panics if the oneof descriptor does not belong to this message. +func (x *fastReflection_QueryInboundKeysResponse) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in uexecutor.v1.QueryInboundKeysResponse", d.FullName())) + } + panic("unreachable") +} + +// GetUnknown retrieves the entire list of unknown fields. +// The caller may only mutate the contents of the RawFields +// if the mutated bytes are stored back into the message with SetUnknown. +func (x *fastReflection_QueryInboundKeysResponse) GetUnknown() protoreflect.RawFields { + return x.unknownFields +} + +// SetUnknown stores an entire list of unknown fields. +// The raw fields must be syntactically valid according to the wire format. +// An implementation may panic if this is not the case. +// Once stored, the caller must not mutate the content of the RawFields. +// An empty RawFields may be passed to clear the fields. +// +// SetUnknown is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryInboundKeysResponse) SetUnknown(fields protoreflect.RawFields) { + x.unknownFields = fields +} + +// IsValid reports whether the message is valid. +// +// An invalid message is an empty, read-only value. +// +// An invalid message often corresponds to a nil pointer of the concrete +// message type, but the details are implementation dependent. +// Validity is not part of the protobuf data model, and may not +// be preserved in marshaling or other operations. +func (x *fastReflection_QueryInboundKeysResponse) IsValid() bool { + return x != nil +} + +// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. +// This method may return nil. +// +// The returned methods type is identical to +// "google.golang.org/protobuf/runtime/protoiface".Methods. +// Consult the protoiface package documentation for details. +func (x *fastReflection_QueryInboundKeysResponse) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*QueryInboundKeysResponse) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + l = len(x.UtxId) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + l = len(x.BallotId) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.CanonicalInbound != nil { + l = options.Size(x.CanonicalInbound) + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*QueryInboundKeysResponse) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if x.CanonicalInbound != nil { + encoded, err := options.Marshal(x.CanonicalInbound) + if err != nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, err + } + i -= len(encoded) + copy(dAtA[i:], encoded) + i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) + i-- + dAtA[i] = 0x1a + } + if len(x.BallotId) > 0 { + i -= len(x.BallotId) + copy(dAtA[i:], x.BallotId) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.BallotId))) + i-- + dAtA[i] = 0x12 + } + if len(x.UtxId) > 0 { + i -= len(x.UtxId) + copy(dAtA[i:], x.UtxId) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.UtxId))) + i-- + dAtA[i] = 0xa + } + if input.Buf != nil { + input.Buf = append(input.Buf, dAtA...) + } else { + input.Buf = dAtA + } + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { + x := input.Message.Interface().(*QueryInboundKeysResponse) + if x == nil { + return protoiface.UnmarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Flags: input.Flags, + }, nil + } + options := runtime.UnmarshalInputToOptions(input) + _ = options + dAtA := input.Buf + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, 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 protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryInboundKeysResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryInboundKeysResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field UtxId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.UtxId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field BallotId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.BallotId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field CanonicalInbound", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if x.CanonicalInbound == nil { + x.CanonicalInbound = &Inbound{} + } + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.CanonicalInbound); err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + +var ( + md_QueryOutboundBallotKeyRequest protoreflect.MessageDescriptor + fd_QueryOutboundBallotKeyRequest_utx_id protoreflect.FieldDescriptor + fd_QueryOutboundBallotKeyRequest_outbound_id protoreflect.FieldDescriptor + fd_QueryOutboundBallotKeyRequest_observed_tx protoreflect.FieldDescriptor +) + +func init() { + file_uexecutor_v1_query_proto_init() + md_QueryOutboundBallotKeyRequest = File_uexecutor_v1_query_proto.Messages().ByName("QueryOutboundBallotKeyRequest") + fd_QueryOutboundBallotKeyRequest_utx_id = md_QueryOutboundBallotKeyRequest.Fields().ByName("utx_id") + fd_QueryOutboundBallotKeyRequest_outbound_id = md_QueryOutboundBallotKeyRequest.Fields().ByName("outbound_id") + fd_QueryOutboundBallotKeyRequest_observed_tx = md_QueryOutboundBallotKeyRequest.Fields().ByName("observed_tx") +} + +var _ protoreflect.Message = (*fastReflection_QueryOutboundBallotKeyRequest)(nil) + +type fastReflection_QueryOutboundBallotKeyRequest QueryOutboundBallotKeyRequest + +func (x *QueryOutboundBallotKeyRequest) ProtoReflect() protoreflect.Message { + return (*fastReflection_QueryOutboundBallotKeyRequest)(x) +} + +func (x *QueryOutboundBallotKeyRequest) slowProtoReflect() protoreflect.Message { + mi := &file_uexecutor_v1_query_proto_msgTypes[25] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_QueryOutboundBallotKeyRequest_messageType fastReflection_QueryOutboundBallotKeyRequest_messageType +var _ protoreflect.MessageType = fastReflection_QueryOutboundBallotKeyRequest_messageType{} + +type fastReflection_QueryOutboundBallotKeyRequest_messageType struct{} + +func (x fastReflection_QueryOutboundBallotKeyRequest_messageType) Zero() protoreflect.Message { + return (*fastReflection_QueryOutboundBallotKeyRequest)(nil) +} +func (x fastReflection_QueryOutboundBallotKeyRequest_messageType) New() protoreflect.Message { + return new(fastReflection_QueryOutboundBallotKeyRequest) +} +func (x fastReflection_QueryOutboundBallotKeyRequest_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_QueryOutboundBallotKeyRequest +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_QueryOutboundBallotKeyRequest) Descriptor() protoreflect.MessageDescriptor { + return md_QueryOutboundBallotKeyRequest +} + +// Type returns the message type, which encapsulates both Go and protobuf +// type information. If the Go type information is not needed, +// it is recommended that the message descriptor be used instead. +func (x *fastReflection_QueryOutboundBallotKeyRequest) Type() protoreflect.MessageType { + return _fastReflection_QueryOutboundBallotKeyRequest_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_QueryOutboundBallotKeyRequest) New() protoreflect.Message { + return new(fastReflection_QueryOutboundBallotKeyRequest) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_QueryOutboundBallotKeyRequest) Interface() protoreflect.ProtoMessage { + return (*QueryOutboundBallotKeyRequest)(x) +} + +// Range iterates over every populated field in an undefined order, +// calling f for each field descriptor and value encountered. +// Range returns immediately if f returns false. +// While iterating, mutating operations may only be performed +// on the current field descriptor. +func (x *fastReflection_QueryOutboundBallotKeyRequest) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.UtxId != "" { + value := protoreflect.ValueOfString(x.UtxId) + if !f(fd_QueryOutboundBallotKeyRequest_utx_id, value) { + return + } + } + if x.OutboundId != "" { + value := protoreflect.ValueOfString(x.OutboundId) + if !f(fd_QueryOutboundBallotKeyRequest_outbound_id, value) { + return + } + } + if x.ObservedTx != nil { + value := protoreflect.ValueOfMessage(x.ObservedTx.ProtoReflect()) + if !f(fd_QueryOutboundBallotKeyRequest_observed_tx, value) { + return + } + } +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_QueryOutboundBallotKeyRequest) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "uexecutor.v1.QueryOutboundBallotKeyRequest.utx_id": + return x.UtxId != "" + case "uexecutor.v1.QueryOutboundBallotKeyRequest.outbound_id": + return x.OutboundId != "" + case "uexecutor.v1.QueryOutboundBallotKeyRequest.observed_tx": + return x.ObservedTx != nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryOutboundBallotKeyRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryOutboundBallotKeyRequest does not contain field %s", fd.FullName())) + } +} + +// Clear clears the field such that a subsequent Has call reports false. +// +// Clearing an extension field clears both the extension type and value +// associated with the given field number. +// +// Clear is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryOutboundBallotKeyRequest) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "uexecutor.v1.QueryOutboundBallotKeyRequest.utx_id": + x.UtxId = "" + case "uexecutor.v1.QueryOutboundBallotKeyRequest.outbound_id": + x.OutboundId = "" + case "uexecutor.v1.QueryOutboundBallotKeyRequest.observed_tx": + x.ObservedTx = nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryOutboundBallotKeyRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryOutboundBallotKeyRequest does not contain field %s", fd.FullName())) + } +} + +// Get retrieves the value for a field. +// +// For unpopulated scalars, it returns the default value, where +// the default value of a bytes scalar is guaranteed to be a copy. +// For unpopulated composite types, it returns an empty, read-only view +// of the value; to obtain a mutable reference, use Mutable. +func (x *fastReflection_QueryOutboundBallotKeyRequest) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "uexecutor.v1.QueryOutboundBallotKeyRequest.utx_id": + value := x.UtxId + return protoreflect.ValueOfString(value) + case "uexecutor.v1.QueryOutboundBallotKeyRequest.outbound_id": + value := x.OutboundId + return protoreflect.ValueOfString(value) + case "uexecutor.v1.QueryOutboundBallotKeyRequest.observed_tx": + value := x.ObservedTx + return protoreflect.ValueOfMessage(value.ProtoReflect()) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryOutboundBallotKeyRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryOutboundBallotKeyRequest does not contain field %s", descriptor.FullName())) + } +} + +// Set stores the value for a field. +// +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType. +// When setting a composite type, it is unspecified whether the stored value +// aliases the source's memory in any way. If the composite value is an +// empty, read-only value, then it panics. +// +// Set is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryOutboundBallotKeyRequest) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "uexecutor.v1.QueryOutboundBallotKeyRequest.utx_id": + x.UtxId = value.Interface().(string) + case "uexecutor.v1.QueryOutboundBallotKeyRequest.outbound_id": + x.OutboundId = value.Interface().(string) + case "uexecutor.v1.QueryOutboundBallotKeyRequest.observed_tx": + x.ObservedTx = value.Message().Interface().(*OutboundObservation) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryOutboundBallotKeyRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryOutboundBallotKeyRequest does not contain field %s", fd.FullName())) + } +} + +// Mutable returns a mutable reference to a composite type. +// +// If the field is unpopulated, it may allocate a composite value. +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType +// if not already stored. +// It panics if the field does not contain a composite type. +// +// Mutable is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryOutboundBallotKeyRequest) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.QueryOutboundBallotKeyRequest.observed_tx": + if x.ObservedTx == nil { + x.ObservedTx = new(OutboundObservation) + } + return protoreflect.ValueOfMessage(x.ObservedTx.ProtoReflect()) + case "uexecutor.v1.QueryOutboundBallotKeyRequest.utx_id": + panic(fmt.Errorf("field utx_id of message uexecutor.v1.QueryOutboundBallotKeyRequest is not mutable")) + case "uexecutor.v1.QueryOutboundBallotKeyRequest.outbound_id": + panic(fmt.Errorf("field outbound_id of message uexecutor.v1.QueryOutboundBallotKeyRequest is not mutable")) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryOutboundBallotKeyRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryOutboundBallotKeyRequest does not contain field %s", fd.FullName())) + } +} + +// NewField returns a new value that is assignable to the field +// for the given descriptor. For scalars, this returns the default value. +// For lists, maps, and messages, this returns a new, empty, mutable value. +func (x *fastReflection_QueryOutboundBallotKeyRequest) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.QueryOutboundBallotKeyRequest.utx_id": + return protoreflect.ValueOfString("") + case "uexecutor.v1.QueryOutboundBallotKeyRequest.outbound_id": + return protoreflect.ValueOfString("") + case "uexecutor.v1.QueryOutboundBallotKeyRequest.observed_tx": + m := new(OutboundObservation) + return protoreflect.ValueOfMessage(m.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryOutboundBallotKeyRequest")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryOutboundBallotKeyRequest does not contain field %s", fd.FullName())) + } +} + +// WhichOneof reports which field within the oneof is populated, +// returning nil if none are populated. +// It panics if the oneof descriptor does not belong to this message. +func (x *fastReflection_QueryOutboundBallotKeyRequest) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in uexecutor.v1.QueryOutboundBallotKeyRequest", d.FullName())) + } + panic("unreachable") +} + +// GetUnknown retrieves the entire list of unknown fields. +// The caller may only mutate the contents of the RawFields +// if the mutated bytes are stored back into the message with SetUnknown. +func (x *fastReflection_QueryOutboundBallotKeyRequest) GetUnknown() protoreflect.RawFields { + return x.unknownFields +} + +// SetUnknown stores an entire list of unknown fields. +// The raw fields must be syntactically valid according to the wire format. +// An implementation may panic if this is not the case. +// Once stored, the caller must not mutate the content of the RawFields. +// An empty RawFields may be passed to clear the fields. +// +// SetUnknown is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryOutboundBallotKeyRequest) SetUnknown(fields protoreflect.RawFields) { + x.unknownFields = fields +} + +// IsValid reports whether the message is valid. +// +// An invalid message is an empty, read-only value. +// +// An invalid message often corresponds to a nil pointer of the concrete +// message type, but the details are implementation dependent. +// Validity is not part of the protobuf data model, and may not +// be preserved in marshaling or other operations. +func (x *fastReflection_QueryOutboundBallotKeyRequest) IsValid() bool { + return x != nil +} + +// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. +// This method may return nil. +// +// The returned methods type is identical to +// "google.golang.org/protobuf/runtime/protoiface".Methods. +// Consult the protoiface package documentation for details. +func (x *fastReflection_QueryOutboundBallotKeyRequest) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*QueryOutboundBallotKeyRequest) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + l = len(x.UtxId) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + l = len(x.OutboundId) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.ObservedTx != nil { + l = options.Size(x.ObservedTx) + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*QueryOutboundBallotKeyRequest) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if x.ObservedTx != nil { + encoded, err := options.Marshal(x.ObservedTx) + if err != nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, err + } + i -= len(encoded) + copy(dAtA[i:], encoded) + i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) + i-- + dAtA[i] = 0x1a + } + if len(x.OutboundId) > 0 { + i -= len(x.OutboundId) + copy(dAtA[i:], x.OutboundId) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.OutboundId))) + i-- + dAtA[i] = 0x12 + } + if len(x.UtxId) > 0 { + i -= len(x.UtxId) + copy(dAtA[i:], x.UtxId) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.UtxId))) + i-- + dAtA[i] = 0xa + } + if input.Buf != nil { + input.Buf = append(input.Buf, dAtA...) + } else { + input.Buf = dAtA + } + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { + x := input.Message.Interface().(*QueryOutboundBallotKeyRequest) + if x == nil { + return protoiface.UnmarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Flags: input.Flags, + }, nil + } + options := runtime.UnmarshalInputToOptions(input) + _ = options + dAtA := input.Buf + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, 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 protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryOutboundBallotKeyRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryOutboundBallotKeyRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field UtxId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.UtxId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field OutboundId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.OutboundId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ObservedTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if x.ObservedTx == nil { + x.ObservedTx = &OutboundObservation{} + } + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.ObservedTx); err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + +var ( + md_QueryOutboundBallotKeyResponse protoreflect.MessageDescriptor + fd_QueryOutboundBallotKeyResponse_ballot_id protoreflect.FieldDescriptor + fd_QueryOutboundBallotKeyResponse_canonical_observed_tx protoreflect.FieldDescriptor +) + +func init() { + file_uexecutor_v1_query_proto_init() + md_QueryOutboundBallotKeyResponse = File_uexecutor_v1_query_proto.Messages().ByName("QueryOutboundBallotKeyResponse") + fd_QueryOutboundBallotKeyResponse_ballot_id = md_QueryOutboundBallotKeyResponse.Fields().ByName("ballot_id") + fd_QueryOutboundBallotKeyResponse_canonical_observed_tx = md_QueryOutboundBallotKeyResponse.Fields().ByName("canonical_observed_tx") +} + +var _ protoreflect.Message = (*fastReflection_QueryOutboundBallotKeyResponse)(nil) + +type fastReflection_QueryOutboundBallotKeyResponse QueryOutboundBallotKeyResponse + +func (x *QueryOutboundBallotKeyResponse) ProtoReflect() protoreflect.Message { + return (*fastReflection_QueryOutboundBallotKeyResponse)(x) +} + +func (x *QueryOutboundBallotKeyResponse) slowProtoReflect() protoreflect.Message { + mi := &file_uexecutor_v1_query_proto_msgTypes[26] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_QueryOutboundBallotKeyResponse_messageType fastReflection_QueryOutboundBallotKeyResponse_messageType +var _ protoreflect.MessageType = fastReflection_QueryOutboundBallotKeyResponse_messageType{} + +type fastReflection_QueryOutboundBallotKeyResponse_messageType struct{} + +func (x fastReflection_QueryOutboundBallotKeyResponse_messageType) Zero() protoreflect.Message { + return (*fastReflection_QueryOutboundBallotKeyResponse)(nil) +} +func (x fastReflection_QueryOutboundBallotKeyResponse_messageType) New() protoreflect.Message { + return new(fastReflection_QueryOutboundBallotKeyResponse) +} +func (x fastReflection_QueryOutboundBallotKeyResponse_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_QueryOutboundBallotKeyResponse +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_QueryOutboundBallotKeyResponse) Descriptor() protoreflect.MessageDescriptor { + return md_QueryOutboundBallotKeyResponse +} + +// Type returns the message type, which encapsulates both Go and protobuf +// type information. If the Go type information is not needed, +// it is recommended that the message descriptor be used instead. +func (x *fastReflection_QueryOutboundBallotKeyResponse) Type() protoreflect.MessageType { + return _fastReflection_QueryOutboundBallotKeyResponse_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_QueryOutboundBallotKeyResponse) New() protoreflect.Message { + return new(fastReflection_QueryOutboundBallotKeyResponse) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_QueryOutboundBallotKeyResponse) Interface() protoreflect.ProtoMessage { + return (*QueryOutboundBallotKeyResponse)(x) +} + +// Range iterates over every populated field in an undefined order, +// calling f for each field descriptor and value encountered. +// Range returns immediately if f returns false. +// While iterating, mutating operations may only be performed +// on the current field descriptor. +func (x *fastReflection_QueryOutboundBallotKeyResponse) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.BallotId != "" { + value := protoreflect.ValueOfString(x.BallotId) + if !f(fd_QueryOutboundBallotKeyResponse_ballot_id, value) { + return + } + } + if x.CanonicalObservedTx != nil { + value := protoreflect.ValueOfMessage(x.CanonicalObservedTx.ProtoReflect()) + if !f(fd_QueryOutboundBallotKeyResponse_canonical_observed_tx, value) { + return + } + } +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_QueryOutboundBallotKeyResponse) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "uexecutor.v1.QueryOutboundBallotKeyResponse.ballot_id": + return x.BallotId != "" + case "uexecutor.v1.QueryOutboundBallotKeyResponse.canonical_observed_tx": + return x.CanonicalObservedTx != nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryOutboundBallotKeyResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryOutboundBallotKeyResponse does not contain field %s", fd.FullName())) + } +} + +// Clear clears the field such that a subsequent Has call reports false. +// +// Clearing an extension field clears both the extension type and value +// associated with the given field number. +// +// Clear is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryOutboundBallotKeyResponse) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "uexecutor.v1.QueryOutboundBallotKeyResponse.ballot_id": + x.BallotId = "" + case "uexecutor.v1.QueryOutboundBallotKeyResponse.canonical_observed_tx": + x.CanonicalObservedTx = nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryOutboundBallotKeyResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryOutboundBallotKeyResponse does not contain field %s", fd.FullName())) + } +} + +// Get retrieves the value for a field. +// +// For unpopulated scalars, it returns the default value, where +// the default value of a bytes scalar is guaranteed to be a copy. +// For unpopulated composite types, it returns an empty, read-only view +// of the value; to obtain a mutable reference, use Mutable. +func (x *fastReflection_QueryOutboundBallotKeyResponse) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "uexecutor.v1.QueryOutboundBallotKeyResponse.ballot_id": + value := x.BallotId + return protoreflect.ValueOfString(value) + case "uexecutor.v1.QueryOutboundBallotKeyResponse.canonical_observed_tx": + value := x.CanonicalObservedTx + return protoreflect.ValueOfMessage(value.ProtoReflect()) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryOutboundBallotKeyResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryOutboundBallotKeyResponse does not contain field %s", descriptor.FullName())) + } +} + +// Set stores the value for a field. +// +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType. +// When setting a composite type, it is unspecified whether the stored value +// aliases the source's memory in any way. If the composite value is an +// empty, read-only value, then it panics. +// +// Set is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryOutboundBallotKeyResponse) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "uexecutor.v1.QueryOutboundBallotKeyResponse.ballot_id": + x.BallotId = value.Interface().(string) + case "uexecutor.v1.QueryOutboundBallotKeyResponse.canonical_observed_tx": + x.CanonicalObservedTx = value.Message().Interface().(*OutboundObservation) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryOutboundBallotKeyResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryOutboundBallotKeyResponse does not contain field %s", fd.FullName())) + } +} + +// Mutable returns a mutable reference to a composite type. +// +// If the field is unpopulated, it may allocate a composite value. +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType +// if not already stored. +// It panics if the field does not contain a composite type. +// +// Mutable is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryOutboundBallotKeyResponse) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.QueryOutboundBallotKeyResponse.canonical_observed_tx": + if x.CanonicalObservedTx == nil { + x.CanonicalObservedTx = new(OutboundObservation) + } + return protoreflect.ValueOfMessage(x.CanonicalObservedTx.ProtoReflect()) + case "uexecutor.v1.QueryOutboundBallotKeyResponse.ballot_id": + panic(fmt.Errorf("field ballot_id of message uexecutor.v1.QueryOutboundBallotKeyResponse is not mutable")) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryOutboundBallotKeyResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryOutboundBallotKeyResponse does not contain field %s", fd.FullName())) + } +} + +// NewField returns a new value that is assignable to the field +// for the given descriptor. For scalars, this returns the default value. +// For lists, maps, and messages, this returns a new, empty, mutable value. +func (x *fastReflection_QueryOutboundBallotKeyResponse) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "uexecutor.v1.QueryOutboundBallotKeyResponse.ballot_id": + return protoreflect.ValueOfString("") + case "uexecutor.v1.QueryOutboundBallotKeyResponse.canonical_observed_tx": + m := new(OutboundObservation) + return protoreflect.ValueOfMessage(m.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: uexecutor.v1.QueryOutboundBallotKeyResponse")) + } + panic(fmt.Errorf("message uexecutor.v1.QueryOutboundBallotKeyResponse does not contain field %s", fd.FullName())) + } +} + +// WhichOneof reports which field within the oneof is populated, +// returning nil if none are populated. +// It panics if the oneof descriptor does not belong to this message. +func (x *fastReflection_QueryOutboundBallotKeyResponse) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in uexecutor.v1.QueryOutboundBallotKeyResponse", d.FullName())) + } + panic("unreachable") +} + +// GetUnknown retrieves the entire list of unknown fields. +// The caller may only mutate the contents of the RawFields +// if the mutated bytes are stored back into the message with SetUnknown. +func (x *fastReflection_QueryOutboundBallotKeyResponse) GetUnknown() protoreflect.RawFields { + return x.unknownFields +} + +// SetUnknown stores an entire list of unknown fields. +// The raw fields must be syntactically valid according to the wire format. +// An implementation may panic if this is not the case. +// Once stored, the caller must not mutate the content of the RawFields. +// An empty RawFields may be passed to clear the fields. +// +// SetUnknown is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_QueryOutboundBallotKeyResponse) SetUnknown(fields protoreflect.RawFields) { + x.unknownFields = fields +} + +// IsValid reports whether the message is valid. +// +// An invalid message is an empty, read-only value. +// +// An invalid message often corresponds to a nil pointer of the concrete +// message type, but the details are implementation dependent. +// Validity is not part of the protobuf data model, and may not +// be preserved in marshaling or other operations. +func (x *fastReflection_QueryOutboundBallotKeyResponse) IsValid() bool { + return x != nil +} + +// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. +// This method may return nil. +// +// The returned methods type is identical to +// "google.golang.org/protobuf/runtime/protoiface".Methods. +// Consult the protoiface package documentation for details. +func (x *fastReflection_QueryOutboundBallotKeyResponse) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*QueryOutboundBallotKeyResponse) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + l = len(x.BallotId) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.CanonicalObservedTx != nil { + l = options.Size(x.CanonicalObservedTx) + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*QueryOutboundBallotKeyResponse) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if x.CanonicalObservedTx != nil { + encoded, err := options.Marshal(x.CanonicalObservedTx) + if err != nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, err + } + i -= len(encoded) + copy(dAtA[i:], encoded) + i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) + i-- + dAtA[i] = 0x12 + } + if len(x.BallotId) > 0 { + i -= len(x.BallotId) + copy(dAtA[i:], x.BallotId) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.BallotId))) + i-- + dAtA[i] = 0xa + } + if input.Buf != nil { + input.Buf = append(input.Buf, dAtA...) + } else { + input.Buf = dAtA + } + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { + x := input.Message.Interface().(*QueryOutboundBallotKeyResponse) + if x == nil { + return protoiface.UnmarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Flags: input.Flags, + }, nil + } + options := runtime.UnmarshalInputToOptions(input) + _ = options + dAtA := input.Buf + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, 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 protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryOutboundBallotKeyResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: QueryOutboundBallotKeyResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field BallotId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.BallotId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field CanonicalObservedTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if x.CanonicalObservedTx == nil { + x.CanonicalObservedTx = &OutboundObservation{} + } + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.CanonicalObservedTx); err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.0 @@ -12133,6 +14193,188 @@ func (x *QueryAllPendingOutboundsResponse) GetPagination() *v1beta1.PageResponse return nil } +// InboundKeys: derive canonical UTX id + inbound ballot id from an inbound. +type QueryInboundKeysRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Inbound *Inbound `protobuf:"bytes,1,opt,name=inbound,proto3" json:"inbound,omitempty"` +} + +func (x *QueryInboundKeysRequest) Reset() { + *x = QueryInboundKeysRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_uexecutor_v1_query_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryInboundKeysRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryInboundKeysRequest) ProtoMessage() {} + +// Deprecated: Use QueryInboundKeysRequest.ProtoReflect.Descriptor instead. +func (*QueryInboundKeysRequest) Descriptor() ([]byte, []int) { + return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{23} +} + +func (x *QueryInboundKeysRequest) GetInbound() *Inbound { + if x != nil { + return x.Inbound + } + return nil +} + +type QueryInboundKeysResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UtxId string `protobuf:"bytes,1,opt,name=utx_id,json=utxId,proto3" json:"utx_id,omitempty"` // canonical UniversalTx key + BallotId string `protobuf:"bytes,2,opt,name=ballot_id,json=ballotId,proto3" json:"ballot_id,omitempty"` // canonical inbound ballot key + CanonicalInbound *Inbound `protobuf:"bytes,3,opt,name=canonical_inbound,json=canonicalInbound,proto3" json:"canonical_inbound,omitempty"` // the canonicalized inbound the chain derived the keys from +} + +func (x *QueryInboundKeysResponse) Reset() { + *x = QueryInboundKeysResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_uexecutor_v1_query_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryInboundKeysResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryInboundKeysResponse) ProtoMessage() {} + +// Deprecated: Use QueryInboundKeysResponse.ProtoReflect.Descriptor instead. +func (*QueryInboundKeysResponse) Descriptor() ([]byte, []int) { + return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{24} +} + +func (x *QueryInboundKeysResponse) GetUtxId() string { + if x != nil { + return x.UtxId + } + return "" +} + +func (x *QueryInboundKeysResponse) GetBallotId() string { + if x != nil { + return x.BallotId + } + return "" +} + +func (x *QueryInboundKeysResponse) GetCanonicalInbound() *Inbound { + if x != nil { + return x.CanonicalInbound + } + return nil +} + +// OutboundBallotKey: derive the canonical outbound ballot id for an observation. +type QueryOutboundBallotKeyRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UtxId string `protobuf:"bytes,1,opt,name=utx_id,json=utxId,proto3" json:"utx_id,omitempty"` // UniversalTx the outbound belongs to + OutboundId string `protobuf:"bytes,2,opt,name=outbound_id,json=outboundId,proto3" json:"outbound_id,omitempty"` // outbound being observed + ObservedTx *OutboundObservation `protobuf:"bytes,3,opt,name=observed_tx,json=observedTx,proto3" json:"observed_tx,omitempty"` // the observation being voted +} + +func (x *QueryOutboundBallotKeyRequest) Reset() { + *x = QueryOutboundBallotKeyRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_uexecutor_v1_query_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryOutboundBallotKeyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryOutboundBallotKeyRequest) ProtoMessage() {} + +// Deprecated: Use QueryOutboundBallotKeyRequest.ProtoReflect.Descriptor instead. +func (*QueryOutboundBallotKeyRequest) Descriptor() ([]byte, []int) { + return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{25} +} + +func (x *QueryOutboundBallotKeyRequest) GetUtxId() string { + if x != nil { + return x.UtxId + } + return "" +} + +func (x *QueryOutboundBallotKeyRequest) GetOutboundId() string { + if x != nil { + return x.OutboundId + } + return "" +} + +func (x *QueryOutboundBallotKeyRequest) GetObservedTx() *OutboundObservation { + if x != nil { + return x.ObservedTx + } + return nil +} + +type QueryOutboundBallotKeyResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + BallotId string `protobuf:"bytes,1,opt,name=ballot_id,json=ballotId,proto3" json:"ballot_id,omitempty"` // canonical outbound ballot key + CanonicalObservedTx *OutboundObservation `protobuf:"bytes,2,opt,name=canonical_observed_tx,json=canonicalObservedTx,proto3" json:"canonical_observed_tx,omitempty"` // observation after canonicalization +} + +func (x *QueryOutboundBallotKeyResponse) Reset() { + *x = QueryOutboundBallotKeyResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_uexecutor_v1_query_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryOutboundBallotKeyResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryOutboundBallotKeyResponse) ProtoMessage() {} + +// Deprecated: Use QueryOutboundBallotKeyResponse.ProtoReflect.Descriptor instead. +func (*QueryOutboundBallotKeyResponse) Descriptor() ([]byte, []int) { + return file_uexecutor_v1_query_proto_rawDescGZIP(), []int{26} +} + +func (x *QueryOutboundBallotKeyResponse) GetBallotId() string { + if x != nil { + return x.BallotId + } + return "" +} + +func (x *QueryOutboundBallotKeyResponse) GetCanonicalObservedTx() *OutboundObservation { + if x != nil { + return x.CanonicalObservedTx + } + return nil +} + var File_uexecutor_v1_query_proto protoreflect.FileDescriptor var file_uexecutor_v1_query_proto_rawDesc = []byte{ @@ -12317,117 +14559,169 @@ var file_uexecutor_v1_query_proto_rawDesc = []byte{ 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x70, 0x61, - 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0xa8, 0x0c, 0x0a, 0x05, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x12, 0x6b, 0x0a, 0x06, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x20, 0x2e, 0x75, + 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x4a, 0x0a, 0x17, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x07, 0x69, 0x6e, 0x62, + 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x92, 0x01, 0x0a, 0x18, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6e, + 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x15, 0x0a, 0x06, 0x75, 0x74, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x75, 0x74, 0x78, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x61, 0x6c, 0x6c, + 0x6f, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x61, 0x6c, + 0x6c, 0x6f, 0x74, 0x49, 0x64, 0x12, 0x42, 0x0a, 0x11, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, + 0x61, 0x6c, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x15, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x10, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, + 0x61, 0x6c, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x9b, 0x01, 0x0a, 0x1d, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x61, 0x6c, 0x6c, 0x6f, + 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x75, + 0x74, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x75, 0x74, 0x78, + 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, + 0x64, 0x49, 0x64, 0x12, 0x42, 0x0a, 0x0b, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, + 0x74, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, + 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x6f, 0x62, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x64, 0x54, 0x78, 0x22, 0x94, 0x01, 0x0a, 0x1e, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x61, 0x6c, 0x6c, 0x6f, 0x74, 0x4b, + 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x61, + 0x6c, 0x6c, 0x6f, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, + 0x61, 0x6c, 0x6c, 0x6f, 0x74, 0x49, 0x64, 0x12, 0x55, 0x0a, 0x15, 0x63, 0x61, 0x6e, 0x6f, 0x6e, + 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x74, 0x78, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4f, 0x62, + 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x63, 0x61, 0x6e, 0x6f, 0x6e, + 0x69, 0x63, 0x61, 0x6c, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x54, 0x78, 0x32, 0xcd, + 0x0e, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x6b, 0x0a, 0x06, 0x50, 0x61, 0x72, 0x61, + 0x6d, 0x73, 0x12, 0x20, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, + 0x14, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x70, + 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x99, 0x01, 0x0a, 0x12, 0x41, 0x6c, 0x6c, 0x50, 0x65, 0x6e, + 0x64, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x2c, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, - 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x75, 0x65, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, - 0x99, 0x01, 0x0a, 0x12, 0x41, 0x6c, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x49, 0x6e, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x2c, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x50, 0x65, - 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x50, 0x65, 0x6e, 0x64, - 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x75, 0x65, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x65, 0x6e, 0x64, 0x69, - 0x6e, 0x67, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x8f, 0x01, 0x0a, 0x0e, - 0x47, 0x65, 0x74, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, 0x12, 0x28, + 0x79, 0x41, 0x6c, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x62, 0x6f, 0x75, + 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x75, 0x65, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, + 0x6c, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x20, 0x12, 0x1e, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, + 0x2f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, + 0x73, 0x12, 0x8f, 0x01, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, + 0x61, 0x6c, 0x54, 0x78, 0x12, 0x28, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, 0x65, 0x74, 0x55, 0x6e, 0x69, 0x76, + 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, 0x65, 0x74, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, - 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, 0x65, 0x74, - 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x12, 0x20, 0x2f, 0x75, 0x65, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x6e, 0x69, 0x76, 0x65, - 0x72, 0x73, 0x61, 0x6c, 0x5f, 0x74, 0x78, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x8a, 0x01, - 0x0a, 0x0e, 0x41, 0x6c, 0x6c, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, - 0x12, 0x28, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x22, 0x12, 0x20, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, + 0x2f, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x5f, 0x74, 0x78, 0x73, 0x2f, 0x7b, + 0x69, 0x64, 0x7d, 0x12, 0x8a, 0x01, 0x0a, 0x0e, 0x41, 0x6c, 0x6c, 0x55, 0x6e, 0x69, 0x76, 0x65, + 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, 0x12, 0x28, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x55, 0x6e, + 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x29, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, - 0x6c, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x75, 0x65, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, - 0x6c, 0x6c, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x54, 0x78, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, - 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x6e, 0x69, - 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x5f, 0x74, 0x78, 0x73, 0x12, 0x7f, 0x0a, 0x08, 0x47, 0x61, - 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x22, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, 0x61, 0x73, 0x50, 0x72, - 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x75, 0x65, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, - 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x12, 0x22, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x61, 0x73, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, - 0x2f, 0x7b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x81, 0x01, 0x0a, 0x0c, - 0x41, 0x6c, 0x6c, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x73, 0x12, 0x26, 0x2e, 0x75, + 0x6c, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, + 0x76, 0x31, 0x2f, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x5f, 0x74, 0x78, 0x73, + 0x12, 0x7f, 0x0a, 0x08, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x22, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x41, 0x6c, 0x6c, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x47, 0x61, 0x73, 0x50, - 0x72, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, - 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x61, 0x73, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x73, 0x12, - 0x83, 0x01, 0x0a, 0x09, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x23, 0x2e, + 0x79, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x23, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x12, 0x22, 0x2f, + 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x61, 0x73, + 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x2f, 0x7b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, + 0x7d, 0x12, 0x81, 0x01, 0x0a, 0x0c, 0x41, 0x6c, 0x6c, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, + 0x65, 0x73, 0x12, 0x26, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, + 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x75, 0x65, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, + 0x6c, 0x6c, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x75, 0x65, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x61, 0x73, 0x5f, 0x70, + 0x72, 0x69, 0x63, 0x65, 0x73, 0x12, 0x83, 0x01, 0x0a, 0x09, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, + 0x65, 0x74, 0x61, 0x12, 0x23, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, + 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, + 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x61, + 0x2f, 0x7b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x85, 0x01, 0x0a, 0x0d, + 0x41, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x73, 0x12, 0x27, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, - 0x12, 0x23, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, - 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x2f, 0x7b, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x85, 0x01, 0x0a, 0x0d, 0x41, 0x6c, 0x6c, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x73, 0x12, 0x27, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x28, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, - 0x61, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x1b, 0x12, 0x19, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, - 0x31, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x73, 0x12, 0xa7, 0x01, - 0x0a, 0x12, 0x47, 0x65, 0x74, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x62, - 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2c, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, 0x65, 0x74, 0x50, 0x65, 0x6e, 0x64, - 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x12, 0x19, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x6d, 0x65, + 0x74, 0x61, 0x73, 0x12, 0xa7, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x50, 0x65, 0x6e, 0x64, 0x69, + 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2c, 0x2e, 0x75, 0x65, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, + 0x65, 0x74, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, + 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, 0x65, 0x74, + 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x12, + 0x2c, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x70, + 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2f, + 0x7b, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x9d, 0x01, + 0x0a, 0x13, 0x41, 0x6c, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x62, + 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x2d, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x50, 0x65, 0x6e, + 0x64, 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x50, 0x65, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x12, 0x1f, 0x2f, 0x75, + 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x65, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x5f, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x99, 0x01, + 0x0a, 0x12, 0x41, 0x6c, 0x6c, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x49, 0x6e, 0x62, 0x6f, + 0x75, 0x6e, 0x64, 0x73, 0x12, 0x2c, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x45, 0x78, 0x70, 0x69, + 0x72, 0x65, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x47, 0x65, 0x74, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x12, 0x2c, 0x2f, 0x75, 0x65, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, - 0x5f, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x7b, 0x6f, 0x75, 0x74, 0x62, 0x6f, - 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x9d, 0x01, 0x0a, 0x13, 0x41, 0x6c, 0x6c, 0x50, - 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, - 0x2d, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4f, 0x75, - 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, - 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4f, 0x75, 0x74, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x12, 0x1f, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6f, 0x75, - 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x99, 0x01, 0x0a, 0x12, 0x41, 0x6c, 0x6c, 0x45, - 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x2c, - 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x49, 0x6e, 0x62, - 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x75, - 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x41, 0x6c, 0x6c, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, - 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, - 0x76, 0x31, 0x2f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x75, - 0x6e, 0x64, 0x73, 0x42, 0xb2, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x75, 0x65, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x42, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x70, 0x75, 0x73, 0x68, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x2f, 0x70, 0x75, 0x73, - 0x68, 0x2d, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x61, 0x70, 0x69, - 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x3b, 0x75, 0x65, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x55, 0x58, 0x58, 0xaa, - 0x02, 0x0c, 0x55, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x56, 0x31, 0xca, 0x02, - 0x0c, 0x55, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x18, - 0x55, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0d, 0x55, 0x65, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x6f, 0x72, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x41, 0x6c, 0x6c, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, + 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x75, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, + 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x83, 0x01, 0x0a, 0x0b, 0x49, 0x6e, + 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x25, 0x2e, 0x75, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6e, + 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x26, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4b, 0x65, 0x79, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, + 0x3a, 0x01, 0x2a, 0x22, 0x1a, 0x2f, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, + 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x12, + 0x9c, 0x01, 0x0a, 0x11, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x61, 0x6c, 0x6c, + 0x6f, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x2b, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, + 0x6e, 0x64, 0x42, 0x61, 0x6c, 0x6c, 0x6f, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x42, + 0x61, 0x6c, 0x6c, 0x6f, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21, 0x2f, 0x75, 0x65, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x75, 0x74, 0x62, 0x6f, + 0x75, 0x6e, 0x64, 0x5f, 0x62, 0x61, 0x6c, 0x6c, 0x6f, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x42, 0xb2, + 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, + 0x2e, 0x76, 0x31, 0x42, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, + 0x01, 0x5a, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x75, + 0x73, 0x68, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x2f, 0x70, 0x75, 0x73, 0x68, 0x2d, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x75, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x76, 0x31, 0x3b, 0x75, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x6f, 0x72, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x55, 0x58, 0x58, 0xaa, 0x02, 0x0c, 0x55, 0x65, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0c, 0x55, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x6f, 0x72, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x18, 0x55, 0x65, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x6f, 0x72, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0xea, 0x02, 0x0d, 0x55, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x3a, + 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -12442,7 +14736,7 @@ func file_uexecutor_v1_query_proto_rawDescGZIP() []byte { return file_uexecutor_v1_query_proto_rawDescData } -var file_uexecutor_v1_query_proto_msgTypes = make([]protoimpl.MessageInfo, 23) +var file_uexecutor_v1_query_proto_msgTypes = make([]protoimpl.MessageInfo, 27) var file_uexecutor_v1_query_proto_goTypes = []interface{}{ (*QueryGasPriceRequest)(nil), // 0: uexecutor.v1.QueryGasPriceRequest (*QueryGasPriceResponse)(nil), // 1: uexecutor.v1.QueryGasPriceResponse @@ -12467,72 +14761,86 @@ var file_uexecutor_v1_query_proto_goTypes = []interface{}{ (*QueryGetPendingOutboundResponse)(nil), // 20: uexecutor.v1.QueryGetPendingOutboundResponse (*QueryAllPendingOutboundsRequest)(nil), // 21: uexecutor.v1.QueryAllPendingOutboundsRequest (*QueryAllPendingOutboundsResponse)(nil), // 22: uexecutor.v1.QueryAllPendingOutboundsResponse - (*GasPrice)(nil), // 23: uexecutor.v1.GasPrice - (*v1beta1.PageRequest)(nil), // 24: cosmos.base.query.v1beta1.PageRequest - (*v1beta1.PageResponse)(nil), // 25: cosmos.base.query.v1beta1.PageResponse - (*ChainMeta)(nil), // 26: uexecutor.v1.ChainMeta - (*Params)(nil), // 27: uexecutor.v1.Params - (*PendingInboundEntry)(nil), // 28: uexecutor.v1.PendingInboundEntry - (*ExpiredInboundEntry)(nil), // 29: uexecutor.v1.ExpiredInboundEntry - (*UniversalTxLegacy)(nil), // 30: uexecutor.v1.UniversalTxLegacy - (*UniversalTx)(nil), // 31: uexecutor.v1.UniversalTx - (*OutboundObservationVariant)(nil), // 32: uexecutor.v1.OutboundObservationVariant - (*OutboundTx)(nil), // 33: uexecutor.v1.OutboundTx + (*QueryInboundKeysRequest)(nil), // 23: uexecutor.v1.QueryInboundKeysRequest + (*QueryInboundKeysResponse)(nil), // 24: uexecutor.v1.QueryInboundKeysResponse + (*QueryOutboundBallotKeyRequest)(nil), // 25: uexecutor.v1.QueryOutboundBallotKeyRequest + (*QueryOutboundBallotKeyResponse)(nil), // 26: uexecutor.v1.QueryOutboundBallotKeyResponse + (*GasPrice)(nil), // 27: uexecutor.v1.GasPrice + (*v1beta1.PageRequest)(nil), // 28: cosmos.base.query.v1beta1.PageRequest + (*v1beta1.PageResponse)(nil), // 29: cosmos.base.query.v1beta1.PageResponse + (*ChainMeta)(nil), // 30: uexecutor.v1.ChainMeta + (*Params)(nil), // 31: uexecutor.v1.Params + (*PendingInboundEntry)(nil), // 32: uexecutor.v1.PendingInboundEntry + (*ExpiredInboundEntry)(nil), // 33: uexecutor.v1.ExpiredInboundEntry + (*UniversalTxLegacy)(nil), // 34: uexecutor.v1.UniversalTxLegacy + (*UniversalTx)(nil), // 35: uexecutor.v1.UniversalTx + (*OutboundObservationVariant)(nil), // 36: uexecutor.v1.OutboundObservationVariant + (*OutboundTx)(nil), // 37: uexecutor.v1.OutboundTx + (*Inbound)(nil), // 38: uexecutor.v1.Inbound + (*OutboundObservation)(nil), // 39: uexecutor.v1.OutboundObservation } var file_uexecutor_v1_query_proto_depIdxs = []int32{ - 23, // 0: uexecutor.v1.QueryGasPriceResponse.gas_price:type_name -> uexecutor.v1.GasPrice - 24, // 1: uexecutor.v1.QueryAllGasPricesRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest - 23, // 2: uexecutor.v1.QueryAllGasPricesResponse.gas_prices:type_name -> uexecutor.v1.GasPrice - 25, // 3: uexecutor.v1.QueryAllGasPricesResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse - 26, // 4: uexecutor.v1.QueryChainMetaResponse.chain_meta:type_name -> uexecutor.v1.ChainMeta - 24, // 5: uexecutor.v1.QueryAllChainMetasRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest - 26, // 6: uexecutor.v1.QueryAllChainMetasResponse.chain_metas:type_name -> uexecutor.v1.ChainMeta - 25, // 7: uexecutor.v1.QueryAllChainMetasResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse - 27, // 8: uexecutor.v1.QueryParamsResponse.params:type_name -> uexecutor.v1.Params - 24, // 9: uexecutor.v1.QueryAllPendingInboundsRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest - 28, // 10: uexecutor.v1.QueryAllPendingInboundsResponse.entries:type_name -> uexecutor.v1.PendingInboundEntry - 25, // 11: uexecutor.v1.QueryAllPendingInboundsResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse - 24, // 12: uexecutor.v1.QueryAllExpiredInboundsRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest - 29, // 13: uexecutor.v1.QueryAllExpiredInboundsResponse.entries:type_name -> uexecutor.v1.ExpiredInboundEntry - 25, // 14: uexecutor.v1.QueryAllExpiredInboundsResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse - 30, // 15: uexecutor.v1.QueryGetUniversalTxResponse.universal_tx:type_name -> uexecutor.v1.UniversalTxLegacy - 24, // 16: uexecutor.v1.QueryAllUniversalTxRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest - 31, // 17: uexecutor.v1.QueryAllUniversalTxResponse.universal_txs:type_name -> uexecutor.v1.UniversalTx - 25, // 18: uexecutor.v1.QueryAllUniversalTxResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse - 32, // 19: uexecutor.v1.PendingOutboundEntry.variants:type_name -> uexecutor.v1.OutboundObservationVariant + 27, // 0: uexecutor.v1.QueryGasPriceResponse.gas_price:type_name -> uexecutor.v1.GasPrice + 28, // 1: uexecutor.v1.QueryAllGasPricesRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest + 27, // 2: uexecutor.v1.QueryAllGasPricesResponse.gas_prices:type_name -> uexecutor.v1.GasPrice + 29, // 3: uexecutor.v1.QueryAllGasPricesResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse + 30, // 4: uexecutor.v1.QueryChainMetaResponse.chain_meta:type_name -> uexecutor.v1.ChainMeta + 28, // 5: uexecutor.v1.QueryAllChainMetasRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest + 30, // 6: uexecutor.v1.QueryAllChainMetasResponse.chain_metas:type_name -> uexecutor.v1.ChainMeta + 29, // 7: uexecutor.v1.QueryAllChainMetasResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse + 31, // 8: uexecutor.v1.QueryParamsResponse.params:type_name -> uexecutor.v1.Params + 28, // 9: uexecutor.v1.QueryAllPendingInboundsRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest + 32, // 10: uexecutor.v1.QueryAllPendingInboundsResponse.entries:type_name -> uexecutor.v1.PendingInboundEntry + 29, // 11: uexecutor.v1.QueryAllPendingInboundsResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse + 28, // 12: uexecutor.v1.QueryAllExpiredInboundsRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest + 33, // 13: uexecutor.v1.QueryAllExpiredInboundsResponse.entries:type_name -> uexecutor.v1.ExpiredInboundEntry + 29, // 14: uexecutor.v1.QueryAllExpiredInboundsResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse + 34, // 15: uexecutor.v1.QueryGetUniversalTxResponse.universal_tx:type_name -> uexecutor.v1.UniversalTxLegacy + 28, // 16: uexecutor.v1.QueryAllUniversalTxRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest + 35, // 17: uexecutor.v1.QueryAllUniversalTxResponse.universal_txs:type_name -> uexecutor.v1.UniversalTx + 29, // 18: uexecutor.v1.QueryAllUniversalTxResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse + 36, // 19: uexecutor.v1.PendingOutboundEntry.variants:type_name -> uexecutor.v1.OutboundObservationVariant 18, // 20: uexecutor.v1.QueryGetPendingOutboundResponse.entry:type_name -> uexecutor.v1.PendingOutboundEntry - 33, // 21: uexecutor.v1.QueryGetPendingOutboundResponse.outbound:type_name -> uexecutor.v1.OutboundTx - 24, // 22: uexecutor.v1.QueryAllPendingOutboundsRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest + 37, // 21: uexecutor.v1.QueryGetPendingOutboundResponse.outbound:type_name -> uexecutor.v1.OutboundTx + 28, // 22: uexecutor.v1.QueryAllPendingOutboundsRequest.pagination:type_name -> cosmos.base.query.v1beta1.PageRequest 18, // 23: uexecutor.v1.QueryAllPendingOutboundsResponse.entries:type_name -> uexecutor.v1.PendingOutboundEntry - 33, // 24: uexecutor.v1.QueryAllPendingOutboundsResponse.outbounds:type_name -> uexecutor.v1.OutboundTx - 25, // 25: uexecutor.v1.QueryAllPendingOutboundsResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse - 8, // 26: uexecutor.v1.Query.Params:input_type -> uexecutor.v1.QueryParamsRequest - 10, // 27: uexecutor.v1.Query.AllPendingInbounds:input_type -> uexecutor.v1.QueryAllPendingInboundsRequest - 14, // 28: uexecutor.v1.Query.GetUniversalTx:input_type -> uexecutor.v1.QueryGetUniversalTxRequest - 16, // 29: uexecutor.v1.Query.AllUniversalTx:input_type -> uexecutor.v1.QueryAllUniversalTxRequest - 0, // 30: uexecutor.v1.Query.GasPrice:input_type -> uexecutor.v1.QueryGasPriceRequest - 2, // 31: uexecutor.v1.Query.AllGasPrices:input_type -> uexecutor.v1.QueryAllGasPricesRequest - 4, // 32: uexecutor.v1.Query.ChainMeta:input_type -> uexecutor.v1.QueryChainMetaRequest - 6, // 33: uexecutor.v1.Query.AllChainMetas:input_type -> uexecutor.v1.QueryAllChainMetasRequest - 19, // 34: uexecutor.v1.Query.GetPendingOutbound:input_type -> uexecutor.v1.QueryGetPendingOutboundRequest - 21, // 35: uexecutor.v1.Query.AllPendingOutbounds:input_type -> uexecutor.v1.QueryAllPendingOutboundsRequest - 12, // 36: uexecutor.v1.Query.AllExpiredInbounds:input_type -> uexecutor.v1.QueryAllExpiredInboundsRequest - 9, // 37: uexecutor.v1.Query.Params:output_type -> uexecutor.v1.QueryParamsResponse - 11, // 38: uexecutor.v1.Query.AllPendingInbounds:output_type -> uexecutor.v1.QueryAllPendingInboundsResponse - 15, // 39: uexecutor.v1.Query.GetUniversalTx:output_type -> uexecutor.v1.QueryGetUniversalTxResponse - 17, // 40: uexecutor.v1.Query.AllUniversalTx:output_type -> uexecutor.v1.QueryAllUniversalTxResponse - 1, // 41: uexecutor.v1.Query.GasPrice:output_type -> uexecutor.v1.QueryGasPriceResponse - 3, // 42: uexecutor.v1.Query.AllGasPrices:output_type -> uexecutor.v1.QueryAllGasPricesResponse - 5, // 43: uexecutor.v1.Query.ChainMeta:output_type -> uexecutor.v1.QueryChainMetaResponse - 7, // 44: uexecutor.v1.Query.AllChainMetas:output_type -> uexecutor.v1.QueryAllChainMetasResponse - 20, // 45: uexecutor.v1.Query.GetPendingOutbound:output_type -> uexecutor.v1.QueryGetPendingOutboundResponse - 22, // 46: uexecutor.v1.Query.AllPendingOutbounds:output_type -> uexecutor.v1.QueryAllPendingOutboundsResponse - 13, // 47: uexecutor.v1.Query.AllExpiredInbounds:output_type -> uexecutor.v1.QueryAllExpiredInboundsResponse - 37, // [37:48] is the sub-list for method output_type - 26, // [26:37] is the sub-list for method input_type - 26, // [26:26] is the sub-list for extension type_name - 26, // [26:26] is the sub-list for extension extendee - 0, // [0:26] is the sub-list for field type_name + 37, // 24: uexecutor.v1.QueryAllPendingOutboundsResponse.outbounds:type_name -> uexecutor.v1.OutboundTx + 29, // 25: uexecutor.v1.QueryAllPendingOutboundsResponse.pagination:type_name -> cosmos.base.query.v1beta1.PageResponse + 38, // 26: uexecutor.v1.QueryInboundKeysRequest.inbound:type_name -> uexecutor.v1.Inbound + 38, // 27: uexecutor.v1.QueryInboundKeysResponse.canonical_inbound:type_name -> uexecutor.v1.Inbound + 39, // 28: uexecutor.v1.QueryOutboundBallotKeyRequest.observed_tx:type_name -> uexecutor.v1.OutboundObservation + 39, // 29: uexecutor.v1.QueryOutboundBallotKeyResponse.canonical_observed_tx:type_name -> uexecutor.v1.OutboundObservation + 8, // 30: uexecutor.v1.Query.Params:input_type -> uexecutor.v1.QueryParamsRequest + 10, // 31: uexecutor.v1.Query.AllPendingInbounds:input_type -> uexecutor.v1.QueryAllPendingInboundsRequest + 14, // 32: uexecutor.v1.Query.GetUniversalTx:input_type -> uexecutor.v1.QueryGetUniversalTxRequest + 16, // 33: uexecutor.v1.Query.AllUniversalTx:input_type -> uexecutor.v1.QueryAllUniversalTxRequest + 0, // 34: uexecutor.v1.Query.GasPrice:input_type -> uexecutor.v1.QueryGasPriceRequest + 2, // 35: uexecutor.v1.Query.AllGasPrices:input_type -> uexecutor.v1.QueryAllGasPricesRequest + 4, // 36: uexecutor.v1.Query.ChainMeta:input_type -> uexecutor.v1.QueryChainMetaRequest + 6, // 37: uexecutor.v1.Query.AllChainMetas:input_type -> uexecutor.v1.QueryAllChainMetasRequest + 19, // 38: uexecutor.v1.Query.GetPendingOutbound:input_type -> uexecutor.v1.QueryGetPendingOutboundRequest + 21, // 39: uexecutor.v1.Query.AllPendingOutbounds:input_type -> uexecutor.v1.QueryAllPendingOutboundsRequest + 12, // 40: uexecutor.v1.Query.AllExpiredInbounds:input_type -> uexecutor.v1.QueryAllExpiredInboundsRequest + 23, // 41: uexecutor.v1.Query.InboundKeys:input_type -> uexecutor.v1.QueryInboundKeysRequest + 25, // 42: uexecutor.v1.Query.OutboundBallotKey:input_type -> uexecutor.v1.QueryOutboundBallotKeyRequest + 9, // 43: uexecutor.v1.Query.Params:output_type -> uexecutor.v1.QueryParamsResponse + 11, // 44: uexecutor.v1.Query.AllPendingInbounds:output_type -> uexecutor.v1.QueryAllPendingInboundsResponse + 15, // 45: uexecutor.v1.Query.GetUniversalTx:output_type -> uexecutor.v1.QueryGetUniversalTxResponse + 17, // 46: uexecutor.v1.Query.AllUniversalTx:output_type -> uexecutor.v1.QueryAllUniversalTxResponse + 1, // 47: uexecutor.v1.Query.GasPrice:output_type -> uexecutor.v1.QueryGasPriceResponse + 3, // 48: uexecutor.v1.Query.AllGasPrices:output_type -> uexecutor.v1.QueryAllGasPricesResponse + 5, // 49: uexecutor.v1.Query.ChainMeta:output_type -> uexecutor.v1.QueryChainMetaResponse + 7, // 50: uexecutor.v1.Query.AllChainMetas:output_type -> uexecutor.v1.QueryAllChainMetasResponse + 20, // 51: uexecutor.v1.Query.GetPendingOutbound:output_type -> uexecutor.v1.QueryGetPendingOutboundResponse + 22, // 52: uexecutor.v1.Query.AllPendingOutbounds:output_type -> uexecutor.v1.QueryAllPendingOutboundsResponse + 13, // 53: uexecutor.v1.Query.AllExpiredInbounds:output_type -> uexecutor.v1.QueryAllExpiredInboundsResponse + 24, // 54: uexecutor.v1.Query.InboundKeys:output_type -> uexecutor.v1.QueryInboundKeysResponse + 26, // 55: uexecutor.v1.Query.OutboundBallotKey:output_type -> uexecutor.v1.QueryOutboundBallotKeyResponse + 43, // [43:56] is the sub-list for method output_type + 30, // [30:43] is the sub-list for method input_type + 30, // [30:30] is the sub-list for extension type_name + 30, // [30:30] is the sub-list for extension extendee + 0, // [0:30] is the sub-list for field type_name } func init() { file_uexecutor_v1_query_proto_init() } @@ -12821,6 +15129,54 @@ func file_uexecutor_v1_query_proto_init() { return nil } } + file_uexecutor_v1_query_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryInboundKeysRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_uexecutor_v1_query_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryInboundKeysResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_uexecutor_v1_query_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryOutboundBallotKeyRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_uexecutor_v1_query_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryOutboundBallotKeyResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -12828,7 +15184,7 @@ func file_uexecutor_v1_query_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_uexecutor_v1_query_proto_rawDesc, NumEnums: 0, - NumMessages: 23, + NumMessages: 27, NumExtensions: 0, NumServices: 1, }, diff --git a/api/uexecutor/v1/query_grpc.pb.go b/api/uexecutor/v1/query_grpc.pb.go index 0247c9fde..430ab0a9c 100644 --- a/api/uexecutor/v1/query_grpc.pb.go +++ b/api/uexecutor/v1/query_grpc.pb.go @@ -30,6 +30,8 @@ const ( Query_GetPendingOutbound_FullMethodName = "/uexecutor.v1.Query/GetPendingOutbound" Query_AllPendingOutbounds_FullMethodName = "/uexecutor.v1.Query/AllPendingOutbounds" Query_AllExpiredInbounds_FullMethodName = "/uexecutor.v1.Query/AllExpiredInbounds" + Query_InboundKeys_FullMethodName = "/uexecutor.v1.Query/InboundKeys" + Query_OutboundBallotKey_FullMethodName = "/uexecutor.v1.Query/OutboundBallotKey" ) // QueryClient is the client API for Query service. @@ -60,6 +62,14 @@ type QueryClient interface { // inbounds whose ballots all reached EXPIRED/REJECTED without producing // a UniversalTx). Consumed by the future escape-hatch refund flow. AllExpiredInbounds(ctx context.Context, in *QueryAllExpiredInboundsRequest, opts ...grpc.CallOption) (*QueryAllExpiredInboundsResponse, error) + // Derives the canonical UTX id and inbound ballot id for a given inbound, + // so off-chain validators read the keys from the chain instead of + // re-implementing the canonicalization + digest rules. + InboundKeys(ctx context.Context, in *QueryInboundKeysRequest, opts ...grpc.CallOption) (*QueryInboundKeysResponse, error) + // Derives the canonical outbound ballot id for a given observation. The + // observed tx hash is canonicalized against the outbound's destination + // chain (looked up by utx_id/outbound_id). + OutboundBallotKey(ctx context.Context, in *QueryOutboundBallotKeyRequest, opts ...grpc.CallOption) (*QueryOutboundBallotKeyResponse, error) } type queryClient struct { @@ -169,6 +179,24 @@ func (c *queryClient) AllExpiredInbounds(ctx context.Context, in *QueryAllExpire return out, nil } +func (c *queryClient) InboundKeys(ctx context.Context, in *QueryInboundKeysRequest, opts ...grpc.CallOption) (*QueryInboundKeysResponse, error) { + out := new(QueryInboundKeysResponse) + err := c.cc.Invoke(ctx, Query_InboundKeys_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) OutboundBallotKey(ctx context.Context, in *QueryOutboundBallotKeyRequest, opts ...grpc.CallOption) (*QueryOutboundBallotKeyResponse, error) { + out := new(QueryOutboundBallotKeyResponse) + err := c.cc.Invoke(ctx, Query_OutboundBallotKey_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. // All implementations must embed UnimplementedQueryServer // for forward compatibility @@ -197,6 +225,14 @@ type QueryServer interface { // inbounds whose ballots all reached EXPIRED/REJECTED without producing // a UniversalTx). Consumed by the future escape-hatch refund flow. AllExpiredInbounds(context.Context, *QueryAllExpiredInboundsRequest) (*QueryAllExpiredInboundsResponse, error) + // Derives the canonical UTX id and inbound ballot id for a given inbound, + // so off-chain validators read the keys from the chain instead of + // re-implementing the canonicalization + digest rules. + InboundKeys(context.Context, *QueryInboundKeysRequest) (*QueryInboundKeysResponse, error) + // Derives the canonical outbound ballot id for a given observation. The + // observed tx hash is canonicalized against the outbound's destination + // chain (looked up by utx_id/outbound_id). + OutboundBallotKey(context.Context, *QueryOutboundBallotKeyRequest) (*QueryOutboundBallotKeyResponse, error) mustEmbedUnimplementedQueryServer() } @@ -237,6 +273,12 @@ func (UnimplementedQueryServer) AllPendingOutbounds(context.Context, *QueryAllPe func (UnimplementedQueryServer) AllExpiredInbounds(context.Context, *QueryAllExpiredInboundsRequest) (*QueryAllExpiredInboundsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method AllExpiredInbounds not implemented") } +func (UnimplementedQueryServer) InboundKeys(context.Context, *QueryInboundKeysRequest) (*QueryInboundKeysResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method InboundKeys not implemented") +} +func (UnimplementedQueryServer) OutboundBallotKey(context.Context, *QueryOutboundBallotKeyRequest) (*QueryOutboundBallotKeyResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method OutboundBallotKey not implemented") +} func (UnimplementedQueryServer) mustEmbedUnimplementedQueryServer() {} // UnsafeQueryServer may be embedded to opt out of forward compatibility for this service. @@ -448,6 +490,42 @@ func _Query_AllExpiredInbounds_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +func _Query_InboundKeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryInboundKeysRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).InboundKeys(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Query_InboundKeys_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).InboundKeys(ctx, req.(*QueryInboundKeysRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_OutboundBallotKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryOutboundBallotKeyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).OutboundBallotKey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Query_OutboundBallotKey_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).OutboundBallotKey(ctx, req.(*QueryOutboundBallotKeyRequest)) + } + return interceptor(ctx, in, info, handler) +} + // Query_ServiceDesc is the grpc.ServiceDesc for Query service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -499,6 +577,14 @@ var Query_ServiceDesc = grpc.ServiceDesc{ MethodName: "AllExpiredInbounds", Handler: _Query_AllExpiredInbounds_Handler, }, + { + MethodName: "InboundKeys", + Handler: _Query_InboundKeys_Handler, + }, + { + MethodName: "OutboundBallotKey", + Handler: _Query_OutboundBallotKey_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "uexecutor/v1/query.proto", diff --git a/proto/uexecutor/v1/query.proto b/proto/uexecutor/v1/query.proto index 753204ac0..555d870ad 100755 --- a/proto/uexecutor/v1/query.proto +++ b/proto/uexecutor/v1/query.proto @@ -69,6 +69,22 @@ service Query { rpc AllExpiredInbounds(QueryAllExpiredInboundsRequest) returns (QueryAllExpiredInboundsResponse) { option (google.api.http).get = "/uexecutor/v1/expired_inbounds"; } + + // Derives the canonical UTX id and inbound ballot id for a given inbound, + // so off-chain validators read the keys from the chain instead of + // re-implementing the canonicalization + digest rules. + rpc InboundKeys(QueryInboundKeysRequest) returns (QueryInboundKeysResponse) { + option (google.api.http).post = "/uexecutor/v1/inbound_keys"; + option (google.api.http).body = "*"; + } + + // Derives the canonical outbound ballot id for a given observation. The + // observed tx hash is canonicalized against the outbound's destination + // chain (looked up by utx_id/outbound_id). + rpc OutboundBallotKey(QueryOutboundBallotKeyRequest) returns (QueryOutboundBallotKeyResponse) { + option (google.api.http).post = "/uexecutor/v1/outbound_ballot_key"; + option (google.api.http).body = "*"; + } } // ========================== @@ -195,3 +211,26 @@ message QueryAllPendingOutboundsResponse { repeated OutboundTx outbounds = 2; cosmos.base.query.v1beta1.PageResponse pagination = 3; } + +// InboundKeys: derive canonical UTX id + inbound ballot id from an inbound. +message QueryInboundKeysRequest { + Inbound inbound = 1; +} + +message QueryInboundKeysResponse { + string utx_id = 1; // canonical UniversalTx key + string ballot_id = 2; // canonical inbound ballot key + Inbound canonical_inbound = 3; // the canonicalized inbound the chain derived the keys from +} + +// OutboundBallotKey: derive the canonical outbound ballot id for an observation. +message QueryOutboundBallotKeyRequest { + string utx_id = 1; // UniversalTx the outbound belongs to + string outbound_id = 2; // outbound being observed + OutboundObservation observed_tx = 3; // the observation being voted +} + +message QueryOutboundBallotKeyResponse { + string ballot_id = 1; // canonical outbound ballot key + OutboundObservation canonical_observed_tx = 2; // observation after canonicalization +} diff --git a/test/integration/uexecutor/query_keys_test.go b/test/integration/uexecutor/query_keys_test.go new file mode 100644 index 000000000..a3512135a --- /dev/null +++ b/test/integration/uexecutor/query_keys_test.go @@ -0,0 +1,135 @@ +package integrationtest + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/require" + + uexecutorkeeper "github.com/pushchain/push-chain-node/x/uexecutor/keeper" + uexecutortypes "github.com/pushchain/push-chain-node/x/uexecutor/types" +) + +// The InboundKeys / OutboundBallotKey queries let off-chain validators read the +// canonical UTX id + ballot ids from the chain instead of re-implementing the +// canonicalization + digest rules. These tests exercise each query. + +func TestQueryInboundKeys_MatchesDerivation(t *testing.T) { + app, ctx, _, inbound, _ := setupInboundBridgeTest(t, 1) + q := uexecutorkeeper.NewQuerier(app.UexecutorKeeper) + + resp, err := q.InboundKeys(ctx, &uexecutortypes.QueryInboundKeysRequest{Inbound: inbound}) + require.NoError(t, err) + + // The returned keys must equal direct derivation from the canonical inbound. + canon := *inbound + canon.Canonicalize() + require.Equal(t, uexecutortypes.GetInboundUniversalTxKey(canon), resp.UtxId) + wantBallot, err := uexecutortypes.GetInboundBallotKey(canon) + require.NoError(t, err) + require.Equal(t, wantBallot, resp.BallotId) + + // Response echoes the canonical form the chain derived from. + require.NotNil(t, resp.CanonicalInbound) + require.Equal(t, canon.AssetAddr, resp.CanonicalInbound.AssetAddr) + require.Len(t, resp.UtxId, 64) + require.Len(t, resp.BallotId, 64) +} + +func TestQueryInboundKeys_EncodingVariantsAgree(t *testing.T) { + app, ctx, _, inbound, _ := setupInboundBridgeTest(t, 1) + q := uexecutorkeeper.NewQuerier(app.UexecutorKeeper) + + lower := *inbound + lower.AssetAddr = strings.ToLower(inbound.AssetAddr) + lower.Sender = strings.ToLower(inbound.Sender) + + upper := *inbound + upper.AssetAddr = "0X" + strings.ToUpper(strings.TrimPrefix(inbound.AssetAddr, "0x")) + + rl, err := q.InboundKeys(ctx, &uexecutortypes.QueryInboundKeysRequest{Inbound: &lower}) + require.NoError(t, err) + ru, err := q.InboundKeys(ctx, &uexecutortypes.QueryInboundKeysRequest{Inbound: &upper}) + require.NoError(t, err) + + require.Equal(t, rl.UtxId, ru.UtxId, "encoding variants must yield one UTX id") + require.Equal(t, rl.BallotId, ru.BallotId, "encoding variants must yield one ballot id") +} + +func TestQueryInboundKeys_NilRejected(t *testing.T) { + app, ctx, _, _, _ := setupInboundBridgeTest(t, 1) + q := uexecutorkeeper.NewQuerier(app.UexecutorKeeper) + + _, err := q.InboundKeys(ctx, &uexecutortypes.QueryInboundKeysRequest{Inbound: nil}) + require.Error(t, err) + require.Contains(t, err.Error(), "inbound is required") +} + +func TestQueryOutboundBallotKey_MatchesDerivation(t *testing.T) { + app, ctx, _, utxId, outbound, _ := setupOutboundVotingTest(t, 4) + q := uexecutorkeeper.NewQuerier(app.UexecutorKeeper) + + obs := &uexecutortypes.OutboundObservation{ + Success: true, + BlockHeight: 42, + TxHash: "0XB28F49668E7E76DC96D7AABE5B7F63FECFBD1C3574774C05E8204E749FD96FBD", // mixed/upper + GasFeeUsed: outbound.GasFee, + } + + resp, err := q.OutboundBallotKey(ctx, &uexecutortypes.QueryOutboundBallotKeyRequest{ + UtxId: utxId, + OutboundId: outbound.Id, + ObservedTx: obs, + }) + require.NoError(t, err) + + // Equals derivation from the canonicalized observation (lowercased hash). + canonObs := *obs + canonObs.TxHash = "0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd" + want, err := uexecutortypes.GetOutboundBallotKey(utxId, outbound.Id, canonObs) + require.NoError(t, err) + require.Equal(t, want, resp.BallotId) + + require.NotNil(t, resp.CanonicalObservedTx) + require.Equal(t, canonObs.TxHash, resp.CanonicalObservedTx.TxHash, "query returns the canonical hash") + require.Len(t, resp.BallotId, 64) +} + +func TestQueryOutboundBallotKey_EncodingVariantsAgree(t *testing.T) { + app, ctx, _, utxId, outbound, _ := setupOutboundVotingTest(t, 4) + q := uexecutorkeeper.NewQuerier(app.UexecutorKeeper) + + mk := func(hash string) *uexecutortypes.QueryOutboundBallotKeyRequest { + return &uexecutortypes.QueryOutboundBallotKeyRequest{ + UtxId: utxId, OutboundId: outbound.Id, + ObservedTx: &uexecutortypes.OutboundObservation{Success: true, BlockHeight: 7, TxHash: hash, GasFeeUsed: "100"}, + } + } + a, err := q.OutboundBallotKey(ctx, mk("0xb28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd")) + require.NoError(t, err) + b, err := q.OutboundBallotKey(ctx, mk("b28f49668e7e76dc96d7aabe5b7f63fecfbd1c3574774c05e8204e749fd96fbd")) // no 0x + require.NoError(t, err) + require.Equal(t, a.BallotId, b.BallotId, "encoding variants must yield one outbound ballot id") +} + +func TestQueryOutboundBallotKey_Errors(t *testing.T) { + app, ctx, _, utxId, outbound, _ := setupOutboundVotingTest(t, 4) + q := uexecutorkeeper.NewQuerier(app.UexecutorKeeper) + + obs := &uexecutortypes.OutboundObservation{Success: true, BlockHeight: 1, TxHash: "0xaa", GasFeeUsed: "1"} + + // nil observation + _, err := q.OutboundBallotKey(ctx, &uexecutortypes.QueryOutboundBallotKeyRequest{UtxId: utxId, OutboundId: outbound.Id}) + require.Error(t, err) + require.Contains(t, err.Error(), "observed_tx is required") + + // unknown utx + _, err = q.OutboundBallotKey(ctx, &uexecutortypes.QueryOutboundBallotKeyRequest{UtxId: "does-not-exist", OutboundId: outbound.Id, ObservedTx: obs}) + require.Error(t, err) + require.Contains(t, err.Error(), "not found") + + // known utx, unknown outbound + _, err = q.OutboundBallotKey(ctx, &uexecutortypes.QueryOutboundBallotKeyRequest{UtxId: utxId, OutboundId: "no-such-outbound", ObservedTx: obs}) + require.Error(t, err) + require.Contains(t, err.Error(), "not found") +} diff --git a/x/uexecutor/keeper/query_keys.go b/x/uexecutor/keeper/query_keys.go new file mode 100644 index 000000000..503c22678 --- /dev/null +++ b/x/uexecutor/keeper/query_keys.go @@ -0,0 +1,88 @@ +package keeper + +import ( + "context" + "strings" + + sdk "github.com/cosmos/cosmos-sdk/types" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/pushchain/push-chain-node/utils" + "github.com/pushchain/push-chain-node/x/uexecutor/types" +) + +// InboundKeys derives the canonical UTX id and inbound ballot id for the given +// inbound, applying the same canonicalization the vote path uses. Lets off-chain +// validators read the keys from the chain instead of re-implementing the rules. +func (k Querier) InboundKeys(goCtx context.Context, req *types.QueryInboundKeysRequest) (*types.QueryInboundKeysResponse, error) { + if req == nil || req.Inbound == nil { + return nil, status.Error(codes.InvalidArgument, "inbound is required") + } + + inbound := *req.Inbound + inbound.Canonicalize() + + ballotID, err := types.GetInboundBallotKey(inbound) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to derive inbound ballot key: %v", err) + } + + return &types.QueryInboundKeysResponse{ + UtxId: types.GetInboundUniversalTxKey(inbound), + BallotId: ballotID, + CanonicalInbound: &inbound, + }, nil +} + +// OutboundBallotKey derives the canonical outbound ballot id for the given +// observation. The observed tx hash is canonicalized against the outbound's +// destination chain, which is looked up from the stored UTX/outbound so the +// caller can't supply the wrong chain. +func (k Querier) OutboundBallotKey(goCtx context.Context, req *types.QueryOutboundBallotKeyRequest) (*types.QueryOutboundBallotKeyResponse, error) { + if req == nil || req.ObservedTx == nil { + return nil, status.Error(codes.InvalidArgument, "observed_tx is required") + } + if strings.TrimSpace(req.UtxId) == "" || strings.TrimSpace(req.OutboundId) == "" { + return nil, status.Error(codes.InvalidArgument, "utx_id and outbound_id are required") + } + + ctx := sdk.UnwrapSDKContext(goCtx) + // k.Keeper.GetUniversalTx (3 returns), not the shadowing Querier gRPC method. + utx, found, err := k.Keeper.GetUniversalTx(ctx, req.UtxId) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to load universal tx: %v", err) + } + if !found { + return nil, status.Errorf(codes.NotFound, "universal tx %s not found", req.UtxId) + } + + var destChain string + outboundFound := false + for _, ob := range utx.OutboundTx { + if ob.Id == req.OutboundId { + destChain = ob.DestinationChain + outboundFound = true + break + } + } + if !outboundFound { + return nil, status.Errorf(codes.NotFound, "outbound %s not found in universal tx %s", req.OutboundId, req.UtxId) + } + + // Mirror the canonicalization applied at vote ingress (msg_vote_outbound.go). + obs := *req.ObservedTx + obs.TxHash = utils.LenientCanonicalizeTxHash(destChain, obs.TxHash) + obs.GasFeeUsed = strings.TrimSpace(obs.GasFeeUsed) + obs.ErrorMsg = strings.TrimSpace(obs.ErrorMsg) + + ballotID, err := types.GetOutboundBallotKey(req.UtxId, req.OutboundId, obs) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to derive outbound ballot key: %v", err) + } + + return &types.QueryOutboundBallotKeyResponse{ + BallotId: ballotID, + CanonicalObservedTx: &obs, + }, nil +} diff --git a/x/uexecutor/types/query.pb.go b/x/uexecutor/types/query.pb.go index 1bc8c73f1..23c90fd8b 100644 --- a/x/uexecutor/types/query.pb.go +++ b/x/uexecutor/types/query.pb.go @@ -1149,6 +1149,224 @@ func (m *QueryAllPendingOutboundsResponse) GetPagination() *query.PageResponse { return nil } +// InboundKeys: derive canonical UTX id + inbound ballot id from an inbound. +type QueryInboundKeysRequest struct { + Inbound *Inbound `protobuf:"bytes,1,opt,name=inbound,proto3" json:"inbound,omitempty"` +} + +func (m *QueryInboundKeysRequest) Reset() { *m = QueryInboundKeysRequest{} } +func (m *QueryInboundKeysRequest) String() string { return proto.CompactTextString(m) } +func (*QueryInboundKeysRequest) ProtoMessage() {} +func (*QueryInboundKeysRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_94816af5d57d33a7, []int{23} +} +func (m *QueryInboundKeysRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryInboundKeysRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryInboundKeysRequest.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 *QueryInboundKeysRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryInboundKeysRequest.Merge(m, src) +} +func (m *QueryInboundKeysRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryInboundKeysRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryInboundKeysRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryInboundKeysRequest proto.InternalMessageInfo + +func (m *QueryInboundKeysRequest) GetInbound() *Inbound { + if m != nil { + return m.Inbound + } + return nil +} + +type QueryInboundKeysResponse struct { + UtxId string `protobuf:"bytes,1,opt,name=utx_id,json=utxId,proto3" json:"utx_id,omitempty"` + BallotId string `protobuf:"bytes,2,opt,name=ballot_id,json=ballotId,proto3" json:"ballot_id,omitempty"` + CanonicalInbound *Inbound `protobuf:"bytes,3,opt,name=canonical_inbound,json=canonicalInbound,proto3" json:"canonical_inbound,omitempty"` +} + +func (m *QueryInboundKeysResponse) Reset() { *m = QueryInboundKeysResponse{} } +func (m *QueryInboundKeysResponse) String() string { return proto.CompactTextString(m) } +func (*QueryInboundKeysResponse) ProtoMessage() {} +func (*QueryInboundKeysResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_94816af5d57d33a7, []int{24} +} +func (m *QueryInboundKeysResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryInboundKeysResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryInboundKeysResponse.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 *QueryInboundKeysResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryInboundKeysResponse.Merge(m, src) +} +func (m *QueryInboundKeysResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryInboundKeysResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryInboundKeysResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryInboundKeysResponse proto.InternalMessageInfo + +func (m *QueryInboundKeysResponse) GetUtxId() string { + if m != nil { + return m.UtxId + } + return "" +} + +func (m *QueryInboundKeysResponse) GetBallotId() string { + if m != nil { + return m.BallotId + } + return "" +} + +func (m *QueryInboundKeysResponse) GetCanonicalInbound() *Inbound { + if m != nil { + return m.CanonicalInbound + } + return nil +} + +// OutboundBallotKey: derive the canonical outbound ballot id for an observation. +type QueryOutboundBallotKeyRequest struct { + UtxId string `protobuf:"bytes,1,opt,name=utx_id,json=utxId,proto3" json:"utx_id,omitempty"` + OutboundId string `protobuf:"bytes,2,opt,name=outbound_id,json=outboundId,proto3" json:"outbound_id,omitempty"` + ObservedTx *OutboundObservation `protobuf:"bytes,3,opt,name=observed_tx,json=observedTx,proto3" json:"observed_tx,omitempty"` +} + +func (m *QueryOutboundBallotKeyRequest) Reset() { *m = QueryOutboundBallotKeyRequest{} } +func (m *QueryOutboundBallotKeyRequest) String() string { return proto.CompactTextString(m) } +func (*QueryOutboundBallotKeyRequest) ProtoMessage() {} +func (*QueryOutboundBallotKeyRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_94816af5d57d33a7, []int{25} +} +func (m *QueryOutboundBallotKeyRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryOutboundBallotKeyRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryOutboundBallotKeyRequest.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 *QueryOutboundBallotKeyRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryOutboundBallotKeyRequest.Merge(m, src) +} +func (m *QueryOutboundBallotKeyRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryOutboundBallotKeyRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryOutboundBallotKeyRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryOutboundBallotKeyRequest proto.InternalMessageInfo + +func (m *QueryOutboundBallotKeyRequest) GetUtxId() string { + if m != nil { + return m.UtxId + } + return "" +} + +func (m *QueryOutboundBallotKeyRequest) GetOutboundId() string { + if m != nil { + return m.OutboundId + } + return "" +} + +func (m *QueryOutboundBallotKeyRequest) GetObservedTx() *OutboundObservation { + if m != nil { + return m.ObservedTx + } + return nil +} + +type QueryOutboundBallotKeyResponse struct { + BallotId string `protobuf:"bytes,1,opt,name=ballot_id,json=ballotId,proto3" json:"ballot_id,omitempty"` + CanonicalObservedTx *OutboundObservation `protobuf:"bytes,2,opt,name=canonical_observed_tx,json=canonicalObservedTx,proto3" json:"canonical_observed_tx,omitempty"` +} + +func (m *QueryOutboundBallotKeyResponse) Reset() { *m = QueryOutboundBallotKeyResponse{} } +func (m *QueryOutboundBallotKeyResponse) String() string { return proto.CompactTextString(m) } +func (*QueryOutboundBallotKeyResponse) ProtoMessage() {} +func (*QueryOutboundBallotKeyResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_94816af5d57d33a7, []int{26} +} +func (m *QueryOutboundBallotKeyResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryOutboundBallotKeyResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryOutboundBallotKeyResponse.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 *QueryOutboundBallotKeyResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryOutboundBallotKeyResponse.Merge(m, src) +} +func (m *QueryOutboundBallotKeyResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryOutboundBallotKeyResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryOutboundBallotKeyResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryOutboundBallotKeyResponse proto.InternalMessageInfo + +func (m *QueryOutboundBallotKeyResponse) GetBallotId() string { + if m != nil { + return m.BallotId + } + return "" +} + +func (m *QueryOutboundBallotKeyResponse) GetCanonicalObservedTx() *OutboundObservation { + if m != nil { + return m.CanonicalObservedTx + } + return nil +} + func init() { proto.RegisterType((*QueryGasPriceRequest)(nil), "uexecutor.v1.QueryGasPriceRequest") proto.RegisterType((*QueryGasPriceResponse)(nil), "uexecutor.v1.QueryGasPriceResponse") @@ -1173,89 +1391,107 @@ func init() { proto.RegisterType((*QueryGetPendingOutboundResponse)(nil), "uexecutor.v1.QueryGetPendingOutboundResponse") proto.RegisterType((*QueryAllPendingOutboundsRequest)(nil), "uexecutor.v1.QueryAllPendingOutboundsRequest") proto.RegisterType((*QueryAllPendingOutboundsResponse)(nil), "uexecutor.v1.QueryAllPendingOutboundsResponse") + proto.RegisterType((*QueryInboundKeysRequest)(nil), "uexecutor.v1.QueryInboundKeysRequest") + proto.RegisterType((*QueryInboundKeysResponse)(nil), "uexecutor.v1.QueryInboundKeysResponse") + proto.RegisterType((*QueryOutboundBallotKeyRequest)(nil), "uexecutor.v1.QueryOutboundBallotKeyRequest") + proto.RegisterType((*QueryOutboundBallotKeyResponse)(nil), "uexecutor.v1.QueryOutboundBallotKeyResponse") } func init() { proto.RegisterFile("uexecutor/v1/query.proto", fileDescriptor_94816af5d57d33a7) } var fileDescriptor_94816af5d57d33a7 = []byte{ - // 1221 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xcf, 0x6f, 0xe3, 0xc4, - 0x17, 0xef, 0xa4, 0xfb, 0xa3, 0x79, 0xfd, 0xb1, 0x5f, 0xcd, 0xe6, 0x5b, 0x52, 0xb7, 0x4d, 0x53, - 0x77, 0x69, 0xb3, 0x4b, 0x6b, 0xab, 0xdd, 0xa5, 0xe2, 0x80, 0x90, 0xda, 0x65, 0xa9, 0x8a, 0x16, - 0x6d, 0x88, 0x16, 0x0e, 0x5c, 0xa2, 0x49, 0x3c, 0x72, 0x2d, 0x5a, 0x3b, 0x6b, 0x3b, 0x51, 0xaa, - 0xaa, 0x42, 0x80, 0xb8, 0x70, 0x01, 0xc4, 0x09, 0x21, 0xc4, 0x0d, 0xb8, 0xf0, 0x7f, 0xec, 0x71, - 0x25, 0x2e, 0x9c, 0x10, 0xb4, 0xfc, 0x0b, 0xdc, 0x51, 0xc6, 0x33, 0x8e, 0xc7, 0x19, 0xa7, 0x11, - 0x0a, 0xdc, 0x9c, 0x79, 0xef, 0xcd, 0xfb, 0x7c, 0xde, 0xcc, 0xfb, 0xcc, 0x4c, 0xa0, 0xd8, 0xa6, - 0x5d, 0xda, 0x6c, 0x87, 0x9e, 0x6f, 0x76, 0xb6, 0xcd, 0x67, 0x6d, 0xea, 0x9f, 0x1a, 0x2d, 0xdf, - 0x0b, 0x3d, 0x3c, 0x13, 0x5b, 0x8c, 0xce, 0xb6, 0x56, 0xb0, 0x3d, 0xdb, 0x63, 0x06, 0xb3, 0xf7, - 0x15, 0xf9, 0x68, 0x4b, 0xb6, 0xe7, 0xd9, 0xc7, 0xd4, 0x24, 0x2d, 0xc7, 0x24, 0xae, 0xeb, 0x85, - 0x24, 0x74, 0x3c, 0x37, 0xe0, 0x56, 0x79, 0xee, 0xf0, 0xb4, 0x45, 0x85, 0x65, 0x49, 0xb2, 0xd8, - 0x24, 0xa8, 0xb7, 0x7c, 0xa7, 0x49, 0xb9, 0x75, 0x59, 0xb2, 0x36, 0x8f, 0x88, 0xe3, 0xd6, 0x4f, - 0x68, 0x48, 0xb8, 0x59, 0x93, 0xcc, 0x2d, 0xea, 0x5a, 0x8e, 0x6b, 0x73, 0xdb, 0xbd, 0xa6, 0x17, - 0x9c, 0x78, 0x81, 0xd9, 0x20, 0x01, 0x8d, 0xd8, 0x98, 0x9d, 0xed, 0x06, 0x0d, 0xc9, 0xb6, 0xd9, - 0x22, 0xb6, 0xe3, 0x32, 0x7c, 0x91, 0xaf, 0xbe, 0x0d, 0x85, 0x77, 0x7b, 0x1e, 0x07, 0x24, 0xa8, - 0xf6, 0xb2, 0xd7, 0xe8, 0xb3, 0x36, 0x0d, 0x42, 0xbc, 0x00, 0x53, 0x51, 0x4e, 0xc7, 0x2a, 0xa2, - 0x32, 0xaa, 0xe4, 0x6b, 0x37, 0xd9, 0xef, 0x43, 0x4b, 0x7f, 0x0c, 0xff, 0x4f, 0x85, 0x04, 0x2d, - 0xcf, 0x0d, 0x28, 0xbe, 0x0f, 0xf9, 0x98, 0x05, 0x0b, 0x9a, 0xde, 0x99, 0x37, 0x92, 0x05, 0x34, - 0xe2, 0x90, 0x29, 0x9b, 0x7f, 0xe9, 0x0d, 0x28, 0xb2, 0xd9, 0xf6, 0x8e, 0x8f, 0x85, 0x35, 0x10, - 0x20, 0xde, 0x02, 0xe8, 0x03, 0xe6, 0x33, 0xae, 0x1b, 0x11, 0x3b, 0xa3, 0xc7, 0xce, 0x88, 0xd6, - 0x8a, 0xb3, 0x33, 0xaa, 0xc4, 0x16, 0x04, 0x6a, 0x89, 0x48, 0xfd, 0x5b, 0x04, 0x0b, 0x8a, 0x24, - 0x1c, 0xf6, 0xab, 0x00, 0x31, 0xec, 0xa0, 0x88, 0xca, 0x93, 0x43, 0x70, 0xe7, 0x05, 0xee, 0x00, - 0x1f, 0x48, 0xe0, 0x72, 0x0c, 0xdc, 0xc6, 0x95, 0xe0, 0xa2, 0x9c, 0x12, 0xba, 0x1d, 0x5e, 0xcf, - 0x87, 0xbd, 0xfa, 0xbe, 0x43, 0x43, 0x32, 0xc2, 0x1a, 0x54, 0x61, 0x3e, 0x1d, 0xc3, 0xd9, 0xec, - 0x02, 0xf4, 0x37, 0x0b, 0xaf, 0xd9, 0x4b, 0x32, 0x9b, 0x7e, 0x50, 0xbe, 0x29, 0x3e, 0xf5, 0x66, - 0xbf, 0x44, 0xb1, 0x7d, 0xec, 0x0b, 0xf1, 0x3d, 0x02, 0x4d, 0x95, 0x85, 0x63, 0x7f, 0x0d, 0xa6, - 0xfb, 0xd8, 0xc5, 0x52, 0x64, 0x82, 0x87, 0x18, 0xfc, 0x18, 0x17, 0xa3, 0x00, 0x98, 0x01, 0xac, - 0x12, 0x9f, 0x9c, 0x08, 0xfe, 0xfa, 0x43, 0xb8, 0x2d, 0x8d, 0x72, 0xbc, 0x9b, 0x70, 0xa3, 0xc5, - 0x46, 0x78, 0x49, 0x0a, 0x32, 0x54, 0xee, 0xcd, 0x7d, 0xf4, 0x23, 0x28, 0x09, 0xee, 0xd5, 0xa8, - 0x5f, 0x0f, 0xdd, 0x86, 0xd7, 0x76, 0xad, 0xb1, 0x97, 0xf9, 0x67, 0x04, 0x2b, 0x99, 0xa9, 0x38, - 0xf6, 0x3d, 0xb8, 0x49, 0xdd, 0xd0, 0x77, 0xe2, 0x2d, 0xbf, 0x9a, 0x02, 0x2f, 0xc5, 0x3d, 0x72, - 0x43, 0xff, 0x74, 0xff, 0xda, 0xf3, 0xdf, 0x56, 0x26, 0x6a, 0x22, 0x6e, 0x7c, 0x45, 0x4f, 0x54, - 0xe6, 0x51, 0xb7, 0xe5, 0xf8, 0xd4, 0xfa, 0x2f, 0x2a, 0x33, 0x90, 0x6a, 0xc4, 0xca, 0xc8, 0x71, - 0xff, 0x6e, 0x65, 0x36, 0x79, 0xbf, 0x1c, 0xd0, 0xf0, 0x3d, 0xd7, 0xe9, 0x50, 0x3f, 0x20, 0xc7, - 0x4f, 0xbb, 0xa2, 0x2a, 0x73, 0x90, 0x8b, 0xa5, 0x21, 0xe7, 0x58, 0x3a, 0x81, 0x45, 0xa5, 0x37, - 0x27, 0xb6, 0x0f, 0x33, 0x6d, 0x31, 0x5c, 0x0f, 0xbb, 0xbc, 0x8c, 0x2b, 0x32, 0xbb, 0x44, 0xe0, - 0x63, 0x6a, 0x93, 0xe6, 0x69, 0x6d, 0xba, 0xdd, 0x1f, 0xd2, 0xad, 0x7e, 0x03, 0x2b, 0x00, 0x8d, - 0x6b, 0x99, 0x7e, 0x40, 0x9c, 0x49, 0x3a, 0x0d, 0x67, 0xf2, 0x06, 0xcc, 0x26, 0x99, 0x88, 0x85, - 0x5a, 0xc8, 0xa4, 0x52, 0x9b, 0x49, 0x90, 0x18, 0xe3, 0xfa, 0xfc, 0x85, 0xa0, 0xc0, 0x3b, 0xe5, - 0x49, 0x3b, 0xec, 0x6f, 0x08, 0xbc, 0x02, 0xd3, 0x1e, 0x1f, 0xe8, 0xcb, 0x37, 0x88, 0xa1, 0x43, - 0x0b, 0xaf, 0xc3, 0xad, 0x24, 0x85, 0x9e, 0x53, 0x8e, 0x39, 0xcd, 0x26, 0x90, 0x1e, 0x5a, 0x78, - 0x19, 0xa0, 0xe9, 0x53, 0x12, 0x52, 0xab, 0x4e, 0xc2, 0xe2, 0x64, 0x19, 0x55, 0x26, 0x6b, 0x79, - 0x3e, 0xb2, 0x17, 0xe2, 0xbb, 0xf0, 0xbf, 0xc0, 0xb1, 0x5d, 0xc7, 0xb5, 0xeb, 0x16, 0x25, 0xd6, - 0xb1, 0xe3, 0xd2, 0xe2, 0x35, 0xe6, 0x74, 0x8b, 0x8f, 0xbf, 0xc9, 0x87, 0xf1, 0xdb, 0x30, 0xd5, - 0x21, 0xbe, 0x43, 0xdc, 0x30, 0x28, 0x5e, 0x67, 0xf5, 0xaa, 0xc8, 0xf5, 0x12, 0x0c, 0x9e, 0x34, - 0x02, 0xea, 0x77, 0x18, 0xc1, 0xf7, 0xa3, 0x00, 0xbe, 0xbf, 0xe3, 0x78, 0x7d, 0x8f, 0x77, 0xec, - 0x01, 0x0d, 0x53, 0xf4, 0xc5, 0x56, 0xb8, 0xaa, 0x00, 0xfa, 0x57, 0xa2, 0x15, 0x55, 0x73, 0xc4, - 0x07, 0xc2, 0xf5, 0x5e, 0x4b, 0x9d, 0xf2, 0xad, 0xa4, 0x2b, 0x25, 0x4a, 0x2a, 0x7c, 0x2d, 0x0a, - 0xc0, 0x0f, 0x60, 0x4a, 0xe4, 0xe2, 0xeb, 0x5b, 0x54, 0x93, 0x7d, 0xda, 0xad, 0xc5, 0x9e, 0xba, - 0x33, 0xa0, 0x9b, 0xc2, 0x6d, 0xec, 0x4a, 0xf4, 0x07, 0x82, 0x72, 0x76, 0x2e, 0xce, 0xff, 0xf5, - 0xb4, 0x14, 0x8d, 0x52, 0x81, 0x58, 0x85, 0x76, 0x21, 0x2f, 0x98, 0x05, 0xc5, 0x1c, 0x8b, 0xcf, - 0x2e, 0x42, 0xdf, 0x35, 0xd5, 0x1d, 0x93, 0xff, 0xb8, 0x3b, 0x76, 0x7e, 0x9a, 0x81, 0xeb, 0x8c, - 0x23, 0xfe, 0x10, 0x6e, 0x44, 0xa7, 0x21, 0x2e, 0xcb, 0x08, 0x06, 0x0f, 0x5b, 0x6d, 0x75, 0x88, - 0x47, 0x94, 0x44, 0x5f, 0xfa, 0xe4, 0x97, 0x3f, 0xbf, 0xce, 0xcd, 0xe3, 0x82, 0x29, 0x5f, 0x83, - 0xa3, 0x14, 0xdf, 0x20, 0xc0, 0x83, 0x27, 0x1f, 0xde, 0x54, 0xcc, 0x9b, 0x79, 0x16, 0x6b, 0x5b, - 0x23, 0x7a, 0x73, 0x44, 0xeb, 0x0c, 0x51, 0x19, 0x97, 0x4c, 0xd5, 0xc5, 0xbc, 0xee, 0x08, 0x10, - 0x5f, 0x20, 0x98, 0x93, 0xe5, 0x19, 0x57, 0x14, 0x99, 0x94, 0x7a, 0xaf, 0xdd, 0x1d, 0xc1, 0x93, - 0xe3, 0xa9, 0x30, 0x3c, 0x3a, 0x2e, 0xcb, 0x78, 0x24, 0xd5, 0x34, 0xcf, 0x1c, 0xeb, 0x1c, 0x7f, - 0x8e, 0x60, 0x4e, 0x96, 0x59, 0x25, 0x22, 0xa5, 0xe0, 0x2b, 0x11, 0xa9, 0x35, 0x5b, 0x5f, 0x63, - 0x88, 0x96, 0xf1, 0xe2, 0x10, 0x44, 0xf8, 0x23, 0x98, 0x12, 0x77, 0x6d, 0xac, 0xab, 0xd8, 0xca, - 0xcf, 0x14, 0x6d, 0x6d, 0xa8, 0x0f, 0xcf, 0x7c, 0x8f, 0x65, 0xbe, 0x83, 0x75, 0x53, 0xfd, 0xe2, - 0x32, 0xcf, 0xc4, 0x35, 0xfb, 0x1c, 0x7f, 0x8c, 0x60, 0x26, 0xf9, 0x4a, 0xc0, 0xeb, 0x6a, 0x86, - 0xe9, 0xb7, 0x8a, 0xb6, 0x71, 0xa5, 0x1f, 0x47, 0x53, 0x66, 0x68, 0x34, 0x5c, 0xcc, 0x40, 0x13, - 0xe0, 0x4f, 0x11, 0xe4, 0xe3, 0x6b, 0x2e, 0x56, 0x51, 0x4c, 0x3f, 0x15, 0xb4, 0x3b, 0xc3, 0x9d, - 0x78, 0xea, 0x57, 0x58, 0xea, 0x97, 0xf1, 0x9a, 0x99, 0xf1, 0xb8, 0x4c, 0x56, 0xe2, 0x33, 0x04, - 0xb3, 0xd2, 0x35, 0x1d, 0x67, 0x50, 0x1c, 0x78, 0x2e, 0x68, 0x95, 0xab, 0x1d, 0x39, 0xa2, 0x55, - 0x86, 0x68, 0x11, 0x2f, 0x64, 0x21, 0x0a, 0xf0, 0x8f, 0x08, 0xf0, 0xe0, 0x11, 0xa1, 0xec, 0xe6, - 0xcc, 0xd3, 0x48, 0xd9, 0xcd, 0xd9, 0xe7, 0x8e, 0xfe, 0x80, 0xc1, 0x32, 0xf0, 0xa6, 0xba, 0x9b, - 0x85, 0x54, 0x9a, 0x67, 0x89, 0x23, 0xee, 0x1c, 0x7f, 0x87, 0xe0, 0xb6, 0x42, 0xcd, 0xf1, 0x70, - 0x29, 0x49, 0x9f, 0x30, 0x9a, 0x31, 0xaa, 0x3b, 0x07, 0xbb, 0xc1, 0xc0, 0xae, 0xe2, 0x95, 0xe1, - 0x60, 0x63, 0x5d, 0x4c, 0xdd, 0x7b, 0xb3, 0x74, 0x51, 0x7d, 0x13, 0xcf, 0xd2, 0xc5, 0x8c, 0xcb, - 0x74, 0x96, 0x2e, 0xd2, 0xc8, 0x3d, 0xd6, 0xc5, 0xfd, 0xea, 0xf3, 0x8b, 0x12, 0x7a, 0x71, 0x51, - 0x42, 0xbf, 0x5f, 0x94, 0xd0, 0x97, 0x97, 0xa5, 0x89, 0x17, 0x97, 0xa5, 0x89, 0x5f, 0x2f, 0x4b, - 0x13, 0x1f, 0xec, 0xda, 0x4e, 0x78, 0xd4, 0x6e, 0x18, 0x4d, 0xef, 0xc4, 0x6c, 0xb5, 0x83, 0x23, - 0xb6, 0x37, 0xd8, 0xd7, 0x16, 0xfb, 0xdc, 0x72, 0x3d, 0x8b, 0x9a, 0xdd, 0xc4, 0xfc, 0xec, 0x4f, - 0x96, 0xc6, 0x0d, 0xf6, 0x07, 0xc7, 0xfd, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x05, 0xd4, 0xf0, - 0x65, 0xdd, 0x11, 0x00, 0x00, + // 1448 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x98, 0x4f, 0x6f, 0x13, 0x47, + 0x14, 0xc0, 0x33, 0x0e, 0x09, 0xf1, 0x4b, 0x08, 0x30, 0x24, 0xe0, 0x6c, 0x88, 0xe3, 0x2c, 0x10, + 0x02, 0x04, 0xaf, 0x02, 0x14, 0x55, 0x55, 0x55, 0x29, 0xa1, 0x34, 0x0a, 0x50, 0x91, 0x5a, 0xd0, + 0x43, 0x2f, 0xd6, 0xda, 0x3b, 0xda, 0xac, 0x70, 0x76, 0x8d, 0x77, 0x1d, 0xd9, 0x42, 0xa8, 0x6a, + 0x51, 0x2f, 0xbd, 0xf4, 0xef, 0xa5, 0x6a, 0xab, 0xde, 0xda, 0x53, 0xbf, 0x07, 0x97, 0x4a, 0x48, + 0xbd, 0xf4, 0x54, 0xb5, 0xd0, 0xaf, 0xd0, 0x7b, 0xe5, 0xd9, 0x37, 0xbb, 0x3b, 0xeb, 0x59, 0xc7, + 0xaa, 0xdc, 0xde, 0xd6, 0x33, 0xef, 0xcd, 0xfb, 0xbd, 0x37, 0xf3, 0xde, 0xcc, 0x33, 0x14, 0xda, + 0xac, 0xc3, 0xea, 0xed, 0xc0, 0x6b, 0x19, 0x07, 0x1b, 0xc6, 0xe3, 0x36, 0x6b, 0x75, 0xcb, 0xcd, + 0x96, 0x17, 0x78, 0x74, 0x26, 0x9a, 0x29, 0x1f, 0x6c, 0x68, 0x73, 0xb6, 0x67, 0x7b, 0x7c, 0xc2, + 0xe8, 0x7d, 0x85, 0x32, 0xda, 0x59, 0xdb, 0xf3, 0xec, 0x06, 0x33, 0xcc, 0xa6, 0x63, 0x98, 0xae, + 0xeb, 0x05, 0x66, 0xe0, 0x78, 0xae, 0x8f, 0xb3, 0xf2, 0xda, 0x41, 0xb7, 0xc9, 0xc4, 0xcc, 0x59, + 0x69, 0xc6, 0x36, 0xfd, 0x6a, 0xb3, 0xe5, 0xd4, 0x19, 0xce, 0x2e, 0x49, 0xb3, 0xf5, 0x3d, 0xd3, + 0x71, 0xab, 0xfb, 0x2c, 0x30, 0x71, 0x5a, 0x93, 0xa6, 0x9b, 0xcc, 0xb5, 0x1c, 0xd7, 0xc6, 0xb9, + 0xcb, 0x75, 0xcf, 0xdf, 0xf7, 0x7c, 0xa3, 0x66, 0xfa, 0x2c, 0xf4, 0xc6, 0x38, 0xd8, 0xa8, 0xb1, + 0xc0, 0xdc, 0x30, 0x9a, 0xa6, 0xed, 0xb8, 0x9c, 0x2f, 0x94, 0xd5, 0x37, 0x60, 0xee, 0xbd, 0x9e, + 0xc4, 0xb6, 0xe9, 0xef, 0xf6, 0xac, 0x57, 0xd8, 0xe3, 0x36, 0xf3, 0x03, 0xba, 0x00, 0x53, 0xa1, + 0x4d, 0xc7, 0x2a, 0x90, 0x12, 0x59, 0xcb, 0x57, 0x8e, 0xf2, 0xdf, 0x3b, 0x96, 0x7e, 0x0f, 0xe6, + 0x53, 0x2a, 0x7e, 0xd3, 0x73, 0x7d, 0x46, 0xaf, 0x43, 0x3e, 0xf2, 0x82, 0x2b, 0x4d, 0x5f, 0x3b, + 0x5d, 0x4e, 0x06, 0xb0, 0x1c, 0xa9, 0x4c, 0xd9, 0xf8, 0xa5, 0xd7, 0xa0, 0xc0, 0x57, 0xdb, 0x6c, + 0x34, 0xc4, 0xac, 0x2f, 0x20, 0xde, 0x01, 0x88, 0x81, 0x71, 0xc5, 0xd5, 0x72, 0xe8, 0x5d, 0xb9, + 0xe7, 0x5d, 0x39, 0xdc, 0x2b, 0xf4, 0xae, 0xbc, 0x6b, 0xda, 0xc2, 0x81, 0x4a, 0x42, 0x53, 0xff, + 0x96, 0xc0, 0x82, 0xc2, 0x08, 0x62, 0xbf, 0x06, 0x10, 0x61, 0xfb, 0x05, 0x52, 0x1a, 0x1f, 0xc0, + 0x9d, 0x17, 0xdc, 0x3e, 0xdd, 0x96, 0xe0, 0x72, 0x1c, 0xee, 0xe2, 0xa1, 0x70, 0xa1, 0x4d, 0x89, + 0xee, 0x1a, 0xc6, 0xf3, 0x56, 0x2f, 0xbe, 0xef, 0xb2, 0xc0, 0x1c, 0x62, 0x0f, 0x76, 0xe1, 0x74, + 0x5a, 0x07, 0xbd, 0xb9, 0x09, 0x10, 0x1f, 0x16, 0x8c, 0xd9, 0x19, 0xd9, 0x9b, 0x58, 0x29, 0x5f, + 0x17, 0x9f, 0x7a, 0x3d, 0x0e, 0x51, 0x34, 0x3f, 0xf2, 0x8d, 0xf8, 0x81, 0x80, 0xa6, 0xb2, 0x82, + 0xec, 0xaf, 0xc3, 0x74, 0xcc, 0x2e, 0xb6, 0x22, 0x13, 0x1e, 0x22, 0xf8, 0x11, 0x6e, 0xc6, 0x1c, + 0x50, 0x0e, 0xb8, 0x6b, 0xb6, 0xcc, 0x7d, 0xe1, 0xbf, 0x7e, 0x0b, 0x4e, 0x49, 0xa3, 0xc8, 0xbb, + 0x0e, 0x93, 0x4d, 0x3e, 0x82, 0x21, 0x99, 0x93, 0x51, 0x51, 0x1a, 0x65, 0xf4, 0x3d, 0x28, 0x0a, + 0xdf, 0x77, 0xc3, 0x7c, 0xdd, 0x71, 0x6b, 0x5e, 0xdb, 0xb5, 0x46, 0x1e, 0xe6, 0x9f, 0x09, 0x2c, + 0x67, 0x9a, 0x42, 0xf6, 0x4d, 0x38, 0xca, 0xdc, 0xa0, 0xe5, 0x44, 0x47, 0x7e, 0x25, 0x05, 0x2f, + 0xe9, 0xdd, 0x76, 0x83, 0x56, 0x77, 0xeb, 0xc8, 0xf3, 0xdf, 0x97, 0xc7, 0x2a, 0x42, 0x6f, 0x74, + 0x41, 0x4f, 0x44, 0xe6, 0x76, 0xa7, 0xe9, 0xb4, 0x98, 0xf5, 0x7f, 0x44, 0xa6, 0xcf, 0xd4, 0x90, + 0x91, 0x91, 0xf5, 0xfe, 0xdb, 0xc8, 0xac, 0x63, 0xbe, 0x6c, 0xb3, 0xe0, 0xa1, 0xeb, 0x1c, 0xb0, + 0x96, 0x6f, 0x36, 0x1e, 0x74, 0x44, 0x54, 0x66, 0x21, 0x17, 0x95, 0x86, 0x9c, 0x63, 0xe9, 0x26, + 0x2c, 0x2a, 0xa5, 0xd1, 0xb1, 0x2d, 0x98, 0x69, 0x8b, 0xe1, 0x6a, 0xd0, 0xc1, 0x30, 0x2e, 0xcb, + 0xde, 0x25, 0x14, 0xef, 0x31, 0xdb, 0xac, 0x77, 0x2b, 0xd3, 0xed, 0x78, 0x48, 0xb7, 0xe2, 0x04, + 0x56, 0x00, 0x8d, 0x6a, 0x9b, 0x7e, 0x24, 0xe8, 0x49, 0xda, 0x0c, 0x7a, 0xf2, 0x16, 0x1c, 0x4b, + 0x7a, 0x22, 0x36, 0x6a, 0x21, 0xd3, 0x95, 0xca, 0x4c, 0xc2, 0x89, 0x11, 0xee, 0xcf, 0xdf, 0x04, + 0xe6, 0x30, 0x53, 0xee, 0xb7, 0x83, 0xf8, 0x40, 0xd0, 0x65, 0x98, 0xf6, 0x70, 0x20, 0x2e, 0xdf, + 0x20, 0x86, 0x76, 0x2c, 0xba, 0x0a, 0xc7, 0x93, 0x2e, 0xf4, 0x84, 0x72, 0x5c, 0xe8, 0x58, 0x82, + 0x74, 0xc7, 0xa2, 0x4b, 0x00, 0xf5, 0x16, 0x33, 0x03, 0x66, 0x55, 0xcd, 0xa0, 0x30, 0x5e, 0x22, + 0x6b, 0xe3, 0x95, 0x3c, 0x8e, 0x6c, 0x06, 0xf4, 0x12, 0x9c, 0xf0, 0x1d, 0xdb, 0x75, 0x5c, 0xbb, + 0x6a, 0x31, 0xd3, 0x6a, 0x38, 0x2e, 0x2b, 0x1c, 0xe1, 0x42, 0xc7, 0x71, 0xfc, 0x6d, 0x1c, 0xa6, + 0x77, 0x60, 0xea, 0xc0, 0x6c, 0x39, 0xa6, 0x1b, 0xf8, 0x85, 0x09, 0x1e, 0xaf, 0x35, 0x39, 0x5e, + 0xc2, 0x83, 0xfb, 0x35, 0x9f, 0xb5, 0x0e, 0xb8, 0x83, 0xef, 0x87, 0x0a, 0x78, 0xbe, 0x23, 0x7d, + 0x7d, 0x13, 0x33, 0x76, 0x9b, 0x05, 0x29, 0xf7, 0xc5, 0x51, 0x38, 0x2c, 0x00, 0xfa, 0x17, 0x22, + 0x15, 0x55, 0x6b, 0x44, 0x17, 0xc2, 0x44, 0x2f, 0xa5, 0xba, 0x78, 0x94, 0x74, 0x65, 0x89, 0x92, + 0x02, 0x5f, 0x09, 0x15, 0xe8, 0x0d, 0x98, 0x12, 0xb6, 0x70, 0x7f, 0x0b, 0x6a, 0x67, 0x1f, 0x74, + 0x2a, 0x91, 0xa4, 0xee, 0xf4, 0xd5, 0x4d, 0x21, 0x36, 0xf2, 0x4a, 0xf4, 0x27, 0x81, 0x52, 0xb6, + 0x2d, 0xf4, 0xff, 0xcd, 0x74, 0x29, 0x1a, 0x26, 0x02, 0x51, 0x15, 0xba, 0x09, 0x79, 0xe1, 0x99, + 0x5f, 0xc8, 0x71, 0xfd, 0xec, 0x20, 0xc4, 0xa2, 0xa9, 0xec, 0x18, 0xff, 0xf7, 0xd9, 0x71, 0x07, + 0xce, 0x70, 0x17, 0xb1, 0x54, 0xde, 0x65, 0xdd, 0x28, 0x8c, 0x06, 0x1c, 0x75, 0xc2, 0x51, 0x8c, + 0xe1, 0xbc, 0x4c, 0x86, 0x2a, 0x15, 0x21, 0xa5, 0x7f, 0x49, 0xf0, 0xa1, 0x28, 0x2d, 0x86, 0x71, + 0x9a, 0x87, 0xc9, 0x76, 0x98, 0x43, 0xe1, 0x39, 0x9b, 0x68, 0x07, 0xbd, 0xdc, 0x59, 0x84, 0x7c, + 0xcd, 0x6c, 0x34, 0xbc, 0x20, 0xce, 0xae, 0xa9, 0x70, 0x60, 0xc7, 0xa2, 0x5b, 0x70, 0xb2, 0x6e, + 0xba, 0x9e, 0xeb, 0xd4, 0xcd, 0x46, 0x55, 0xb0, 0x8c, 0x0f, 0x62, 0x39, 0x11, 0xc9, 0xe3, 0x48, + 0xef, 0x61, 0xb9, 0xc4, 0xa1, 0x44, 0x20, 0xb7, 0xf8, 0xea, 0x77, 0x59, 0x57, 0xf8, 0x99, 0x41, + 0x96, 0xca, 0x8e, 0x5c, 0x5f, 0x79, 0xd8, 0x82, 0x69, 0x8f, 0xa7, 0x21, 0xb3, 0x7a, 0xa5, 0x3a, + 0xe4, 0x5a, 0x39, 0x34, 0x5f, 0x2b, 0x20, 0xb4, 0x1e, 0x74, 0xf4, 0xaf, 0x09, 0x66, 0xa9, 0x82, + 0x0e, 0x03, 0x27, 0x45, 0x88, 0xa4, 0x22, 0xf4, 0x10, 0xe6, 0xe3, 0x08, 0x25, 0x69, 0x72, 0xc3, + 0xd2, 0x9c, 0x8a, 0xf4, 0xef, 0x47, 0x58, 0xd7, 0x7e, 0x99, 0x85, 0x09, 0x8e, 0x45, 0x1f, 0xc1, + 0x64, 0xf8, 0x46, 0xa2, 0x25, 0x79, 0xad, 0xfe, 0x27, 0x98, 0xb6, 0x32, 0x40, 0x22, 0x74, 0x46, + 0x3f, 0xfb, 0xf1, 0xaf, 0x7f, 0x7d, 0x95, 0x3b, 0x4d, 0xe7, 0x0c, 0xb9, 0x39, 0x0a, 0x4d, 0x7c, + 0x43, 0x80, 0xf6, 0xbf, 0x87, 0xe8, 0xba, 0x62, 0xdd, 0xcc, 0x17, 0x9a, 0x76, 0x75, 0x48, 0x69, + 0x24, 0x5a, 0xe5, 0x44, 0x25, 0x5a, 0x34, 0x54, 0xed, 0x9a, 0x38, 0x75, 0x3e, 0xfd, 0x8c, 0xc0, + 0xac, 0x7c, 0x69, 0xd3, 0x35, 0x85, 0x25, 0xe5, 0x2b, 0x40, 0xbb, 0x34, 0x84, 0x24, 0xf2, 0xac, + 0x71, 0x1e, 0x9d, 0x96, 0x64, 0x1e, 0xe9, 0x2e, 0x35, 0x9e, 0x38, 0xd6, 0x53, 0xfa, 0x29, 0x81, + 0x59, 0xf9, 0xf2, 0x55, 0x12, 0x29, 0x9f, 0x01, 0x4a, 0x22, 0xf5, 0x4d, 0xae, 0x9f, 0xe3, 0x44, + 0x4b, 0x74, 0x71, 0x00, 0x11, 0xfd, 0x10, 0xa6, 0x44, 0x07, 0x46, 0x75, 0x95, 0xb7, 0x72, 0xf3, + 0xaa, 0x9d, 0x1b, 0x28, 0x83, 0x96, 0x2f, 0x73, 0xcb, 0xe7, 0xa9, 0x6e, 0xa8, 0xfb, 0x70, 0xe3, + 0x89, 0x68, 0xbe, 0x9e, 0xd2, 0x8f, 0x08, 0xcc, 0x24, 0x7b, 0x47, 0xba, 0xaa, 0xf6, 0x30, 0xdd, + 0xc1, 0x6a, 0x17, 0x0f, 0x95, 0x43, 0x9a, 0x12, 0xa7, 0xd1, 0x68, 0x21, 0x83, 0xc6, 0xa7, 0xcf, + 0x08, 0xe4, 0xa3, 0xe6, 0x87, 0xaa, 0x5c, 0x4c, 0x37, 0x90, 0xda, 0xf9, 0xc1, 0x42, 0x68, 0xfa, + 0x0a, 0x37, 0x7d, 0x81, 0x9e, 0x33, 0x32, 0xfe, 0x72, 0x48, 0x46, 0xe2, 0x13, 0x02, 0xc7, 0xa4, + 0xe6, 0x8d, 0x66, 0xb8, 0xd8, 0xd7, 0x44, 0x6a, 0x6b, 0x87, 0x0b, 0x22, 0xd1, 0x0a, 0x27, 0x5a, + 0xa4, 0x0b, 0x59, 0x44, 0x3e, 0xfd, 0x89, 0x00, 0xed, 0x7f, 0x38, 0x28, 0xb3, 0x39, 0xf3, 0x8d, + 0xa2, 0xcc, 0xe6, 0xec, 0xd7, 0x88, 0x7e, 0x83, 0x63, 0x95, 0xe9, 0xba, 0x3a, 0x9b, 0x45, 0xf5, + 0x36, 0x9e, 0x24, 0x4a, 0xfb, 0x53, 0xfa, 0x3d, 0x81, 0x53, 0x8a, 0x3b, 0x9e, 0x0e, 0x2e, 0x25, + 0xe9, 0x77, 0x87, 0x56, 0x1e, 0x56, 0x1c, 0x61, 0x2f, 0x72, 0xd8, 0x15, 0xba, 0x3c, 0x18, 0x36, + 0xaa, 0x8b, 0xa9, 0x6e, 0x28, 0xab, 0x2e, 0xaa, 0xfb, 0xb3, 0xac, 0xba, 0x98, 0xd1, 0x62, 0x65, + 0xd5, 0x45, 0x16, 0x8a, 0xc7, 0x75, 0xf1, 0x19, 0x81, 0xe9, 0xc4, 0x7d, 0x4f, 0x2f, 0x28, 0xcc, + 0xf4, 0x3f, 0x2e, 0xb4, 0xd5, 0xc3, 0xc4, 0x10, 0xe3, 0x02, 0xc7, 0x58, 0x7e, 0x83, 0x5c, 0xd6, + 0x35, 0x99, 0x04, 0x09, 0xaa, 0x8f, 0x7a, 0x56, 0xbf, 0x23, 0x70, 0xb2, 0xef, 0x0a, 0xa5, 0x57, + 0x14, 0x46, 0xb2, 0x9e, 0x01, 0xda, 0xfa, 0x70, 0xc2, 0xc8, 0xb5, 0xce, 0xb9, 0x56, 0x7b, 0x5c, + 0x2b, 0x32, 0x57, 0x74, 0xb2, 0xf0, 0xd6, 0x7e, 0xc4, 0xba, 0x5b, 0xbb, 0xcf, 0x5f, 0x16, 0xc9, + 0x8b, 0x97, 0x45, 0xf2, 0xc7, 0xcb, 0x22, 0xf9, 0xfc, 0x55, 0x71, 0xec, 0xc5, 0xab, 0xe2, 0xd8, + 0x6f, 0xaf, 0x8a, 0x63, 0x1f, 0xdc, 0xb4, 0x9d, 0x60, 0xaf, 0x5d, 0x2b, 0xd7, 0xbd, 0x7d, 0xa3, + 0xd9, 0xf6, 0xf7, 0x78, 0x02, 0xf1, 0xaf, 0xab, 0xfc, 0xf3, 0xaa, 0xeb, 0x59, 0xcc, 0xe8, 0x24, + 0x4c, 0xf0, 0xff, 0x27, 0x6b, 0x93, 0xfc, 0xbf, 0xc1, 0xeb, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, + 0xc5, 0x9c, 0xf1, 0x29, 0x18, 0x15, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1294,6 +1530,14 @@ type QueryClient interface { // inbounds whose ballots all reached EXPIRED/REJECTED without producing // a UniversalTx). Consumed by the future escape-hatch refund flow. AllExpiredInbounds(ctx context.Context, in *QueryAllExpiredInboundsRequest, opts ...grpc.CallOption) (*QueryAllExpiredInboundsResponse, error) + // Derives the canonical UTX id and inbound ballot id for a given inbound, + // so off-chain validators read the keys from the chain instead of + // re-implementing the canonicalization + digest rules. + InboundKeys(ctx context.Context, in *QueryInboundKeysRequest, opts ...grpc.CallOption) (*QueryInboundKeysResponse, error) + // Derives the canonical outbound ballot id for a given observation. The + // observed tx hash is canonicalized against the outbound's destination + // chain (looked up by utx_id/outbound_id). + OutboundBallotKey(ctx context.Context, in *QueryOutboundBallotKeyRequest, opts ...grpc.CallOption) (*QueryOutboundBallotKeyResponse, error) } type queryClient struct { @@ -1403,6 +1647,24 @@ func (c *queryClient) AllExpiredInbounds(ctx context.Context, in *QueryAllExpire return out, nil } +func (c *queryClient) InboundKeys(ctx context.Context, in *QueryInboundKeysRequest, opts ...grpc.CallOption) (*QueryInboundKeysResponse, error) { + out := new(QueryInboundKeysResponse) + err := c.cc.Invoke(ctx, "/uexecutor.v1.Query/InboundKeys", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) OutboundBallotKey(ctx context.Context, in *QueryOutboundBallotKeyRequest, opts ...grpc.CallOption) (*QueryOutboundBallotKeyResponse, error) { + out := new(QueryOutboundBallotKeyResponse) + err := c.cc.Invoke(ctx, "/uexecutor.v1.Query/OutboundBallotKey", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { // Params queries all parameters of the module. @@ -1429,6 +1691,14 @@ type QueryServer interface { // inbounds whose ballots all reached EXPIRED/REJECTED without producing // a UniversalTx). Consumed by the future escape-hatch refund flow. AllExpiredInbounds(context.Context, *QueryAllExpiredInboundsRequest) (*QueryAllExpiredInboundsResponse, error) + // Derives the canonical UTX id and inbound ballot id for a given inbound, + // so off-chain validators read the keys from the chain instead of + // re-implementing the canonicalization + digest rules. + InboundKeys(context.Context, *QueryInboundKeysRequest) (*QueryInboundKeysResponse, error) + // Derives the canonical outbound ballot id for a given observation. The + // observed tx hash is canonicalized against the outbound's destination + // chain (looked up by utx_id/outbound_id). + OutboundBallotKey(context.Context, *QueryOutboundBallotKeyRequest) (*QueryOutboundBallotKeyResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -1468,6 +1738,12 @@ func (*UnimplementedQueryServer) AllPendingOutbounds(ctx context.Context, req *Q func (*UnimplementedQueryServer) AllExpiredInbounds(ctx context.Context, req *QueryAllExpiredInboundsRequest) (*QueryAllExpiredInboundsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method AllExpiredInbounds not implemented") } +func (*UnimplementedQueryServer) InboundKeys(ctx context.Context, req *QueryInboundKeysRequest) (*QueryInboundKeysResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method InboundKeys not implemented") +} +func (*UnimplementedQueryServer) OutboundBallotKey(ctx context.Context, req *QueryOutboundBallotKeyRequest) (*QueryOutboundBallotKeyResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method OutboundBallotKey not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -1671,6 +1947,42 @@ func _Query_AllExpiredInbounds_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +func _Query_InboundKeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryInboundKeysRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).InboundKeys(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/uexecutor.v1.Query/InboundKeys", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).InboundKeys(ctx, req.(*QueryInboundKeysRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_OutboundBallotKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryOutboundBallotKeyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).OutboundBallotKey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/uexecutor.v1.Query/OutboundBallotKey", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).OutboundBallotKey(ctx, req.(*QueryOutboundBallotKeyRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "uexecutor.v1.Query", HandlerType: (*QueryServer)(nil), @@ -1719,6 +2031,14 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "AllExpiredInbounds", Handler: _Query_AllExpiredInbounds_Handler, }, + { + MethodName: "InboundKeys", + Handler: _Query_InboundKeys_Handler, + }, + { + MethodName: "OutboundBallotKey", + Handler: _Query_OutboundBallotKey_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "uexecutor/v1/query.proto", @@ -2633,69 +2953,244 @@ func (m *QueryAllPendingOutboundsResponse) MarshalToSizedBuffer(dAtA []byte) (in 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++ +func (m *QueryInboundKeysRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err } - dAtA[offset] = uint8(v) - return base + return dAtA[:n], nil } -func (m *QueryGasPriceRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ChainId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - return n + +func (m *QueryInboundKeysRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *QueryGasPriceResponse) Size() (n int) { - if m == nil { - return 0 - } +func (m *QueryInboundKeysRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i var l int _ = l - if m.GasPrice != nil { - l = m.GasPrice.Size() - n += 1 + l + sovQuery(uint64(l)) + if m.Inbound != nil { + { + size, err := m.Inbound.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa } - return n + return len(dAtA) - i, nil } -func (m *QueryAllGasPricesRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Pagination != nil { - l = m.Pagination.Size() - n += 1 + l + sovQuery(uint64(l)) +func (m *QueryInboundKeysResponse) 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 n + return dAtA[:n], nil } -func (m *QueryAllGasPricesResponse) Size() (n int) { - if m == nil { - return 0 - } +func (m *QueryInboundKeysResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryInboundKeysResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i var l int _ = l - if len(m.GasPrices) > 0 { - for _, e := range m.GasPrices { - l = e.Size() - n += 1 + l + sovQuery(uint64(l)) - } - } - if m.Pagination != nil { + if m.CanonicalInbound != nil { + { + size, err := m.CanonicalInbound.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if len(m.BallotId) > 0 { + i -= len(m.BallotId) + copy(dAtA[i:], m.BallotId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.BallotId))) + i-- + dAtA[i] = 0x12 + } + if len(m.UtxId) > 0 { + i -= len(m.UtxId) + copy(dAtA[i:], m.UtxId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.UtxId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryOutboundBallotKeyRequest) 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 *QueryOutboundBallotKeyRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryOutboundBallotKeyRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.ObservedTx != nil { + { + size, err := m.ObservedTx.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if len(m.OutboundId) > 0 { + i -= len(m.OutboundId) + copy(dAtA[i:], m.OutboundId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.OutboundId))) + i-- + dAtA[i] = 0x12 + } + if len(m.UtxId) > 0 { + i -= len(m.UtxId) + copy(dAtA[i:], m.UtxId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.UtxId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryOutboundBallotKeyResponse) 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 *QueryOutboundBallotKeyResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryOutboundBallotKeyResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.CanonicalObservedTx != nil { + { + size, err := m.CanonicalObservedTx.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.BallotId) > 0 { + i -= len(m.BallotId) + copy(dAtA[i:], m.BallotId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.BallotId))) + i-- + dAtA[i] = 0xa + } + 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 *QueryGasPriceRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ChainId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryGasPriceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.GasPrice != nil { + l = m.GasPrice.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryAllGasPricesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryAllGasPricesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.GasPrices) > 0 { + for _, e := range m.GasPrices { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { l = m.Pagination.Size() n += 1 + l + sovQuery(uint64(l)) } @@ -3001,6 +3496,78 @@ func (m *QueryAllPendingOutboundsResponse) Size() (n int) { return n } +func (m *QueryInboundKeysRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Inbound != nil { + l = m.Inbound.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryInboundKeysResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.UtxId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.BallotId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.CanonicalInbound != nil { + l = m.CanonicalInbound.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryOutboundBallotKeyRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.UtxId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.OutboundId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.ObservedTx != nil { + l = m.ObservedTx.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryOutboundBallotKeyResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.BallotId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.CanonicalObservedTx != nil { + l = m.CanonicalObservedTx.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -5307,6 +5874,510 @@ func (m *QueryAllPendingOutboundsResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryInboundKeysRequest) 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: QueryInboundKeysRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryInboundKeysRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Inbound", 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 + } + if m.Inbound == nil { + m.Inbound = &Inbound{} + } + if err := m.Inbound.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 *QueryInboundKeysResponse) 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: QueryInboundKeysResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryInboundKeysResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UtxId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.UtxId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BallotId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BallotId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CanonicalInbound", 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 + } + if m.CanonicalInbound == nil { + m.CanonicalInbound = &Inbound{} + } + if err := m.CanonicalInbound.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 *QueryOutboundBallotKeyRequest) 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: QueryOutboundBallotKeyRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryOutboundBallotKeyRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UtxId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.UtxId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OutboundId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.OutboundId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ObservedTx", 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 + } + if m.ObservedTx == nil { + m.ObservedTx = &OutboundObservation{} + } + if err := m.ObservedTx.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 *QueryOutboundBallotKeyResponse) 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: QueryOutboundBallotKeyResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryOutboundBallotKeyResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BallotId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BallotId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CanonicalObservedTx", 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 + } + if m.CanonicalObservedTx == nil { + m.CanonicalObservedTx = &OutboundObservation{} + } + if err := m.CanonicalObservedTx.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 skipQuery(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/uexecutor/types/query.pb.gw.go b/x/uexecutor/types/query.pb.gw.go index 2a32c1962..8675cf9a2 100644 --- a/x/uexecutor/types/query.pb.gw.go +++ b/x/uexecutor/types/query.pb.gw.go @@ -483,6 +483,74 @@ func local_request_Query_AllExpiredInbounds_0(ctx context.Context, marshaler run } +func request_Query_InboundKeys_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryInboundKeysRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.InboundKeys(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_InboundKeys_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryInboundKeysRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.InboundKeys(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_OutboundBallotKey_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryOutboundBallotKeyRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.OutboundBallotKey(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_OutboundBallotKey_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryOutboundBallotKeyRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.OutboundBallotKey(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. @@ -742,6 +810,52 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("POST", pattern_Query_InboundKeys_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_InboundKeys_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_InboundKeys_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_Query_OutboundBallotKey_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_OutboundBallotKey_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_OutboundBallotKey_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -1003,6 +1117,46 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("POST", pattern_Query_InboundKeys_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_InboundKeys_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_InboundKeys_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_Query_OutboundBallotKey_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_OutboundBallotKey_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_OutboundBallotKey_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -1028,6 +1182,10 @@ var ( pattern_Query_AllPendingOutbounds_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"uexecutor", "v1", "pending_outbounds"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_AllExpiredInbounds_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"uexecutor", "v1", "expired_inbounds"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_InboundKeys_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"uexecutor", "v1", "inbound_keys"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_OutboundBallotKey_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"uexecutor", "v1", "outbound_ballot_key"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( @@ -1052,4 +1210,8 @@ var ( forward_Query_AllPendingOutbounds_0 = runtime.ForwardResponseMessage forward_Query_AllExpiredInbounds_0 = runtime.ForwardResponseMessage + + forward_Query_InboundKeys_0 = runtime.ForwardResponseMessage + + forward_Query_OutboundBallotKey_0 = runtime.ForwardResponseMessage )