From b290e30391793a8896c164b629727b4e834d64d2 Mon Sep 17 00:00:00 2001 From: Evan Gray Date: Wed, 17 May 2023 20:09:47 -0400 Subject: [PATCH] WIP: CCQ --- Dockerfile.const | 11 +- devnet/node.yaml | 8 +- node/cmd/guardiand/node.go | 65 ++- node/cmd/guardiand/query.go | 84 +++ node/cmd/spy/spy.go | 16 + node/hack/query/dev.guardian.key | 8 + node/hack/query/send_req.go | 284 +++++++++++ node/pkg/common/queryReqSendC.go | 16 + node/pkg/p2p/p2p.go | 5 + node/pkg/proto/gossip/v1/gossip.pb.go | 708 ++++++++++++++++++-------- node/pkg/watchers/evm/watcher.go | 84 +++ proto/gossip/v1/gossip.proto | 26 + 12 files changed, 1086 insertions(+), 229 deletions(-) create mode 100644 node/cmd/guardiand/query.go create mode 100644 node/hack/query/dev.guardian.key create mode 100644 node/hack/query/send_req.go create mode 100644 node/pkg/common/queryReqSendC.go diff --git a/Dockerfile.const b/Dockerfile.const index 7f3d7e7cf3..876ca3e89d 100644 --- a/Dockerfile.const +++ b/Dockerfile.const @@ -1,13 +1,18 @@ # syntax=docker.io/docker/dockerfile:1.3@sha256:42399d4635eddd7a9b8a24be879d2f9a930d0ed040a61324cfdf59ef1357b3b2 FROM node:16-alpine@sha256:004dbac84fed48e20f9888a23e32fa7cf83c2995e174a78d41d9a9dd1e051a20 as const-build -# fetch scripts/guardian-set-init.sh deps -RUN apk update && apk add bash g++ make python3 curl jq findutils - # Support additional root CAs COPY README.md cert.pem* /certs/ # Alpine RUN if [ -e /certs/cert.pem ]; then cp /certs/cert.pem /etc/ssl/cert.pem; fi +# Node +ENV NODE_EXTRA_CA_CERTS=/certs/cert.pem +ENV NODE_OPTIONS=--use-openssl-ca +# npm +RUN if [ -e /certs/cert.pem ]; then npm config set cafile /certs/cert.pem; fi + +# fetch scripts/guardian-set-init.sh deps +RUN apk update && apk add bash g++ make python3 curl jq findutils # install CLI deps & build WORKDIR /clients/js diff --git a/devnet/node.yaml b/devnet/node.yaml index 2b0c2799a5..d19e7cb7f6 100644 --- a/devnet/node.yaml +++ b/devnet/node.yaml @@ -78,7 +78,9 @@ spec: # - --bscRPC # - ws://eth-devnet2:8545 - --polygonRPC - - ws://eth-devnet:8545 + - wss://ws-matic-mainnet.chainstacklabs.com + - --polygonContract + - "0x7A4B5a56256163F07b2C80A7cA55aBE66c4ec4d7" - --avalancheRPC - ws://eth-devnet:8545 - --auroraRPC @@ -167,8 +169,8 @@ spec: - /tmp/data - --publicRpcLogDetail - "full" - # - --chainGovernorEnabled=true - # - --logLevel=debug + # - --chainGovernorEnabled=true + # - --logLevel=debug securityContext: capabilities: add: diff --git a/node/cmd/guardiand/node.go b/node/cmd/guardiand/node.go index 21968093e4..bf54ab0350 100644 --- a/node/cmd/guardiand/node.go +++ b/node/cmd/guardiand/node.go @@ -412,6 +412,8 @@ var Build = "prod" // observationRequestBufferSize is the buffer size of the per-network reobservation channel const observationRequestBufferSize = 25 +// queryRequestBufferSize is the buffer size of the per-network reobservation channel +const queryRequestBufferSize = 25 func runNode(cmd *cobra.Command, args []string) { if Build == "dev" && !*unsafeDevMode { @@ -506,7 +508,7 @@ func runNode(cmd *cobra.Command, args []string) { // Deterministic ganache ETH devnet address. *ethContract = unsafeDevModeEvmContractAddress(*ethContract) *bscContract = unsafeDevModeEvmContractAddress(*bscContract) - *polygonContract = unsafeDevModeEvmContractAddress(*polygonContract) + // *polygonContract = unsafeDevModeEvmContractAddress(*polygonContract) *avalancheContract = unsafeDevModeEvmContractAddress(*avalancheContract) *oasisContract = unsafeDevModeEvmContractAddress(*oasisContract) *auroraContract = unsafeDevModeEvmContractAddress(*auroraContract) @@ -924,6 +926,12 @@ func runNode(cmd *cobra.Command, args []string) { // Per-chain observation requests chainObsvReqC := make(map[vaa.ChainID]chan *gossipv1.ObservationRequest) + // Inbound observation requests from the p2p service (for all chains) + signedQueryReqReadC, signedQueryReqWriteC := makeChannelPair[*gossipv1.SignedQueryRequest](common.QueryReqChannelSize) + + // Per-chain query requests + chainQueryReqC := make(map[vaa.ChainID]chan *gossipv1.QueryRequest) + // Per-chain msgC chainMsgC := make(map[vaa.ChainID]chan *common.MessagePublication) // aggregate per-chain msgC into msgC. @@ -1158,7 +1166,8 @@ func runNode(cmd *cobra.Command, args []string) { nil, nil, components, - &ibc.Features)); err != nil { + &ibc.Features, + signedQueryReqWriteC)); err != nil { return err } @@ -1174,7 +1183,8 @@ func runNode(cmd *cobra.Command, args []string) { logger.Info("Starting Ethereum watcher") common.MustRegisterReadinessSyncing(vaa.ChainIDEthereum) chainObsvReqC[vaa.ChainIDEthereum] = make(chan *gossipv1.ObservationRequest, observationRequestBufferSize) - ethWatcher = evm.NewEthWatcher(*ethRPC, ethContractAddr, "eth", vaa.ChainIDEthereum, chainMsgC[vaa.ChainIDEthereum], setWriteC, chainObsvReqC[vaa.ChainIDEthereum], *unsafeDevMode) + chainQueryReqC[vaa.ChainIDEthereum] = make(chan *gossipv1.QueryRequest, queryRequestBufferSize) + ethWatcher = evm.NewEthWatcher(*ethRPC, ethContractAddr, "eth", vaa.ChainIDEthereum, chainMsgC[vaa.ChainIDEthereum], setWriteC, chainObsvReqC[vaa.ChainIDEthereum], chainQueryReqC[vaa.ChainIDEthereum], *unsafeDevMode) if err := supervisor.Run(ctx, "ethwatch", common.WrapWithScissors(ethWatcher.Run, "ethwatch")); err != nil { return err @@ -1185,7 +1195,8 @@ func runNode(cmd *cobra.Command, args []string) { logger.Info("Starting BSC watcher") common.MustRegisterReadinessSyncing(vaa.ChainIDBSC) chainObsvReqC[vaa.ChainIDBSC] = make(chan *gossipv1.ObservationRequest, observationRequestBufferSize) - bscWatcher := evm.NewEthWatcher(*bscRPC, bscContractAddr, "bsc", vaa.ChainIDBSC, chainMsgC[vaa.ChainIDBSC], nil, chainObsvReqC[vaa.ChainIDBSC], *unsafeDevMode) + chainQueryReqC[vaa.ChainIDBSC] = make(chan *gossipv1.QueryRequest, queryRequestBufferSize) + bscWatcher := evm.NewEthWatcher(*bscRPC, bscContractAddr, "bsc", vaa.ChainIDBSC, chainMsgC[vaa.ChainIDBSC], nil, chainObsvReqC[vaa.ChainIDBSC], chainQueryReqC[vaa.ChainIDBSC], *unsafeDevMode) bscWatcher.SetWaitForConfirmations(true) if err := supervisor.Run(ctx, "bscwatch", common.WrapWithScissors(bscWatcher.Run, "bscwatch")); err != nil { return err @@ -1201,7 +1212,8 @@ func runNode(cmd *cobra.Command, args []string) { logger.Info("Starting Polygon watcher") common.MustRegisterReadinessSyncing(vaa.ChainIDPolygon) chainObsvReqC[vaa.ChainIDPolygon] = make(chan *gossipv1.ObservationRequest, observationRequestBufferSize) - polygonWatcher := evm.NewEthWatcher(*polygonRPC, polygonContractAddr, "polygon", vaa.ChainIDPolygon, chainMsgC[vaa.ChainIDPolygon], nil, chainObsvReqC[vaa.ChainIDPolygon], *unsafeDevMode) + chainQueryReqC[vaa.ChainIDPolygon] = make(chan *gossipv1.QueryRequest, queryRequestBufferSize) + polygonWatcher := evm.NewEthWatcher(*polygonRPC, polygonContractAddr, "polygon", vaa.ChainIDPolygon, chainMsgC[vaa.ChainIDPolygon], nil, chainObsvReqC[vaa.ChainIDPolygon], chainQueryReqC[vaa.ChainIDPolygon], *unsafeDevMode) polygonWatcher.SetWaitForConfirmations(waitForConfirmations) if err := polygonWatcher.SetRootChainParams(*polygonRootChainRpc, *polygonRootChainContractAddress); err != nil { return err @@ -1214,8 +1226,9 @@ func runNode(cmd *cobra.Command, args []string) { logger.Info("Starting Avalanche watcher") common.MustRegisterReadinessSyncing(vaa.ChainIDAvalanche) chainObsvReqC[vaa.ChainIDAvalanche] = make(chan *gossipv1.ObservationRequest, observationRequestBufferSize) + chainQueryReqC[vaa.ChainIDAvalanche] = make(chan *gossipv1.QueryRequest, queryRequestBufferSize) if err := supervisor.Run(ctx, "avalanchewatch", - common.WrapWithScissors(evm.NewEthWatcher(*avalancheRPC, avalancheContractAddr, "avalanche", vaa.ChainIDAvalanche, chainMsgC[vaa.ChainIDAvalanche], nil, chainObsvReqC[vaa.ChainIDAvalanche], *unsafeDevMode).Run, "avalanchewatch")); err != nil { + common.WrapWithScissors(evm.NewEthWatcher(*avalancheRPC, avalancheContractAddr, "avalanche", vaa.ChainIDAvalanche, chainMsgC[vaa.ChainIDAvalanche], nil, chainObsvReqC[vaa.ChainIDAvalanche], chainQueryReqC[vaa.ChainIDAvalanche], *unsafeDevMode).Run, "avalanchewatch")); err != nil { return err } } @@ -1223,8 +1236,9 @@ func runNode(cmd *cobra.Command, args []string) { logger.Info("Starting Oasis watcher") common.MustRegisterReadinessSyncing(vaa.ChainIDOasis) chainObsvReqC[vaa.ChainIDOasis] = make(chan *gossipv1.ObservationRequest, observationRequestBufferSize) + chainQueryReqC[vaa.ChainIDOasis] = make(chan *gossipv1.QueryRequest, queryRequestBufferSize) if err := supervisor.Run(ctx, "oasiswatch", - common.WrapWithScissors(evm.NewEthWatcher(*oasisRPC, oasisContractAddr, "oasis", vaa.ChainIDOasis, chainMsgC[vaa.ChainIDOasis], nil, chainObsvReqC[vaa.ChainIDOasis], *unsafeDevMode).Run, "oasiswatch")); err != nil { + common.WrapWithScissors(evm.NewEthWatcher(*oasisRPC, oasisContractAddr, "oasis", vaa.ChainIDOasis, chainMsgC[vaa.ChainIDOasis], nil, chainObsvReqC[vaa.ChainIDOasis], chainQueryReqC[vaa.ChainIDOasis], *unsafeDevMode).Run, "oasiswatch")); err != nil { return err } } @@ -1232,8 +1246,9 @@ func runNode(cmd *cobra.Command, args []string) { logger.Info("Starting Aurora watcher") common.MustRegisterReadinessSyncing(vaa.ChainIDAurora) chainObsvReqC[vaa.ChainIDAurora] = make(chan *gossipv1.ObservationRequest, observationRequestBufferSize) + chainQueryReqC[vaa.ChainIDAurora] = make(chan *gossipv1.QueryRequest, queryRequestBufferSize) if err := supervisor.Run(ctx, "aurorawatch", - common.WrapWithScissors(evm.NewEthWatcher(*auroraRPC, auroraContractAddr, "aurora", vaa.ChainIDAurora, chainMsgC[vaa.ChainIDAurora], nil, chainObsvReqC[vaa.ChainIDAurora], *unsafeDevMode).Run, "aurorawatch")); err != nil { + common.WrapWithScissors(evm.NewEthWatcher(*auroraRPC, auroraContractAddr, "aurora", vaa.ChainIDAurora, chainMsgC[vaa.ChainIDAurora], nil, chainObsvReqC[vaa.ChainIDAurora], chainQueryReqC[vaa.ChainIDAurora], *unsafeDevMode).Run, "aurorawatch")); err != nil { return err } } @@ -1241,8 +1256,9 @@ func runNode(cmd *cobra.Command, args []string) { logger.Info("Starting Fantom watcher") common.MustRegisterReadinessSyncing(vaa.ChainIDFantom) chainObsvReqC[vaa.ChainIDFantom] = make(chan *gossipv1.ObservationRequest, observationRequestBufferSize) + chainQueryReqC[vaa.ChainIDFantom] = make(chan *gossipv1.QueryRequest, queryRequestBufferSize) if err := supervisor.Run(ctx, "fantomwatch", - common.WrapWithScissors(evm.NewEthWatcher(*fantomRPC, fantomContractAddr, "fantom", vaa.ChainIDFantom, chainMsgC[vaa.ChainIDFantom], nil, chainObsvReqC[vaa.ChainIDFantom], *unsafeDevMode).Run, "fantomwatch")); err != nil { + common.WrapWithScissors(evm.NewEthWatcher(*fantomRPC, fantomContractAddr, "fantom", vaa.ChainIDFantom, chainMsgC[vaa.ChainIDFantom], nil, chainObsvReqC[vaa.ChainIDFantom], chainQueryReqC[vaa.ChainIDFantom], *unsafeDevMode).Run, "fantomwatch")); err != nil { return err } } @@ -1250,8 +1266,9 @@ func runNode(cmd *cobra.Command, args []string) { logger.Info("Starting Karura watcher") common.MustRegisterReadinessSyncing(vaa.ChainIDKarura) chainObsvReqC[vaa.ChainIDKarura] = make(chan *gossipv1.ObservationRequest, observationRequestBufferSize) + chainQueryReqC[vaa.ChainIDKarura] = make(chan *gossipv1.QueryRequest, queryRequestBufferSize) if err := supervisor.Run(ctx, "karurawatch", - common.WrapWithScissors(evm.NewEthWatcher(*karuraRPC, karuraContractAddr, "karura", vaa.ChainIDKarura, chainMsgC[vaa.ChainIDKarura], nil, chainObsvReqC[vaa.ChainIDKarura], *unsafeDevMode).Run, "karurawatch")); err != nil { + common.WrapWithScissors(evm.NewEthWatcher(*karuraRPC, karuraContractAddr, "karura", vaa.ChainIDKarura, chainMsgC[vaa.ChainIDKarura], nil, chainObsvReqC[vaa.ChainIDKarura], chainQueryReqC[vaa.ChainIDKarura], *unsafeDevMode).Run, "karurawatch")); err != nil { return err } } @@ -1259,8 +1276,9 @@ func runNode(cmd *cobra.Command, args []string) { logger.Info("Starting Acala watcher") common.MustRegisterReadinessSyncing(vaa.ChainIDAcala) chainObsvReqC[vaa.ChainIDAcala] = make(chan *gossipv1.ObservationRequest, observationRequestBufferSize) + chainQueryReqC[vaa.ChainIDAcala] = make(chan *gossipv1.QueryRequest, queryRequestBufferSize) if err := supervisor.Run(ctx, "acalawatch", - common.WrapWithScissors(evm.NewEthWatcher(*acalaRPC, acalaContractAddr, "acala", vaa.ChainIDAcala, chainMsgC[vaa.ChainIDAcala], nil, chainObsvReqC[vaa.ChainIDAcala], *unsafeDevMode).Run, "acalawatch")); err != nil { + common.WrapWithScissors(evm.NewEthWatcher(*acalaRPC, acalaContractAddr, "acala", vaa.ChainIDAcala, chainMsgC[vaa.ChainIDAcala], nil, chainObsvReqC[vaa.ChainIDAcala], chainQueryReqC[vaa.ChainIDAcala], *unsafeDevMode).Run, "acalawatch")); err != nil { return err } } @@ -1268,8 +1286,9 @@ func runNode(cmd *cobra.Command, args []string) { logger.Info("Starting Klaytn watcher") common.MustRegisterReadinessSyncing(vaa.ChainIDKlaytn) chainObsvReqC[vaa.ChainIDKlaytn] = make(chan *gossipv1.ObservationRequest, observationRequestBufferSize) + chainQueryReqC[vaa.ChainIDKlaytn] = make(chan *gossipv1.QueryRequest, queryRequestBufferSize) if err := supervisor.Run(ctx, "klaytnwatch", - common.WrapWithScissors(evm.NewEthWatcher(*klaytnRPC, klaytnContractAddr, "klaytn", vaa.ChainIDKlaytn, chainMsgC[vaa.ChainIDKlaytn], nil, chainObsvReqC[vaa.ChainIDKlaytn], *unsafeDevMode).Run, "klaytnwatch")); err != nil { + common.WrapWithScissors(evm.NewEthWatcher(*klaytnRPC, klaytnContractAddr, "klaytn", vaa.ChainIDKlaytn, chainMsgC[vaa.ChainIDKlaytn], nil, chainObsvReqC[vaa.ChainIDKlaytn], chainQueryReqC[vaa.ChainIDKlaytn], *unsafeDevMode).Run, "klaytnwatch")); err != nil { return err } } @@ -1277,8 +1296,9 @@ func runNode(cmd *cobra.Command, args []string) { logger.Info("Starting Celo watcher") common.MustRegisterReadinessSyncing(vaa.ChainIDCelo) chainObsvReqC[vaa.ChainIDCelo] = make(chan *gossipv1.ObservationRequest, observationRequestBufferSize) + chainQueryReqC[vaa.ChainIDCelo] = make(chan *gossipv1.QueryRequest, queryRequestBufferSize) if err := supervisor.Run(ctx, "celowatch", - common.WrapWithScissors(evm.NewEthWatcher(*celoRPC, celoContractAddr, "celo", vaa.ChainIDCelo, chainMsgC[vaa.ChainIDCelo], nil, chainObsvReqC[vaa.ChainIDCelo], *unsafeDevMode).Run, "celowatch")); err != nil { + common.WrapWithScissors(evm.NewEthWatcher(*celoRPC, celoContractAddr, "celo", vaa.ChainIDCelo, chainMsgC[vaa.ChainIDCelo], nil, chainObsvReqC[vaa.ChainIDCelo], chainQueryReqC[vaa.ChainIDCelo], *unsafeDevMode).Run, "celowatch")); err != nil { return err } } @@ -1286,8 +1306,9 @@ func runNode(cmd *cobra.Command, args []string) { logger.Info("Starting Moonbeam watcher") common.MustRegisterReadinessSyncing(vaa.ChainIDMoonbeam) chainObsvReqC[vaa.ChainIDMoonbeam] = make(chan *gossipv1.ObservationRequest, observationRequestBufferSize) + chainQueryReqC[vaa.ChainIDMoonbeam] = make(chan *gossipv1.QueryRequest, queryRequestBufferSize) if err := supervisor.Run(ctx, "moonbeamwatch", - common.WrapWithScissors(evm.NewEthWatcher(*moonbeamRPC, moonbeamContractAddr, "moonbeam", vaa.ChainIDMoonbeam, chainMsgC[vaa.ChainIDMoonbeam], nil, chainObsvReqC[vaa.ChainIDMoonbeam], *unsafeDevMode).Run, "moonbeamwatch")); err != nil { + common.WrapWithScissors(evm.NewEthWatcher(*moonbeamRPC, moonbeamContractAddr, "moonbeam", vaa.ChainIDMoonbeam, chainMsgC[vaa.ChainIDMoonbeam], nil, chainObsvReqC[vaa.ChainIDMoonbeam], chainQueryReqC[vaa.ChainIDMoonbeam], *unsafeDevMode).Run, "moonbeamwatch")); err != nil { return err } } @@ -1298,7 +1319,8 @@ func runNode(cmd *cobra.Command, args []string) { logger.Info("Starting Arbitrum watcher") common.MustRegisterReadinessSyncing(vaa.ChainIDArbitrum) chainObsvReqC[vaa.ChainIDArbitrum] = make(chan *gossipv1.ObservationRequest, observationRequestBufferSize) - arbitrumWatcher := evm.NewEthWatcher(*arbitrumRPC, arbitrumContractAddr, "arbitrum", vaa.ChainIDArbitrum, chainMsgC[vaa.ChainIDArbitrum], nil, chainObsvReqC[vaa.ChainIDArbitrum], *unsafeDevMode) + chainQueryReqC[vaa.ChainIDArbitrum] = make(chan *gossipv1.QueryRequest, queryRequestBufferSize) + arbitrumWatcher := evm.NewEthWatcher(*arbitrumRPC, arbitrumContractAddr, "arbitrum", vaa.ChainIDArbitrum, chainMsgC[vaa.ChainIDArbitrum], nil, chainObsvReqC[vaa.ChainIDArbitrum], chainQueryReqC[vaa.ChainIDArbitrum], *unsafeDevMode) arbitrumWatcher.SetL1Finalizer(ethWatcher) if err := supervisor.Run(ctx, "arbitrumwatch", common.WrapWithScissors(arbitrumWatcher.Run, "arbitrumwatch")); err != nil { return err @@ -1308,7 +1330,8 @@ func runNode(cmd *cobra.Command, args []string) { logger.Info("Starting Optimism watcher") common.MustRegisterReadinessSyncing(vaa.ChainIDOptimism) chainObsvReqC[vaa.ChainIDOptimism] = make(chan *gossipv1.ObservationRequest, observationRequestBufferSize) - optimismWatcher := evm.NewEthWatcher(*optimismRPC, optimismContractAddr, "optimism", vaa.ChainIDOptimism, chainMsgC[vaa.ChainIDOptimism], nil, chainObsvReqC[vaa.ChainIDOptimism], *unsafeDevMode) + chainQueryReqC[vaa.ChainIDOptimism] = make(chan *gossipv1.QueryRequest, queryRequestBufferSize) + optimismWatcher := evm.NewEthWatcher(*optimismRPC, optimismContractAddr, "optimism", vaa.ChainIDOptimism, chainMsgC[vaa.ChainIDOptimism], nil, chainObsvReqC[vaa.ChainIDOptimism], chainQueryReqC[vaa.ChainIDOptimism], *unsafeDevMode) // If rootChainParams are set, pass them in for pre-Bedrock mode if *optimismCtcRpc != "" || *optimismCtcContractAddress != "" { @@ -1447,7 +1470,8 @@ func runNode(cmd *cobra.Command, args []string) { logger.Info("Starting Neon watcher") common.MustRegisterReadinessSyncing(vaa.ChainIDNeon) chainObsvReqC[vaa.ChainIDNeon] = make(chan *gossipv1.ObservationRequest, observationRequestBufferSize) - neonWatcher := evm.NewEthWatcher(*neonRPC, neonContractAddr, "neon", vaa.ChainIDNeon, chainMsgC[vaa.ChainIDNeon], nil, chainObsvReqC[vaa.ChainIDNeon], *unsafeDevMode) + chainQueryReqC[vaa.ChainIDNeon] = make(chan *gossipv1.QueryRequest, queryRequestBufferSize) + neonWatcher := evm.NewEthWatcher(*neonRPC, neonContractAddr, "neon", vaa.ChainIDNeon, chainMsgC[vaa.ChainIDNeon], nil, chainObsvReqC[vaa.ChainIDNeon], chainQueryReqC[vaa.ChainIDNeon], *unsafeDevMode) neonWatcher.SetL1Finalizer(solanaFinalizedWatcher) if err := supervisor.Run(ctx, "neonwatch", common.WrapWithScissors(neonWatcher.Run, "neonwatch")); err != nil { return err @@ -1457,7 +1481,8 @@ func runNode(cmd *cobra.Command, args []string) { logger.Info("Starting Base watcher") common.MustRegisterReadinessSyncing(vaa.ChainIDBase) chainObsvReqC[vaa.ChainIDBase] = make(chan *gossipv1.ObservationRequest, observationRequestBufferSize) - baseWatcher := evm.NewEthWatcher(*baseRPC, baseContractAddr, "base", vaa.ChainIDBase, chainMsgC[vaa.ChainIDBase], nil, chainObsvReqC[vaa.ChainIDBase], *unsafeDevMode) + chainQueryReqC[vaa.ChainIDBase] = make(chan *gossipv1.QueryRequest, queryRequestBufferSize) + baseWatcher := evm.NewEthWatcher(*baseRPC, baseContractAddr, "base", vaa.ChainIDBase, chainMsgC[vaa.ChainIDBase], nil, chainObsvReqC[vaa.ChainIDBase], chainQueryReqC[vaa.ChainIDBase], *unsafeDevMode) if err := supervisor.Run(ctx, "basewatch", common.WrapWithScissors(baseWatcher.Run, "basewatch")); err != nil { return err } @@ -1469,7 +1494,8 @@ func runNode(cmd *cobra.Command, args []string) { logger.Info("Starting Sepolia watcher") common.MustRegisterReadinessSyncing(vaa.ChainIDSepolia) chainObsvReqC[vaa.ChainIDSepolia] = make(chan *gossipv1.ObservationRequest, observationRequestBufferSize) - sepoliaWatcher := evm.NewEthWatcher(*sepoliaRPC, sepoliaContractAddr, "sepolia", vaa.ChainIDSepolia, chainMsgC[vaa.ChainIDSepolia], nil, chainObsvReqC[vaa.ChainIDSepolia], *unsafeDevMode) + chainQueryReqC[vaa.ChainIDSepolia] = make(chan *gossipv1.QueryRequest, queryRequestBufferSize) + sepoliaWatcher := evm.NewEthWatcher(*sepoliaRPC, sepoliaContractAddr, "sepolia", vaa.ChainIDSepolia, chainMsgC[vaa.ChainIDSepolia], nil, chainObsvReqC[vaa.ChainIDSepolia], chainQueryReqC[vaa.ChainIDSepolia], *unsafeDevMode) if err := supervisor.Run(ctx, "sepoliawatch", common.WrapWithScissors(sepoliaWatcher.Run, "sepoliawatch")); err != nil { return err } @@ -1520,6 +1546,7 @@ func runNode(cmd *cobra.Command, args []string) { } go handleReobservationRequests(rootCtx, clock.New(), logger, obsvReqReadC, chainObsvReqC) + go handleQueryRequests(rootCtx, clock.New(), logger, signedQueryReqReadC, chainQueryReqC) if acct != nil { if err := acct.Start(ctx); err != nil { diff --git a/node/cmd/guardiand/query.go b/node/cmd/guardiand/query.go new file mode 100644 index 0000000000..25b851ae64 --- /dev/null +++ b/node/cmd/guardiand/query.go @@ -0,0 +1,84 @@ +package guardiand + +import ( + "context" + + "github.com/benbjohnson/clock" + gossipv1 "github.com/certusone/wormhole/node/pkg/proto/gossip/v1" + "github.com/ethereum/go-ethereum/common" + ethcrypto "github.com/ethereum/go-ethereum/crypto" + "github.com/wormhole-foundation/wormhole/sdk/vaa" + "go.uber.org/zap" + "google.golang.org/protobuf/proto" +) + +// TODO: should this use a different standard of signing messages, like https://eips.ethereum.org/EIPS/eip-712 +var queryRequestPrefix = []byte("query_request_00000000000000000000|") + +func queryRequestDigest(b []byte) common.Hash { + return ethcrypto.Keccak256Hash(append(queryRequestPrefix, b...)) +} + +var allowedRequestor = common.BytesToAddress(common.Hex2Bytes("beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe")) + +// Multiplex observation requests to the appropriate chain +func handleQueryRequests( + ctx context.Context, + clock clock.Clock, + logger *zap.Logger, + signedQueryReqC <-chan *gossipv1.SignedQueryRequest, + chainQueryReqC map[vaa.ChainID]chan *gossipv1.QueryRequest, +) { + qLogger := logger.With(zap.String("component", "queryHandler")) + for { + select { + case <-ctx.Done(): + return + case signedQueryRequest := <-signedQueryReqC: + // requestor validation happens here + // request type validation is currently handled by the watcher + // in the future, it may be worthwhile to catch certain types of + // invalid requests here for tracking purposes + requestorAddr := common.BytesToAddress(signedQueryRequest.RequestorAddr) + if requestorAddr != allowedRequestor { + qLogger.Error("invalid requestor", zap.String("requestor", requestorAddr.Hex())) + continue + } + + digest := queryRequestDigest(signedQueryRequest.QueryRequest) + + signerBytes, err := ethcrypto.Ecrecover(digest.Bytes(), signedQueryRequest.Signature) + if err != nil { + qLogger.Error("failed to recover public key", zap.String("requestor", requestorAddr.Hex())) + continue + } + + signerAddress := common.BytesToAddress(ethcrypto.Keccak256(signerBytes[1:])[12:]) + if signerAddress != requestorAddr { + qLogger.Error("requestor signer mismatch", zap.String("requestor", requestorAddr.Hex()), zap.String("signer", signerAddress.Hex())) + continue + } + + var queryRequest gossipv1.QueryRequest + err = proto.Unmarshal(signedQueryRequest.QueryRequest, &queryRequest) + if err != nil { + qLogger.Error("received invalid message", + zap.String("requestor", requestorAddr.Hex())) + continue + } + + if channel, ok := chainQueryReqC[vaa.ChainID(queryRequest.ChainId)]; ok { + select { + // TODO: is pointer fine here? + case channel <- &queryRequest: + default: + qLogger.Warn("failed to send query request to watcher", + zap.Uint16("chain_id", uint16(queryRequest.ChainId))) + } + } else { + qLogger.Error("unknown chain ID for query request", + zap.Uint16("chain_id", uint16(queryRequest.ChainId))) + } + } + } +} diff --git a/node/cmd/spy/spy.go b/node/cmd/spy/spy.go index dff0203241..2680a6e246 100644 --- a/node/cmd/spy/spy.go +++ b/node/cmd/spy/spy.go @@ -466,6 +466,9 @@ func runSpy(cmd *cobra.Command, args []string) { // Inbound observation requests obsvReqC := make(chan *gossipv1.ObservationRequest, 50) + // Inbound observation requests + queryReqC := make(chan *gossipv1.SignedQueryRequest, 50) + // Inbound signed VAAs signedInC := make(chan *gossipv1.SignedVAAWithQuorum, 50) @@ -502,6 +505,18 @@ func runSpy(cmd *cobra.Command, args []string) { } }() + // Ignore query requests + // Note: without this, the whole program hangs on query requests + go func() { + for { + select { + case <-rootCtx.Done(): + return + case <-queryReqC: + } + } + }() + // Log signed VAAs go func() { for { @@ -553,6 +568,7 @@ func runSpy(cmd *cobra.Command, args []string) { nil, components, nil, // ibc feature string + queryReqC, )); err != nil { return err } diff --git a/node/hack/query/dev.guardian.key b/node/hack/query/dev.guardian.key new file mode 100644 index 0000000000..0be9e035bd --- /dev/null +++ b/node/hack/query/dev.guardian.key @@ -0,0 +1,8 @@ +-----BEGIN WORMHOLE GUARDIAN PRIVATE KEY----- +PublicKey: 0xbeFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe +Description: auto-generated deterministic devnet key + +CiDPsSMDoZzeWAu03XcWObDSa8aDU2RVcajP9RarLuEToBAB +=VN/A +-----END WORMHOLE GUARDIAN PRIVATE KEY----- + diff --git a/node/hack/query/send_req.go b/node/hack/query/send_req.go new file mode 100644 index 0000000000..0bcb0e977f --- /dev/null +++ b/node/hack/query/send_req.go @@ -0,0 +1,284 @@ +// This tool can be used to send various queries to the p2p gossip network. +// It is meant for testing purposes only. + +package main + +import ( + "context" + "crypto/ecdsa" + "encoding/hex" + "fmt" + "io" + "os" + "strings" + + "github.com/certusone/wormhole/node/pkg/common" + "github.com/certusone/wormhole/node/pkg/p2p" + gossipv1 "github.com/certusone/wormhole/node/pkg/proto/gossip/v1" + nodev1 "github.com/certusone/wormhole/node/pkg/proto/node/v1" + ethCommon "github.com/ethereum/go-ethereum/common" + ethCrypto "github.com/ethereum/go-ethereum/crypto" + "github.com/libp2p/go-libp2p" + dht "github.com/libp2p/go-libp2p-kad-dht" + pubsub "github.com/libp2p/go-libp2p-pubsub" + "github.com/libp2p/go-libp2p/core/crypto" + "github.com/libp2p/go-libp2p/core/host" + "github.com/libp2p/go-libp2p/core/peer" + "github.com/libp2p/go-libp2p/core/protocol" + "github.com/libp2p/go-libp2p/core/routing" + libp2ptls "github.com/libp2p/go-libp2p/p2p/security/tls" + libp2pquic "github.com/libp2p/go-libp2p/p2p/transport/quic" + "github.com/multiformats/go-multiaddr" + "go.uber.org/zap" + "golang.org/x/crypto/openpgp/armor" //nolint + "google.golang.org/protobuf/proto" +) + +var queryRequestPrefix = []byte("query_request_00000000000000000000|") + +func queryRequestDigest(b []byte) ethCommon.Hash { + return ethCrypto.Keccak256Hash(append(queryRequestPrefix, b...)) +} + +// this script has to be run inside kubernetes since it relies on UDP +// https://github.com/kubernetes/kubernetes/issues/47862 +// kubectl --namespace=wormhole exec -it spy-0 -- sh -c "cd node/hack/query/ && go run send_req.go" + +func main() { + + p2pNetworkID := "/wormhole/dev" + var p2pPort uint = 8998 // don't collide with spy so we can run from the same container in tilt + p2pBootstrap := "/dns4/guardian-0.guardian/udp/8999/quic/p2p/12D3KooWL3XJ9EMCyZvmmGXL2LMiVBtrVa2BuESsJiXkSj7333Jw" + nodeKeyPath := "/tmp/querier.key" // don't use node key so we get a new address + + ctx := context.Background() + logger, _ := zap.NewDevelopment() + + signingKeyPath := string("./dev.guardian.key") + + logger.Info("Loading signing key", zap.String("signingKeyPath", signingKeyPath)) + sk, err := loadGuardianKey(signingKeyPath) + if err != nil { + logger.Fatal("failed to load guardian key", zap.Error(err)) + } + logger.Info("Signing key loaded", zap.String("publicKey", ethCrypto.PubkeyToAddress(sk.PublicKey).Hex())) + + // Load p2p private key + var priv crypto.PrivKey + priv, err = common.GetOrCreateNodeKey(logger, nodeKeyPath) + if err != nil { + logger.Fatal("Failed to load node key", zap.Error(err)) + } + + // Manual p2p setup + components := p2p.DefaultComponents() + components.Port = p2pPort + bootstrapPeers := p2pBootstrap + networkID := p2pNetworkID + h, err := libp2p.New( + // Use the keypair we generated + libp2p.Identity(priv), + + // Multiple listen addresses + libp2p.ListenAddrStrings( + components.ListeningAddresses()..., + ), + + // Enable TLS security as the only security protocol. + libp2p.Security(libp2ptls.ID, libp2ptls.New), + + // Enable QUIC transport as the only transport. + libp2p.Transport(libp2pquic.NewTransport), + + // Let's prevent our peer from having too many + // connections by attaching a connection manager. + libp2p.ConnectionManager(components.ConnMgr), + + // Let this host use the DHT to find other hosts + libp2p.Routing(func(h host.Host) (routing.PeerRouting, error) { + logger.Info("Connecting to bootstrap peers", zap.String("bootstrap_peers", bootstrapPeers)) + bootstrappers := make([]peer.AddrInfo, 0) + for _, addr := range strings.Split(bootstrapPeers, ",") { + if addr == "" { + continue + } + ma, err := multiaddr.NewMultiaddr(addr) + if err != nil { + logger.Error("Invalid bootstrap address", zap.String("peer", addr), zap.Error(err)) + continue + } + pi, err := peer.AddrInfoFromP2pAddr(ma) + if err != nil { + logger.Error("Invalid bootstrap address", zap.String("peer", addr), zap.Error(err)) + continue + } + if pi.ID == h.ID() { + logger.Info("We're a bootstrap node") + continue + } + bootstrappers = append(bootstrappers, *pi) + } + // TODO(leo): Persistent data store (i.e. address book) + idht, err := dht.New(ctx, h, dht.Mode(dht.ModeServer), + // This intentionally makes us incompatible with the global IPFS DHT + dht.ProtocolPrefix(protocol.ID("/"+networkID)), + dht.BootstrapPeers(bootstrappers...), + ) + return idht, err + }), + ) + + if err != nil { + panic(err) + } + + topic := fmt.Sprintf("%s/%s", networkID, "broadcast") + + logger.Info("Subscribing pubsub topic", zap.String("topic", topic)) + ps, err := pubsub.NewGossipSub(ctx, h) + if err != nil { + panic(err) + } + + th, err := ps.Join(topic) + if err != nil { + logger.Panic("failed to join topic", zap.Error(err)) + } + + sub, err := th.Subscribe() + if err != nil { + logger.Panic("failed to subscribe topic", zap.Error(err)) + } + + logger.Info("Node has been started", zap.String("peer_id", h.ID().String()), + zap.String("addrs", fmt.Sprintf("%v", h.Addrs()))) + + to, _ := hex.DecodeString("0d500b1d8e8ef31e21c99d1db9a6444d3adf1270") + data, _ := hex.DecodeString("18160ddd") + // block := "0x28d9630" + // block := "latest" + block := "0x2e0d2bc116d77308db4e76eb906f6c168767ed00ad62cd2e2a31c61744c506e6" + callRequest := &gossipv1.EthCallQueryRequest{ + To: to, + Data: data, + Block: block, + } + queryRequest := &gossipv1.QueryRequest{ + ChainId: 5, + Nonce: 0, + Message: &gossipv1.QueryRequest_EthCallQueryRequest{ + EthCallQueryRequest: callRequest}} + + queryRequestBytes, err := proto.Marshal(queryRequest) + if err != nil { + panic(err) + } + + // Sign the query request using our private key. + digest := queryRequestDigest(queryRequestBytes) + sig, err := ethCrypto.Sign(digest.Bytes(), sk) + if err != nil { + panic(err) + } + + signedQueryRequest := &gossipv1.SignedQueryRequest{ + QueryRequest: queryRequestBytes, + Signature: sig, + RequestorAddr: ethCrypto.PubkeyToAddress(sk.PublicKey).Bytes(), + } + + msg := gossipv1.GossipMessage{ + Message: &gossipv1.GossipMessage_SignedQueryRequest{ + SignedQueryRequest: signedQueryRequest, + }, + } + + b, err := proto.Marshal(&msg) + if err != nil { + panic(err) + } + + // do something to wait for peers, this waits to receive a message + logger.Info("Waiting for a message...") + for { + envelope, err := sub.Next(ctx) + if err != nil { + logger.Panic("failed to receive pubsub message", zap.Error(err)) + } + var msg gossipv1.GossipMessage + err = proto.Unmarshal(envelope.Data, &msg) + if err != nil { + logger.Info("received invalid message", + zap.Binary("data", envelope.Data), + zap.String("from", envelope.GetFrom().String())) + continue + } + logger.Info("Received a message!") + break + } + + err = th.Publish(ctx, b) + if err != nil { + panic(err) + } + + logger.Info("Waiting for message...") + for { + envelope, err := sub.Next(ctx) + if err != nil { + logger.Panic("failed to receive pubsub message", zap.Error(err)) + } + var msg gossipv1.GossipMessage + err = proto.Unmarshal(envelope.Data, &msg) + if err != nil { + logger.Info("received invalid message", + zap.Binary("data", envelope.Data), + zap.String("from", envelope.GetFrom().String())) + continue + } + // TODO: actually wait for the corresponding response + logger.Info("received message") + break + } + + logger.Info("Success! All tests passed!") +} + +const ( + GuardianKeyArmoredBlock = "WORMHOLE GUARDIAN PRIVATE KEY" +) + +// loadGuardianKey loads a serialized guardian key from disk. +func loadGuardianKey(filename string) (*ecdsa.PrivateKey, error) { + f, err := os.Open(filename) + if err != nil { + return nil, fmt.Errorf("failed to open file: %w", err) + } + + p, err := armor.Decode(f) + if err != nil { + return nil, fmt.Errorf("failed to read armored file: %w", err) + } + + if p.Type != GuardianKeyArmoredBlock { + return nil, fmt.Errorf("invalid block type: %s", p.Type) + } + + b, err := io.ReadAll(p.Body) + if err != nil { + return nil, fmt.Errorf("failed to read file: %w", err) + } + + var m nodev1.GuardianKey + err = proto.Unmarshal(b, &m) + if err != nil { + return nil, fmt.Errorf("failed to deserialize protobuf: %w", err) + } + + gk, err := ethCrypto.ToECDSA(m.Data) + if err != nil { + return nil, fmt.Errorf("failed to deserialize raw key data: %w", err) + } + + return gk, nil +} diff --git a/node/pkg/common/queryReqSendC.go b/node/pkg/common/queryReqSendC.go new file mode 100644 index 0000000000..9acfedeb5c --- /dev/null +++ b/node/pkg/common/queryReqSendC.go @@ -0,0 +1,16 @@ +package common + +import ( + gossipv1 "github.com/certusone/wormhole/node/pkg/proto/gossip/v1" +) + +const QueryReqChannelSize = 50 + +func PostQueryRequest(obsvReqSendC chan<- *gossipv1.QueryRequest, req *gossipv1.QueryRequest) error { + select { + case obsvReqSendC <- req: + return nil + default: + return ErrChanFull + } +} diff --git a/node/pkg/p2p/p2p.go b/node/pkg/p2p/p2p.go index f8a746a044..567ba334e6 100644 --- a/node/pkg/p2p/p2p.go +++ b/node/pkg/p2p/p2p.go @@ -155,6 +155,7 @@ func Run( signedGovSt chan *gossipv1.SignedChainGovernorStatus, components *Components, ibcFeatures *string, + signedQueryReqC chan<- *gossipv1.SignedQueryRequest, ) func(ctx context.Context) error { if components == nil { components = DefaultComponents() @@ -554,6 +555,10 @@ func Run( if signedGovSt != nil { signedGovSt <- m.SignedChainGovernorStatus } + case *gossipv1.GossipMessage_SignedQueryRequest: + if signedQueryReqC != nil { + signedQueryReqC <- m.SignedQueryRequest + } default: p2pMessagesReceived.WithLabelValues("unknown").Inc() logger.Warn("received unknown message type (running outdated software?)", diff --git a/node/pkg/proto/gossip/v1/gossip.pb.go b/node/pkg/proto/gossip/v1/gossip.pb.go index 291a25c3ac..4159b13a7f 100644 --- a/node/pkg/proto/gossip/v1/gossip.pb.go +++ b/node/pkg/proto/gossip/v1/gossip.pb.go @@ -35,6 +35,7 @@ type GossipMessage struct { // *GossipMessage_SignedBatchVaaWithQuorum // *GossipMessage_SignedChainGovernorConfig // *GossipMessage_SignedChainGovernorStatus + // *GossipMessage_SignedQueryRequest Message isGossipMessage_Message `protobuf_oneof:"message"` } @@ -133,6 +134,13 @@ func (x *GossipMessage) GetSignedChainGovernorStatus() *SignedChainGovernorStatu return nil } +func (x *GossipMessage) GetSignedQueryRequest() *SignedQueryRequest { + if x, ok := x.GetMessage().(*GossipMessage_SignedQueryRequest); ok { + return x.SignedQueryRequest + } + return nil +} + type isGossipMessage_Message interface { isGossipMessage_Message() } @@ -169,6 +177,10 @@ type GossipMessage_SignedChainGovernorStatus struct { SignedChainGovernorStatus *SignedChainGovernorStatus `protobuf:"bytes,9,opt,name=signed_chain_governor_status,json=signedChainGovernorStatus,proto3,oneof"` } +type GossipMessage_SignedQueryRequest struct { + SignedQueryRequest *SignedQueryRequest `protobuf:"bytes,10,opt,name=signed_query_request,json=signedQueryRequest,proto3,oneof"` +} + func (*GossipMessage_SignedObservation) isGossipMessage_Message() {} func (*GossipMessage_SignedHeartbeat) isGossipMessage_Message() {} @@ -185,6 +197,8 @@ func (*GossipMessage_SignedChainGovernorConfig) isGossipMessage_Message() {} func (*GossipMessage_SignedChainGovernorStatus) isGossipMessage_Message() {} +func (*GossipMessage_SignedQueryRequest) isGossipMessage_Message() {} + type SignedHeartbeat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1127,6 +1141,218 @@ func (x *ChainGovernorStatus) GetChains() []*ChainGovernorStatus_Chain { return nil } +type SignedQueryRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Serialized QueryRequest message. + QueryRequest []byte `protobuf:"bytes,1,opt,name=query_request,json=queryRequest,proto3" json:"query_request,omitempty"` + // ECDSA signature using the requestor's public key. + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` + // Requestor address that signed this payload (truncated Eth address). + RequestorAddr []byte `protobuf:"bytes,3,opt,name=requestor_addr,json=requestorAddr,proto3" json:"requestor_addr,omitempty"` +} + +func (x *SignedQueryRequest) Reset() { + *x = SignedQueryRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gossip_v1_gossip_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignedQueryRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignedQueryRequest) ProtoMessage() {} + +func (x *SignedQueryRequest) ProtoReflect() protoreflect.Message { + mi := &file_gossip_v1_gossip_proto_msgTypes[13] + 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) +} + +// Deprecated: Use SignedQueryRequest.ProtoReflect.Descriptor instead. +func (*SignedQueryRequest) Descriptor() ([]byte, []int) { + return file_gossip_v1_gossip_proto_rawDescGZIP(), []int{13} +} + +func (x *SignedQueryRequest) GetQueryRequest() []byte { + if x != nil { + return x.QueryRequest + } + return nil +} + +func (x *SignedQueryRequest) GetSignature() []byte { + if x != nil { + return x.Signature + } + return nil +} + +func (x *SignedQueryRequest) GetRequestorAddr() []byte { + if x != nil { + return x.RequestorAddr + } + return nil +} + +type QueryRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ChainId uint32 `protobuf:"varint,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + Nonce uint32 `protobuf:"varint,2,opt,name=nonce,proto3" json:"nonce,omitempty"` + // Types that are assignable to Message: + // + // *QueryRequest_EthCallQueryRequest + Message isQueryRequest_Message `protobuf_oneof:"message"` +} + +func (x *QueryRequest) Reset() { + *x = QueryRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gossip_v1_gossip_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryRequest) ProtoMessage() {} + +func (x *QueryRequest) ProtoReflect() protoreflect.Message { + mi := &file_gossip_v1_gossip_proto_msgTypes[14] + 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) +} + +// Deprecated: Use QueryRequest.ProtoReflect.Descriptor instead. +func (*QueryRequest) Descriptor() ([]byte, []int) { + return file_gossip_v1_gossip_proto_rawDescGZIP(), []int{14} +} + +func (x *QueryRequest) GetChainId() uint32 { + if x != nil { + return x.ChainId + } + return 0 +} + +func (x *QueryRequest) GetNonce() uint32 { + if x != nil { + return x.Nonce + } + return 0 +} + +func (m *QueryRequest) GetMessage() isQueryRequest_Message { + if m != nil { + return m.Message + } + return nil +} + +func (x *QueryRequest) GetEthCallQueryRequest() *EthCallQueryRequest { + if x, ok := x.GetMessage().(*QueryRequest_EthCallQueryRequest); ok { + return x.EthCallQueryRequest + } + return nil +} + +type isQueryRequest_Message interface { + isQueryRequest_Message() +} + +type QueryRequest_EthCallQueryRequest struct { + EthCallQueryRequest *EthCallQueryRequest `protobuf:"bytes,3,opt,name=eth_call_query_request,json=ethCallQueryRequest,proto3,oneof"` +} + +func (*QueryRequest_EthCallQueryRequest) isQueryRequest_Message() {} + +type EthCallQueryRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + To []byte `protobuf:"bytes,1,opt,name=to,proto3" json:"to,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Block string `protobuf:"bytes,3,opt,name=block,proto3" json:"block,omitempty"` +} + +func (x *EthCallQueryRequest) Reset() { + *x = EthCallQueryRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gossip_v1_gossip_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EthCallQueryRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EthCallQueryRequest) ProtoMessage() {} + +func (x *EthCallQueryRequest) ProtoReflect() protoreflect.Message { + mi := &file_gossip_v1_gossip_proto_msgTypes[15] + 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) +} + +// Deprecated: Use EthCallQueryRequest.ProtoReflect.Descriptor instead. +func (*EthCallQueryRequest) Descriptor() ([]byte, []int) { + return file_gossip_v1_gossip_proto_rawDescGZIP(), []int{15} +} + +func (x *EthCallQueryRequest) GetTo() []byte { + if x != nil { + return x.To + } + return nil +} + +func (x *EthCallQueryRequest) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +func (x *EthCallQueryRequest) GetBlock() string { + if x != nil { + return x.Block + } + return "" +} + type Heartbeat_Network struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1145,7 +1371,7 @@ type Heartbeat_Network struct { func (x *Heartbeat_Network) Reset() { *x = Heartbeat_Network{} if protoimpl.UnsafeEnabled { - mi := &file_gossip_v1_gossip_proto_msgTypes[13] + mi := &file_gossip_v1_gossip_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1158,7 +1384,7 @@ func (x *Heartbeat_Network) String() string { func (*Heartbeat_Network) ProtoMessage() {} func (x *Heartbeat_Network) ProtoReflect() protoreflect.Message { - mi := &file_gossip_v1_gossip_proto_msgTypes[13] + mi := &file_gossip_v1_gossip_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1215,7 +1441,7 @@ type ChainGovernorConfig_Chain struct { func (x *ChainGovernorConfig_Chain) Reset() { *x = ChainGovernorConfig_Chain{} if protoimpl.UnsafeEnabled { - mi := &file_gossip_v1_gossip_proto_msgTypes[14] + mi := &file_gossip_v1_gossip_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1228,7 +1454,7 @@ func (x *ChainGovernorConfig_Chain) String() string { func (*ChainGovernorConfig_Chain) ProtoMessage() {} func (x *ChainGovernorConfig_Chain) ProtoReflect() protoreflect.Message { - mi := &file_gossip_v1_gossip_proto_msgTypes[14] + mi := &file_gossip_v1_gossip_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1278,7 +1504,7 @@ type ChainGovernorConfig_Token struct { func (x *ChainGovernorConfig_Token) Reset() { *x = ChainGovernorConfig_Token{} if protoimpl.UnsafeEnabled { - mi := &file_gossip_v1_gossip_proto_msgTypes[15] + mi := &file_gossip_v1_gossip_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1291,7 +1517,7 @@ func (x *ChainGovernorConfig_Token) String() string { func (*ChainGovernorConfig_Token) ProtoMessage() {} func (x *ChainGovernorConfig_Token) ProtoReflect() protoreflect.Message { - mi := &file_gossip_v1_gossip_proto_msgTypes[15] + mi := &file_gossip_v1_gossip_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1342,7 +1568,7 @@ type ChainGovernorStatus_EnqueuedVAA struct { func (x *ChainGovernorStatus_EnqueuedVAA) Reset() { *x = ChainGovernorStatus_EnqueuedVAA{} if protoimpl.UnsafeEnabled { - mi := &file_gossip_v1_gossip_proto_msgTypes[16] + mi := &file_gossip_v1_gossip_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1355,7 +1581,7 @@ func (x *ChainGovernorStatus_EnqueuedVAA) String() string { func (*ChainGovernorStatus_EnqueuedVAA) ProtoMessage() {} func (x *ChainGovernorStatus_EnqueuedVAA) ProtoReflect() protoreflect.Message { - mi := &file_gossip_v1_gossip_proto_msgTypes[16] + mi := &file_gossip_v1_gossip_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1412,7 +1638,7 @@ type ChainGovernorStatus_Emitter struct { func (x *ChainGovernorStatus_Emitter) Reset() { *x = ChainGovernorStatus_Emitter{} if protoimpl.UnsafeEnabled { - mi := &file_gossip_v1_gossip_proto_msgTypes[17] + mi := &file_gossip_v1_gossip_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1425,7 +1651,7 @@ func (x *ChainGovernorStatus_Emitter) String() string { func (*ChainGovernorStatus_Emitter) ProtoMessage() {} func (x *ChainGovernorStatus_Emitter) ProtoReflect() protoreflect.Message { - mi := &file_gossip_v1_gossip_proto_msgTypes[17] + mi := &file_gossip_v1_gossip_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1475,7 +1701,7 @@ type ChainGovernorStatus_Chain struct { func (x *ChainGovernorStatus_Chain) Reset() { *x = ChainGovernorStatus_Chain{} if protoimpl.UnsafeEnabled { - mi := &file_gossip_v1_gossip_proto_msgTypes[18] + mi := &file_gossip_v1_gossip_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1488,7 +1714,7 @@ func (x *ChainGovernorStatus_Chain) String() string { func (*ChainGovernorStatus_Chain) ProtoMessage() {} func (x *ChainGovernorStatus_Chain) ProtoReflect() protoreflect.Message { - mi := &file_gossip_v1_gossip_proto_msgTypes[18] + mi := &file_gossip_v1_gossip_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1530,7 +1756,7 @@ var File_gossip_v1_gossip_proto protoreflect.FileDescriptor var file_gossip_v1_gossip_proto_rawDesc = []byte{ 0x0a, 0x16, 0x67, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x67, 0x6f, 0x73, 0x73, 0x69, 0x70, - 0x2e, 0x76, 0x31, 0x22, 0x86, 0x06, 0x0a, 0x0d, 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x4d, 0x65, + 0x2e, 0x76, 0x31, 0x22, 0xd9, 0x06, 0x0a, 0x0d, 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x4d, 0x0a, 0x12, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, @@ -1578,180 +1804,209 @@ var file_gossip_v1_gossip_proto_rawDesc = []byte{ 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x47, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x48, 0x00, 0x52, 0x19, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x47, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x72, 0x0a, 0x0f, - 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x12, - 0x1c, 0x0a, 0x09, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x09, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x12, 0x1c, 0x0a, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x67, - 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x0c, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x41, 0x64, 0x64, 0x72, - 0x22, 0xbb, 0x03, 0x0a, 0x09, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x12, 0x1b, - 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x12, 0x38, 0x0a, 0x08, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x18, - 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x2e, 0x76, - 0x31, 0x2e, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x2e, 0x4e, 0x65, 0x74, 0x77, - 0x6f, 0x72, 0x6b, 0x52, 0x08, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x12, 0x18, 0x0a, - 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x67, 0x75, 0x61, 0x72, 0x64, - 0x69, 0x61, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x12, 0x25, 0x0a, 0x0e, - 0x62, 0x6f, 0x6f, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x62, 0x6f, 0x6f, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, - 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, - 0x1e, 0x0a, 0x0b, 0x70, 0x32, 0x70, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x32, 0x70, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x1a, - 0x7d, 0x0a, 0x07, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, - 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1f, 0x0a, - 0x0b, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x0a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x91, - 0x01, 0x0a, 0x11, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, + 0x73, 0x12, 0x51, 0x0a, 0x14, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, + 0x65, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, + 0x52, 0x12, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, + 0x72, 0x0a, 0x0f, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, + 0x61, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, + 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x23, + 0x0a, 0x0d, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x41, + 0x64, 0x64, 0x72, 0x22, 0xbb, 0x03, 0x0a, 0x09, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, + 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x38, 0x0a, 0x08, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, + 0x6b, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x73, 0x69, + 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x2e, 0x4e, + 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x08, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, + 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x67, 0x75, + 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x12, + 0x25, 0x0a, 0x0e, 0x62, 0x6f, 0x6f, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x62, 0x6f, 0x6f, 0x74, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x70, 0x32, 0x70, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, + 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x32, 0x70, 0x4e, 0x6f, 0x64, 0x65, + 0x49, 0x64, 0x1a, 0x7d, 0x0a, 0x07, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, + 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x68, + 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, + 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x12, 0x1f, 0x0a, 0x0b, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x22, 0x91, 0x01, 0x0a, 0x11, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x4f, 0x62, 0x73, 0x65, + 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, + 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, + 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x17, 0x0a, + 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, + 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x49, 0x64, 0x22, 0x27, 0x0a, 0x13, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, + 0x41, 0x41, 0x57, 0x69, 0x74, 0x68, 0x51, 0x75, 0x6f, 0x72, 0x75, 0x6d, 0x12, 0x10, 0x0a, 0x03, + 0x76, 0x61, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x76, 0x61, 0x61, 0x22, 0x8e, + 0x01, 0x0a, 0x18, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x13, 0x6f, + 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x12, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x67, 0x75, + 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x0c, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x22, + 0x48, 0x0a, 0x12, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, + 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x22, 0xbf, 0x01, 0x0a, 0x16, 0x53, 0x69, + 0x67, 0x6e, 0x65, 0x64, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, - 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x74, 0x78, 0x48, - 0x61, 0x73, 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, - 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x49, 0x64, 0x22, 0x27, 0x0a, 0x13, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x41, 0x41, 0x57, - 0x69, 0x74, 0x68, 0x51, 0x75, 0x6f, 0x72, 0x75, 0x6d, 0x12, 0x10, 0x0a, 0x03, 0x76, 0x61, 0x61, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x76, 0x61, 0x61, 0x22, 0x8e, 0x01, 0x0a, 0x18, - 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x13, 0x6f, 0x62, 0x73, 0x65, - 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x12, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x67, 0x75, 0x61, 0x72, 0x64, - 0x69, 0x61, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, - 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x22, 0x48, 0x0a, 0x12, - 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x17, 0x0a, - 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, - 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x22, 0xbf, 0x01, 0x0a, 0x16, 0x53, 0x69, 0x67, 0x6e, 0x65, - 0x64, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x04, 0x61, 0x64, 0x64, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x13, 0x0a, 0x05, 0x74, 0x78, 0x5f, 0x69, 0x64, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x74, 0x78, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, - 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, - 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x19, 0x0a, - 0x08, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x62, 0x61, 0x74, 0x63, 0x68, 0x49, 0x64, 0x22, 0x98, 0x01, 0x0a, 0x18, 0x53, 0x69, 0x67, - 0x6e, 0x65, 0x64, 0x42, 0x61, 0x74, 0x63, 0x68, 0x56, 0x41, 0x41, 0x57, 0x69, 0x74, 0x68, 0x51, - 0x75, 0x6f, 0x72, 0x75, 0x6d, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x76, - 0x61, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x62, 0x61, 0x74, 0x63, 0x68, 0x56, - 0x61, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x13, 0x0a, - 0x05, 0x74, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x74, 0x78, - 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0d, 0x52, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x61, 0x74, 0x63, - 0x68, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x61, 0x74, 0x63, - 0x68, 0x49, 0x64, 0x22, 0x76, 0x0a, 0x19, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x47, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x6f, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, - 0x61, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x67, - 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x22, 0xd1, 0x03, 0x0a, 0x13, + 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x13, 0x0a, 0x05, 0x74, 0x78, + 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x74, 0x78, 0x49, 0x64, 0x12, + 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, + 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, + 0x12, 0x19, 0x0a, 0x08, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x62, 0x61, 0x74, 0x63, 0x68, 0x49, 0x64, 0x22, 0x98, 0x01, 0x0a, 0x18, + 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x61, 0x74, 0x63, 0x68, 0x56, 0x41, 0x41, 0x57, 0x69, + 0x74, 0x68, 0x51, 0x75, 0x6f, 0x72, 0x75, 0x6d, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x61, 0x74, 0x63, + 0x68, 0x5f, 0x76, 0x61, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x62, 0x61, 0x74, + 0x63, 0x68, 0x56, 0x61, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, + 0x12, 0x13, 0x0a, 0x05, 0x74, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x04, 0x74, 0x78, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x62, + 0x61, 0x74, 0x63, 0x68, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, + 0x61, 0x74, 0x63, 0x68, 0x49, 0x64, 0x22, 0x76, 0x0a, 0x19, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x47, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x6f, 0x72, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, - 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x3c, 0x0a, 0x06, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x73, 0x73, 0x69, - 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x47, 0x6f, 0x76, 0x65, 0x72, 0x6e, - 0x6f, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x06, - 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x3c, 0x0a, 0x06, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, - 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x47, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x6f, 0x72, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x06, 0x74, 0x6f, - 0x6b, 0x65, 0x6e, 0x73, 0x1a, 0x7b, 0x0a, 0x05, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x19, 0x0a, - 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x6e, 0x6f, 0x74, 0x69, - 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x0d, 0x6e, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, - 0x30, 0x0a, 0x14, 0x62, 0x69, 0x67, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x12, 0x62, - 0x69, 0x67, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x69, 0x7a, - 0x65, 0x1a, 0x6c, 0x0a, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x26, 0x0a, 0x0f, 0x6f, 0x72, - 0x69, 0x67, 0x69, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x5f, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6f, 0x72, 0x69, 0x67, - 0x69, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x69, - 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x22, - 0x76, 0x0a, 0x19, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x47, 0x6f, - 0x76, 0x65, 0x72, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x5f, 0x61, - 0x64, 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x67, 0x75, 0x61, 0x72, 0x64, - 0x69, 0x61, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x22, 0x98, 0x05, 0x0a, 0x13, 0x43, 0x68, 0x61, 0x69, + 0x66, 0x69, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x67, 0x75, 0x61, + 0x72, 0x64, 0x69, 0x61, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x0c, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x22, 0xd1, + 0x03, 0x0a, 0x13, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x47, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x6f, 0x72, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x1c, 0x0a, + 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x3c, 0x0a, 0x06, 0x63, + 0x68, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, + 0x73, 0x73, 0x69, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x47, 0x6f, 0x76, + 0x65, 0x72, 0x6e, 0x6f, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x52, 0x06, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x3c, 0x0a, 0x06, 0x74, 0x6f, 0x6b, + 0x65, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x73, 0x73, + 0x69, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x47, 0x6f, 0x76, 0x65, 0x72, + 0x6e, 0x6f, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, + 0x06, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x1a, 0x7b, 0x0a, 0x05, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x6e, + 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x0d, 0x6e, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x4c, 0x69, 0x6d, + 0x69, 0x74, 0x12, 0x30, 0x0a, 0x14, 0x62, 0x69, 0x67, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x12, 0x62, 0x69, 0x67, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x53, 0x69, 0x7a, 0x65, 0x1a, 0x6c, 0x0a, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x26, 0x0a, + 0x0f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x5f, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6f, + 0x72, 0x69, 0x67, 0x69, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, + 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x70, 0x72, 0x69, + 0x63, 0x65, 0x22, 0x76, 0x0a, 0x19, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x47, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, - 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x12, 0x3c, 0x0a, 0x06, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x04, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x47, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x6f, 0x72, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x73, 0x1a, 0x8c, 0x01, 0x0a, 0x0b, 0x45, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x64, 0x56, - 0x41, 0x41, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x21, - 0x0a, 0x0c, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x54, 0x69, 0x6d, - 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x6e, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x6e, 0x6f, 0x74, 0x69, 0x6f, - 0x6e, 0x61, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, - 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, - 0x68, 0x1a, 0xb3, 0x01, 0x0a, 0x07, 0x45, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x12, 0x27, 0x0a, - 0x0f, 0x65, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, - 0x65, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x64, 0x5f, 0x76, 0x61, 0x61, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x11, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x45, 0x6e, 0x71, 0x75, 0x65, 0x75, - 0x65, 0x64, 0x56, 0x61, 0x61, 0x73, 0x12, 0x4f, 0x0a, 0x0d, 0x65, 0x6e, 0x71, 0x75, 0x65, 0x75, - 0x65, 0x64, 0x5f, 0x76, 0x61, 0x61, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, - 0x67, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x47, - 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x45, 0x6e, - 0x71, 0x75, 0x65, 0x75, 0x65, 0x64, 0x56, 0x41, 0x41, 0x52, 0x0c, 0x65, 0x6e, 0x71, 0x75, 0x65, - 0x75, 0x65, 0x64, 0x56, 0x61, 0x61, 0x73, 0x1a, 0xa8, 0x01, 0x0a, 0x05, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x40, 0x0a, 0x1c, - 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, - 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x1a, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x76, 0x61, - 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x12, 0x42, - 0x0a, 0x08, 0x65, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, + 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, + 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x67, 0x75, + 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x22, 0x98, 0x05, 0x0a, 0x13, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x47, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x3c, 0x0a, 0x06, 0x63, 0x68, 0x61, 0x69, 0x6e, + 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x73, 0x73, 0x69, 0x70, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x47, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x6f, + 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x63, + 0x68, 0x61, 0x69, 0x6e, 0x73, 0x1a, 0x8c, 0x01, 0x0a, 0x0b, 0x45, 0x6e, 0x71, 0x75, 0x65, 0x75, + 0x65, 0x64, 0x56, 0x41, 0x41, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, + 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x74, 0x69, 0x6d, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, + 0x54, 0x69, 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x6e, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, + 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x6e, 0x6f, + 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x74, + 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, + 0x48, 0x61, 0x73, 0x68, 0x1a, 0xb3, 0x01, 0x0a, 0x07, 0x45, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, + 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x6d, 0x69, 0x74, 0x74, + 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x74, 0x6f, 0x74, + 0x61, 0x6c, 0x5f, 0x65, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x64, 0x5f, 0x76, 0x61, 0x61, 0x73, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x45, 0x6e, 0x71, + 0x75, 0x65, 0x75, 0x65, 0x64, 0x56, 0x61, 0x61, 0x73, 0x12, 0x4f, 0x0a, 0x0d, 0x65, 0x6e, 0x71, + 0x75, 0x65, 0x75, 0x65, 0x64, 0x5f, 0x76, 0x61, 0x61, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x47, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x2e, 0x45, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x52, 0x08, 0x65, 0x6d, 0x69, 0x74, 0x74, 0x65, - 0x72, 0x73, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x63, 0x65, 0x72, 0x74, 0x75, 0x73, 0x6f, 0x6e, 0x65, 0x2f, 0x77, 0x6f, 0x72, 0x6d, 0x68, - 0x6f, 0x6c, 0x65, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x2f, 0x76, 0x31, 0x3b, 0x67, 0x6f, 0x73, - 0x73, 0x69, 0x70, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2e, 0x45, 0x6e, 0x71, 0x75, 0x65, 0x75, 0x65, 0x64, 0x56, 0x41, 0x41, 0x52, 0x0c, 0x65, 0x6e, + 0x71, 0x75, 0x65, 0x75, 0x65, 0x64, 0x56, 0x61, 0x61, 0x73, 0x1a, 0xa8, 0x01, 0x0a, 0x05, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, + 0x40, 0x0a, 0x1c, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x76, 0x61, + 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1a, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, + 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x61, + 0x6c, 0x12, 0x42, 0x0a, 0x08, 0x65, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x68, 0x61, 0x69, 0x6e, 0x47, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x2e, 0x45, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x52, 0x08, 0x65, 0x6d, 0x69, + 0x74, 0x74, 0x65, 0x72, 0x73, 0x22, 0x7e, 0x0a, 0x12, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x71, + 0x75, 0x65, 0x72, 0x79, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x0c, 0x71, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x25, + 0x0a, 0x0e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x6f, + 0x72, 0x41, 0x64, 0x64, 0x72, 0x22, 0xa1, 0x01, 0x0a, 0x0c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, + 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x55, 0x0a, 0x16, 0x65, 0x74, 0x68, 0x5f, 0x63, + 0x61, 0x6c, 0x6c, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x73, 0x73, 0x69, 0x70, + 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x43, 0x61, 0x6c, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x13, 0x65, 0x74, 0x68, 0x43, 0x61, + 0x6c, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x09, + 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x4f, 0x0a, 0x13, 0x45, 0x74, 0x68, + 0x43, 0x61, 0x6c, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x74, 0x6f, + 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, + 0x64, 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x75, 0x73, 0x6f, + 0x6e, 0x65, 0x2f, 0x77, 0x6f, 0x72, 0x6d, 0x68, 0x6f, 0x6c, 0x65, 0x2f, 0x6e, 0x6f, 0x64, 0x65, + 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x73, 0x69, + 0x70, 0x2f, 0x76, 0x31, 0x3b, 0x67, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x76, 0x31, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1766,7 +2021,7 @@ func file_gossip_v1_gossip_proto_rawDescGZIP() []byte { return file_gossip_v1_gossip_proto_rawDescData } -var file_gossip_v1_gossip_proto_msgTypes = make([]protoimpl.MessageInfo, 19) +var file_gossip_v1_gossip_proto_msgTypes = make([]protoimpl.MessageInfo, 22) var file_gossip_v1_gossip_proto_goTypes = []interface{}{ (*GossipMessage)(nil), // 0: gossip.v1.GossipMessage (*SignedHeartbeat)(nil), // 1: gossip.v1.SignedHeartbeat @@ -1781,12 +2036,15 @@ var file_gossip_v1_gossip_proto_goTypes = []interface{}{ (*ChainGovernorConfig)(nil), // 10: gossip.v1.ChainGovernorConfig (*SignedChainGovernorStatus)(nil), // 11: gossip.v1.SignedChainGovernorStatus (*ChainGovernorStatus)(nil), // 12: gossip.v1.ChainGovernorStatus - (*Heartbeat_Network)(nil), // 13: gossip.v1.Heartbeat.Network - (*ChainGovernorConfig_Chain)(nil), // 14: gossip.v1.ChainGovernorConfig.Chain - (*ChainGovernorConfig_Token)(nil), // 15: gossip.v1.ChainGovernorConfig.Token - (*ChainGovernorStatus_EnqueuedVAA)(nil), // 16: gossip.v1.ChainGovernorStatus.EnqueuedVAA - (*ChainGovernorStatus_Emitter)(nil), // 17: gossip.v1.ChainGovernorStatus.Emitter - (*ChainGovernorStatus_Chain)(nil), // 18: gossip.v1.ChainGovernorStatus.Chain + (*SignedQueryRequest)(nil), // 13: gossip.v1.SignedQueryRequest + (*QueryRequest)(nil), // 14: gossip.v1.QueryRequest + (*EthCallQueryRequest)(nil), // 15: gossip.v1.EthCallQueryRequest + (*Heartbeat_Network)(nil), // 16: gossip.v1.Heartbeat.Network + (*ChainGovernorConfig_Chain)(nil), // 17: gossip.v1.ChainGovernorConfig.Chain + (*ChainGovernorConfig_Token)(nil), // 18: gossip.v1.ChainGovernorConfig.Token + (*ChainGovernorStatus_EnqueuedVAA)(nil), // 19: gossip.v1.ChainGovernorStatus.EnqueuedVAA + (*ChainGovernorStatus_Emitter)(nil), // 20: gossip.v1.ChainGovernorStatus.Emitter + (*ChainGovernorStatus_Chain)(nil), // 21: gossip.v1.ChainGovernorStatus.Chain } var file_gossip_v1_gossip_proto_depIdxs = []int32{ 3, // 0: gossip.v1.GossipMessage.signed_observation:type_name -> gossip.v1.SignedObservation @@ -1797,17 +2055,19 @@ var file_gossip_v1_gossip_proto_depIdxs = []int32{ 8, // 5: gossip.v1.GossipMessage.signed_batch_vaa_with_quorum:type_name -> gossip.v1.SignedBatchVAAWithQuorum 9, // 6: gossip.v1.GossipMessage.signed_chain_governor_config:type_name -> gossip.v1.SignedChainGovernorConfig 11, // 7: gossip.v1.GossipMessage.signed_chain_governor_status:type_name -> gossip.v1.SignedChainGovernorStatus - 13, // 8: gossip.v1.Heartbeat.networks:type_name -> gossip.v1.Heartbeat.Network - 14, // 9: gossip.v1.ChainGovernorConfig.chains:type_name -> gossip.v1.ChainGovernorConfig.Chain - 15, // 10: gossip.v1.ChainGovernorConfig.tokens:type_name -> gossip.v1.ChainGovernorConfig.Token - 18, // 11: gossip.v1.ChainGovernorStatus.chains:type_name -> gossip.v1.ChainGovernorStatus.Chain - 16, // 12: gossip.v1.ChainGovernorStatus.Emitter.enqueued_vaas:type_name -> gossip.v1.ChainGovernorStatus.EnqueuedVAA - 17, // 13: gossip.v1.ChainGovernorStatus.Chain.emitters:type_name -> gossip.v1.ChainGovernorStatus.Emitter - 14, // [14:14] is the sub-list for method output_type - 14, // [14:14] is the sub-list for method input_type - 14, // [14:14] is the sub-list for extension type_name - 14, // [14:14] is the sub-list for extension extendee - 0, // [0:14] is the sub-list for field type_name + 13, // 8: gossip.v1.GossipMessage.signed_query_request:type_name -> gossip.v1.SignedQueryRequest + 16, // 9: gossip.v1.Heartbeat.networks:type_name -> gossip.v1.Heartbeat.Network + 17, // 10: gossip.v1.ChainGovernorConfig.chains:type_name -> gossip.v1.ChainGovernorConfig.Chain + 18, // 11: gossip.v1.ChainGovernorConfig.tokens:type_name -> gossip.v1.ChainGovernorConfig.Token + 21, // 12: gossip.v1.ChainGovernorStatus.chains:type_name -> gossip.v1.ChainGovernorStatus.Chain + 15, // 13: gossip.v1.QueryRequest.eth_call_query_request:type_name -> gossip.v1.EthCallQueryRequest + 19, // 14: gossip.v1.ChainGovernorStatus.Emitter.enqueued_vaas:type_name -> gossip.v1.ChainGovernorStatus.EnqueuedVAA + 20, // 15: gossip.v1.ChainGovernorStatus.Chain.emitters:type_name -> gossip.v1.ChainGovernorStatus.Emitter + 16, // [16:16] is the sub-list for method output_type + 16, // [16:16] is the sub-list for method input_type + 16, // [16:16] is the sub-list for extension type_name + 16, // [16:16] is the sub-list for extension extendee + 0, // [0:16] is the sub-list for field type_name } func init() { file_gossip_v1_gossip_proto_init() } @@ -1973,7 +2233,7 @@ func file_gossip_v1_gossip_proto_init() { } } file_gossip_v1_gossip_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Heartbeat_Network); i { + switch v := v.(*SignedQueryRequest); i { case 0: return &v.state case 1: @@ -1985,7 +2245,7 @@ func file_gossip_v1_gossip_proto_init() { } } file_gossip_v1_gossip_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ChainGovernorConfig_Chain); i { + switch v := v.(*QueryRequest); i { case 0: return &v.state case 1: @@ -1997,7 +2257,7 @@ func file_gossip_v1_gossip_proto_init() { } } file_gossip_v1_gossip_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ChainGovernorConfig_Token); i { + switch v := v.(*EthCallQueryRequest); i { case 0: return &v.state case 1: @@ -2009,7 +2269,7 @@ func file_gossip_v1_gossip_proto_init() { } } file_gossip_v1_gossip_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ChainGovernorStatus_EnqueuedVAA); i { + switch v := v.(*Heartbeat_Network); i { case 0: return &v.state case 1: @@ -2021,7 +2281,7 @@ func file_gossip_v1_gossip_proto_init() { } } file_gossip_v1_gossip_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ChainGovernorStatus_Emitter); i { + switch v := v.(*ChainGovernorConfig_Chain); i { case 0: return &v.state case 1: @@ -2033,6 +2293,42 @@ func file_gossip_v1_gossip_proto_init() { } } file_gossip_v1_gossip_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ChainGovernorConfig_Token); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gossip_v1_gossip_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ChainGovernorStatus_EnqueuedVAA); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gossip_v1_gossip_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ChainGovernorStatus_Emitter); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gossip_v1_gossip_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ChainGovernorStatus_Chain); i { case 0: return &v.state @@ -2054,6 +2350,10 @@ func file_gossip_v1_gossip_proto_init() { (*GossipMessage_SignedBatchVaaWithQuorum)(nil), (*GossipMessage_SignedChainGovernorConfig)(nil), (*GossipMessage_SignedChainGovernorStatus)(nil), + (*GossipMessage_SignedQueryRequest)(nil), + } + file_gossip_v1_gossip_proto_msgTypes[14].OneofWrappers = []interface{}{ + (*QueryRequest_EthCallQueryRequest)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -2061,7 +2361,7 @@ func file_gossip_v1_gossip_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_gossip_v1_gossip_proto_rawDesc, NumEnums: 0, - NumMessages: 19, + NumMessages: 22, NumExtensions: 0, NumServices: 0, }, diff --git a/node/pkg/watchers/evm/watcher.go b/node/pkg/watchers/evm/watcher.go index b935e15bf7..af483c8c8a 100644 --- a/node/pkg/watchers/evm/watcher.go +++ b/node/pkg/watchers/evm/watcher.go @@ -94,6 +94,10 @@ type ( // include requests for our chainID. obsvReqC <-chan *gossipv1.ObservationRequest + // Incoming query requests from the network. Pre-filtered to only + // include requests for our chainID. + queryReqC <-chan *gossipv1.QueryRequest + pending map[pendingKey]*pendingMessage pendingMu sync.Mutex @@ -143,6 +147,7 @@ func NewEthWatcher( msgC chan<- *common.MessagePublication, setC chan<- *common.GuardianSet, obsvReqC <-chan *gossipv1.ObservationRequest, + queryReqC <-chan *gossipv1.QueryRequest, unsafeDevMode bool, ) *Watcher { @@ -157,6 +162,7 @@ func NewEthWatcher( msgC: msgC, setC: setC, obsvReqC: obsvReqC, + queryReqC: queryReqC, pending: map[pendingKey]*pendingMessage{}, unsafeDevMode: unsafeDevMode, } @@ -527,6 +533,84 @@ func (w *Watcher) Run(parentCtx context.Context) error { } }) + common.RunWithScissors(ctx, errC, "evm_fetch_query_req", func(ctx context.Context) error { + for { + select { + case <-ctx.Done(): + return nil + case queryRequest := <-w.queryReqC: + // This can't happen unless there is a programming error - the caller + // is expected to send us only requests for our chainID. + if vaa.ChainID(queryRequest.ChainId) != w.chainID { + panic("invalid chain ID") + } + + switch req := queryRequest.Message.(type) { + case *gossipv1.QueryRequest_EthCallQueryRequest: + to := eth_common.BytesToAddress(req.EthCallQueryRequest.To) + data := eth_hexutil.Encode(req.EthCallQueryRequest.Data) + block := req.EthCallQueryRequest.Block + logger.Info("received query request", + zap.String("eth_network", w.networkName), + zap.String("to", to.Hex()), + zap.Any("data", data), + zap.String("block", block)) + + timeout, cancel := context.WithTimeout(ctx, 5*time.Second) + // like https://github.com/ethereum/go-ethereum/blob/master/ethclient/ethclient.go#L610 + arg := map[string]interface{}{ + "to": to, + "data": data, + } + var blockArg interface{} + // TODO: try making these error and see what happens + // 1. 66 chars but not 0x hex + // 2. 64 chars but not hex + // 3. bad blocks + // 4. bad 0x lengths + // 5. strings that aren't "latest", "safe", "finalized" + // 6. "safe" on a chain that doesn't support safe + // etc? + // I would expect this to trip within this scissor (if at all) but maybe this should get more defensive + if (len(block) == 66 || len(block) == 64) { + // looks like a hash which requires the object parameter + // https://docs.alchemy.com/reference/eth-call + hash := eth_common.HexToHash(block) + blockArg = rpc.BlockNumberOrHash{ + BlockHash: &hash, + } + } else { + blockArg = block + } + var result string + err := w.ethConn.RawCallContext(timeout, &result, "eth_call", arg, blockArg) + cancel() + + if err != nil { + logger.Error("failed to process query request", + zap.Error(err), zap.String("eth_network", w.networkName), + zap.String("to", to.Hex()), + zap.Any("data", data), + zap.String("block", block)) + continue + } + + // TODO: error on "0x" response + + logger.Info("query result", + zap.String("eth_network", w.networkName), + zap.String("to", to.Hex()), + zap.Any("data", data), + zap.String("block", block), + zap.String("result", result)) + default: + logger.Warn("received unsupported request type", + zap.Any("payload", queryRequest.Message)) + } + } + } + }) + common.RunWithScissors(ctx, errC, "evm_fetch_messages", func(ctx context.Context) error { for { select { diff --git a/proto/gossip/v1/gossip.proto b/proto/gossip/v1/gossip.proto index 19d8a4ac83..0e9841721f 100644 --- a/proto/gossip/v1/gossip.proto +++ b/proto/gossip/v1/gossip.proto @@ -14,6 +14,7 @@ message GossipMessage { SignedBatchVAAWithQuorum signed_batch_vaa_with_quorum = 7; SignedChainGovernorConfig signed_chain_governor_config = 8; SignedChainGovernorStatus signed_chain_governor_status = 9; + SignedQueryRequest signed_query_request = 10; } } @@ -231,3 +232,28 @@ message ChainGovernorStatus { int64 timestamp = 3; repeated Chain chains = 4; } + +message SignedQueryRequest { + // Serialized QueryRequest message. + bytes query_request = 1; + + // ECDSA signature using the requestor's public key. + bytes signature = 2; + + // Requestor address that signed this payload (truncated Eth address). + bytes requestor_addr = 3; +} + +message QueryRequest { + uint32 chain_id = 1; + uint32 nonce = 2; + oneof message { + EthCallQueryRequest eth_call_query_request = 3; + } +} + +message EthCallQueryRequest { + bytes to = 1; + bytes data = 2; + string block = 3; +}