From bfae7f3c9fa30cf0d513b59ad95cc99a5316eacd Mon Sep 17 00:00:00 2001 From: james-prysm <90280386+james-prysm@users.noreply.github.com> Date: Mon, 16 Oct 2023 17:16:20 -0500 Subject: [PATCH] HTTP VALIDATOR API: `/eth/v1/validator/{pubkey}/voluntary_exit` (#13032) * migrating set validator exit to http only and removing from api middleware * fixing ineffassign error * cleaning up middleware * fixing linting * Update validator/rpc/handlers_keymanager.go Co-authored-by: Sammy Rosso <15244892+saolyn@users.noreply.github.com> * Update validator/rpc/handlers_keymanager.go Co-authored-by: Sammy Rosso <15244892+saolyn@users.noreply.github.com> * Update validator/rpc/handlers_keymanager.go Co-authored-by: Sammy Rosso <15244892+saolyn@users.noreply.github.com> * adding more tests based on sammy's comments * radek's feedback * adjusting error codes * one more status change * fixing unit test --------- Co-authored-by: Sammy Rosso <15244892+saolyn@users.noreply.github.com> Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> --- api/server/BUILD.bazel | 21 + .../router.go => api/server/middleware.go | 8 +- .../eth/helpers/http.go => api/server/util.go | 2 +- .../http_test.go => api/server/util_test.go | 2 +- beacon-chain/node/BUILD.bazel | 3 +- beacon-chain/node/node.go | 3 +- beacon-chain/rpc/eth/beacon/handlers.go | 2 +- beacon-chain/rpc/eth/helpers/BUILD.bazel | 2 - proto/eth/service/key_management.pb.go | 1057 ++++++----------- proto/eth/service/key_management.pb.gw.go | 117 -- proto/eth/service/key_management.proto | 37 - validator/node/BUILD.bazel | 1 + validator/node/node.go | 74 +- validator/rpc/BUILD.bazel | 9 + validator/rpc/apimiddleware/BUILD.bazel | 9 +- validator/rpc/apimiddleware/custom_hooks.go | 39 - .../rpc/apimiddleware/custom_hooks_test.go | 49 - .../rpc/apimiddleware/endpoint_factory.go | 7 - validator/rpc/apimiddleware/structs.go | 19 - validator/rpc/handlers_keymanager.go | 94 ++ validator/rpc/handlers_keymanager_test.go | 218 ++++ validator/rpc/server.go | 9 +- validator/rpc/standard_api.go | 50 - validator/rpc/standard_api_test.go | 118 -- validator/rpc/structs.go | 7 + 25 files changed, 758 insertions(+), 1199 deletions(-) create mode 100644 api/server/BUILD.bazel rename beacon-chain/node/router.go => api/server/middleware.go (52%) rename beacon-chain/rpc/eth/helpers/http.go => api/server/util.go (95%) rename beacon-chain/rpc/eth/helpers/http_test.go => api/server/util_test.go (97%) delete mode 100644 validator/rpc/apimiddleware/custom_hooks.go delete mode 100644 validator/rpc/apimiddleware/custom_hooks_test.go create mode 100644 validator/rpc/handlers_keymanager.go create mode 100644 validator/rpc/handlers_keymanager_test.go create mode 100644 validator/rpc/structs.go diff --git a/api/server/BUILD.bazel b/api/server/BUILD.bazel new file mode 100644 index 0000000000..dd5fa0332e --- /dev/null +++ b/api/server/BUILD.bazel @@ -0,0 +1,21 @@ +load("@prysm//tools/go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "middleware.go", + "util.go", + ], + importpath = "github.com/prysmaticlabs/prysm/v4/api/server", + visibility = ["//visibility:public"], +) + +go_test( + name = "go_default_test", + srcs = ["util_test.go"], + embed = [":go_default_library"], + deps = [ + "//testing/assert:go_default_library", + "//testing/require:go_default_library", + ], +) diff --git a/beacon-chain/node/router.go b/api/server/middleware.go similarity index 52% rename from beacon-chain/node/router.go rename to api/server/middleware.go index b05ec37051..670dff2be5 100644 --- a/beacon-chain/node/router.go +++ b/api/server/middleware.go @@ -1,15 +1,13 @@ -package node +package server import ( "net/http" - - "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/helpers" ) -func middleware(next http.Handler) http.Handler { +func NormalizeQueryValuesHandler(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { query := r.URL.Query() - helpers.NormalizeQueryValues(query) + NormalizeQueryValues(query) r.URL.RawQuery = query.Encode() next.ServeHTTP(w, r) diff --git a/beacon-chain/rpc/eth/helpers/http.go b/api/server/util.go similarity index 95% rename from beacon-chain/rpc/eth/helpers/http.go rename to api/server/util.go index 0056dda1d3..5fbcd9eaef 100644 --- a/beacon-chain/rpc/eth/helpers/http.go +++ b/api/server/util.go @@ -1,4 +1,4 @@ -package helpers +package server import ( "net/url" diff --git a/beacon-chain/rpc/eth/helpers/http_test.go b/api/server/util_test.go similarity index 97% rename from beacon-chain/rpc/eth/helpers/http_test.go rename to api/server/util_test.go index bcc1052ba5..ada0d35496 100644 --- a/beacon-chain/rpc/eth/helpers/http_test.go +++ b/api/server/util_test.go @@ -1,4 +1,4 @@ -package helpers +package server import ( "testing" diff --git a/beacon-chain/node/BUILD.bazel b/beacon-chain/node/BUILD.bazel index 84f6a00633..6f5bee643a 100644 --- a/beacon-chain/node/BUILD.bazel +++ b/beacon-chain/node/BUILD.bazel @@ -8,7 +8,6 @@ go_library( "node.go", "options.go", "prometheus.go", - "router.go", ], importpath = "github.com/prysmaticlabs/prysm/v4/beacon-chain/node", visibility = [ @@ -17,6 +16,7 @@ go_library( ], deps = [ "//api/gateway:go_default_library", + "//api/server:go_default_library", "//async/event:go_default_library", "//beacon-chain/blockchain:go_default_library", "//beacon-chain/builder:go_default_library", @@ -41,7 +41,6 @@ go_library( "//beacon-chain/p2p:go_default_library", "//beacon-chain/rpc:go_default_library", "//beacon-chain/rpc/apimiddleware:go_default_library", - "//beacon-chain/rpc/eth/helpers:go_default_library", "//beacon-chain/slasher:go_default_library", "//beacon-chain/startup:go_default_library", "//beacon-chain/state:go_default_library", diff --git a/beacon-chain/node/node.go b/beacon-chain/node/node.go index 6104c10dd4..517787a3c4 100644 --- a/beacon-chain/node/node.go +++ b/beacon-chain/node/node.go @@ -18,6 +18,7 @@ import ( "github.com/gorilla/mux" "github.com/pkg/errors" apigateway "github.com/prysmaticlabs/prysm/v4/api/gateway" + "github.com/prysmaticlabs/prysm/v4/api/server" "github.com/prysmaticlabs/prysm/v4/async/event" "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain" "github.com/prysmaticlabs/prysm/v4/beacon-chain/builder" @@ -271,7 +272,7 @@ func New(cliCtx *cli.Context, opts ...Option) (*BeaconNode, error) { log.Debugln("Registering RPC Service") router := mux.NewRouter() - router.Use(middleware) + router.Use(server.NormalizeQueryValuesHandler) if err := beacon.registerRPCService(router); err != nil { return nil, err } diff --git a/beacon-chain/rpc/eth/beacon/handlers.go b/beacon-chain/rpc/eth/beacon/handlers.go index 89607de170..168ae64223 100644 --- a/beacon-chain/rpc/eth/beacon/handlers.go +++ b/beacon-chain/rpc/eth/beacon/handlers.go @@ -814,7 +814,7 @@ func (s *Server) GetBlockHeaders(w http.ResponseWriter, r *http.Request) { var blkRoots [][32]byte if rawParentRoot != "" { - parentRoot, valid := shared.ValidateHex(w, "Parent Root", rawParentRoot, 32) + parentRoot, valid := shared.ValidateHex(w, "Parent Root", rawParentRoot, fieldparams.RootLength) if !valid { return } diff --git a/beacon-chain/rpc/eth/helpers/BUILD.bazel b/beacon-chain/rpc/eth/helpers/BUILD.bazel index bd21fd7591..6dfd51c5e6 100644 --- a/beacon-chain/rpc/eth/helpers/BUILD.bazel +++ b/beacon-chain/rpc/eth/helpers/BUILD.bazel @@ -4,7 +4,6 @@ go_library( name = "go_default_library", srcs = [ "error_handling.go", - "http.go", "sync.go", "validator_status.go", ], @@ -36,7 +35,6 @@ go_library( go_test( name = "go_default_test", srcs = [ - "http_test.go", "sync_test.go", "validator_status_test.go", ], diff --git a/proto/eth/service/key_management.pb.go b/proto/eth/service/key_management.pb.go index 9b9a4c22d8..0724d65ba7 100755 --- a/proto/eth/service/key_management.pb.go +++ b/proto/eth/service/key_management.pb.go @@ -11,8 +11,6 @@ import ( reflect "reflect" sync "sync" - github_com_prysmaticlabs_prysm_v4_consensus_types_primitives "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives" - _ "github.com/prysmaticlabs/prysm/v4/proto/eth/ext" _ "google.golang.org/genproto/googleapis/api/annotations" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" @@ -1244,108 +1242,6 @@ func (x *DeleteGasLimitRequest) GetPubkey() []byte { return nil } -type SetVoluntaryExitRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Pubkey []byte `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty" ssz-size:"48"` - Epoch github_com_prysmaticlabs_prysm_v4_consensus_types_primitives.Epoch `protobuf:"varint,2,opt,name=epoch,proto3" json:"epoch,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives.Epoch"` -} - -func (x *SetVoluntaryExitRequest) Reset() { - *x = SetVoluntaryExitRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_service_key_management_proto_msgTypes[20] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SetVoluntaryExitRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SetVoluntaryExitRequest) ProtoMessage() {} - -func (x *SetVoluntaryExitRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_service_key_management_proto_msgTypes[20] - 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 SetVoluntaryExitRequest.ProtoReflect.Descriptor instead. -func (*SetVoluntaryExitRequest) Descriptor() ([]byte, []int) { - return file_proto_eth_service_key_management_proto_rawDescGZIP(), []int{20} -} - -func (x *SetVoluntaryExitRequest) GetPubkey() []byte { - if x != nil { - return x.Pubkey - } - return nil -} - -func (x *SetVoluntaryExitRequest) GetEpoch() github_com_prysmaticlabs_prysm_v4_consensus_types_primitives.Epoch { - if x != nil { - return x.Epoch - } - return github_com_prysmaticlabs_prysm_v4_consensus_types_primitives.Epoch(0) -} - -type SetVoluntaryExitResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Data *SetVoluntaryExitResponse_SignedVoluntaryExit `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` -} - -func (x *SetVoluntaryExitResponse) Reset() { - *x = SetVoluntaryExitResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_service_key_management_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SetVoluntaryExitResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SetVoluntaryExitResponse) ProtoMessage() {} - -func (x *SetVoluntaryExitResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_service_key_management_proto_msgTypes[21] - 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 SetVoluntaryExitResponse.ProtoReflect.Descriptor instead. -func (*SetVoluntaryExitResponse) Descriptor() ([]byte, []int) { - return file_proto_eth_service_key_management_proto_rawDescGZIP(), []int{21} -} - -func (x *SetVoluntaryExitResponse) GetData() *SetVoluntaryExitResponse_SignedVoluntaryExit { - if x != nil { - return x.Data - } - return nil -} - type ListKeystoresResponse_Keystore struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1358,7 +1254,7 @@ type ListKeystoresResponse_Keystore struct { func (x *ListKeystoresResponse_Keystore) Reset() { *x = ListKeystoresResponse_Keystore{} if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_service_key_management_proto_msgTypes[22] + mi := &file_proto_eth_service_key_management_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1371,7 +1267,7 @@ func (x *ListKeystoresResponse_Keystore) String() string { func (*ListKeystoresResponse_Keystore) ProtoMessage() {} func (x *ListKeystoresResponse_Keystore) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_service_key_management_proto_msgTypes[22] + mi := &file_proto_eth_service_key_management_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1414,7 +1310,7 @@ type ListRemoteKeysResponse_Keystore struct { func (x *ListRemoteKeysResponse_Keystore) Reset() { *x = ListRemoteKeysResponse_Keystore{} if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_service_key_management_proto_msgTypes[23] + mi := &file_proto_eth_service_key_management_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1427,7 +1323,7 @@ func (x *ListRemoteKeysResponse_Keystore) String() string { func (*ListRemoteKeysResponse_Keystore) ProtoMessage() {} func (x *ListRemoteKeysResponse_Keystore) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_service_key_management_proto_msgTypes[23] + mi := &file_proto_eth_service_key_management_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1476,7 +1372,7 @@ type ImportRemoteKeysRequest_Keystore struct { func (x *ImportRemoteKeysRequest_Keystore) Reset() { *x = ImportRemoteKeysRequest_Keystore{} if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_service_key_management_proto_msgTypes[24] + mi := &file_proto_eth_service_key_management_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1489,7 +1385,7 @@ func (x *ImportRemoteKeysRequest_Keystore) String() string { func (*ImportRemoteKeysRequest_Keystore) ProtoMessage() {} func (x *ImportRemoteKeysRequest_Keystore) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_service_key_management_proto_msgTypes[24] + mi := &file_proto_eth_service_key_management_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1531,7 +1427,7 @@ type GetFeeRecipientByPubkeyResponse_FeeRecipient struct { func (x *GetFeeRecipientByPubkeyResponse_FeeRecipient) Reset() { *x = GetFeeRecipientByPubkeyResponse_FeeRecipient{} if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_service_key_management_proto_msgTypes[25] + mi := &file_proto_eth_service_key_management_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1544,7 +1440,7 @@ func (x *GetFeeRecipientByPubkeyResponse_FeeRecipient) String() string { func (*GetFeeRecipientByPubkeyResponse_FeeRecipient) ProtoMessage() {} func (x *GetFeeRecipientByPubkeyResponse_FeeRecipient) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_service_key_management_proto_msgTypes[25] + mi := &file_proto_eth_service_key_management_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1586,7 +1482,7 @@ type GetGasLimitResponse_GasLimit struct { func (x *GetGasLimitResponse_GasLimit) Reset() { *x = GetGasLimitResponse_GasLimit{} if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_service_key_management_proto_msgTypes[26] + mi := &file_proto_eth_service_key_management_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1599,7 +1495,7 @@ func (x *GetGasLimitResponse_GasLimit) String() string { func (*GetGasLimitResponse_GasLimit) ProtoMessage() {} func (x *GetGasLimitResponse_GasLimit) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_service_key_management_proto_msgTypes[26] + mi := &file_proto_eth_service_key_management_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1629,116 +1525,6 @@ func (x *GetGasLimitResponse_GasLimit) GetGasLimit() uint64 { return 0 } -type SetVoluntaryExitResponse_SignedVoluntaryExit struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Message *SetVoluntaryExitResponse_SignedVoluntaryExit_VoluntaryExit `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *SetVoluntaryExitResponse_SignedVoluntaryExit) Reset() { - *x = SetVoluntaryExitResponse_SignedVoluntaryExit{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_service_key_management_proto_msgTypes[27] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SetVoluntaryExitResponse_SignedVoluntaryExit) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SetVoluntaryExitResponse_SignedVoluntaryExit) ProtoMessage() {} - -func (x *SetVoluntaryExitResponse_SignedVoluntaryExit) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_service_key_management_proto_msgTypes[27] - 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 SetVoluntaryExitResponse_SignedVoluntaryExit.ProtoReflect.Descriptor instead. -func (*SetVoluntaryExitResponse_SignedVoluntaryExit) Descriptor() ([]byte, []int) { - return file_proto_eth_service_key_management_proto_rawDescGZIP(), []int{21, 0} -} - -func (x *SetVoluntaryExitResponse_SignedVoluntaryExit) GetMessage() *SetVoluntaryExitResponse_SignedVoluntaryExit_VoluntaryExit { - if x != nil { - return x.Message - } - return nil -} - -func (x *SetVoluntaryExitResponse_SignedVoluntaryExit) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - -type SetVoluntaryExitResponse_SignedVoluntaryExit_VoluntaryExit struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` - ValidatorIndex uint64 `protobuf:"varint,2,opt,name=validator_index,json=validatorIndex,proto3" json:"validator_index,omitempty"` -} - -func (x *SetVoluntaryExitResponse_SignedVoluntaryExit_VoluntaryExit) Reset() { - *x = SetVoluntaryExitResponse_SignedVoluntaryExit_VoluntaryExit{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_service_key_management_proto_msgTypes[28] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SetVoluntaryExitResponse_SignedVoluntaryExit_VoluntaryExit) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SetVoluntaryExitResponse_SignedVoluntaryExit_VoluntaryExit) ProtoMessage() {} - -func (x *SetVoluntaryExitResponse_SignedVoluntaryExit_VoluntaryExit) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_service_key_management_proto_msgTypes[28] - 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 SetVoluntaryExitResponse_SignedVoluntaryExit_VoluntaryExit.ProtoReflect.Descriptor instead. -func (*SetVoluntaryExitResponse_SignedVoluntaryExit_VoluntaryExit) Descriptor() ([]byte, []int) { - return file_proto_eth_service_key_management_proto_rawDescGZIP(), []int{21, 0, 0} -} - -func (x *SetVoluntaryExitResponse_SignedVoluntaryExit_VoluntaryExit) GetEpoch() uint64 { - if x != nil { - return x.Epoch - } - return 0 -} - -func (x *SetVoluntaryExitResponse_SignedVoluntaryExit_VoluntaryExit) GetValidatorIndex() uint64 { - if x != nil { - return x.ValidatorIndex - } - return 0 -} - var File_proto_eth_service_key_management_proto protoreflect.FileDescriptor var file_proto_eth_service_key_management_proto_rawDesc = []byte{ @@ -1751,347 +1537,292 @@ var file_proto_eth_service_key_management_proto_rawDesc = []byte{ 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, - 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x65, 0x78, 0x74, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc3, 0x01, 0x0a, 0x15, 0x4c, 0x69, 0x73, - 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x48, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x73, - 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4b, 0x65, - 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x60, 0x0a, 0x08, - 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x50, - 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x64, 0x65, 0x72, 0x69, 0x76, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, - 0x64, 0x65, 0x72, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x74, 0x68, 0x22, 0x85, - 0x01, 0x0a, 0x16, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6b, 0x65, 0x79, - 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6b, 0x65, - 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x61, 0x73, 0x73, 0x77, - 0x6f, 0x72, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x73, 0x73, - 0x77, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x2f, 0x0a, 0x13, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, - 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x12, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x74, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x5b, 0x0a, 0x17, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, - 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x40, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x4b, - 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x04, 0x64, - 0x61, 0x74, 0x61, 0x22, 0x32, 0x0a, 0x16, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, - 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, - 0x07, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, - 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x8b, 0x01, 0x0a, 0x17, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, - 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x04, - 0x64, 0x61, 0x74, 0x61, 0x12, 0x2f, 0x0a, 0x13, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, - 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x12, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb1, 0x01, 0x0a, 0x16, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, + 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc3, 0x01, 0x0a, 0x15, + 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, + 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x1a, + 0x60, 0x0a, 0x08, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, + 0x6e, 0x67, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x64, 0x65, 0x72, 0x69, + 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0e, 0x64, 0x65, 0x72, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x74, + 0x68, 0x22, 0x85, 0x01, 0x0a, 0x16, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x4b, 0x65, 0x79, 0x73, + 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, + 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x09, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x61, + 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x70, + 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x2f, 0x0a, 0x13, 0x73, 0x6c, 0x61, 0x73, + 0x68, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x50, + 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x5b, 0x0a, 0x17, 0x49, 0x6d, 0x70, + 0x6f, 0x72, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x4b, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, - 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, - 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x30, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x0c, 0x0a, 0x08, 0x49, 0x4d, 0x50, 0x4f, 0x52, 0x54, 0x45, 0x44, 0x10, 0x00, 0x12, - 0x0d, 0x0a, 0x09, 0x44, 0x55, 0x50, 0x4c, 0x49, 0x43, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x09, - 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x22, 0xbe, 0x01, 0x0a, 0x15, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x4a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, - 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3f, 0x0a, 0x06, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x00, - 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x01, 0x12, - 0x0e, 0x0a, 0x0a, 0x4e, 0x4f, 0x54, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x02, 0x12, - 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x22, 0xb5, 0x01, 0x0a, 0x16, 0x4c, - 0x69, 0x73, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, - 0x1a, 0x50, 0x0a, 0x08, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x16, 0x0a, 0x06, - 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x75, - 0x62, 0x6b, 0x65, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x61, 0x64, 0x6f, 0x6e, - 0x6c, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x61, 0x64, 0x6f, 0x6e, - 0x6c, 0x79, 0x22, 0xa8, 0x01, 0x0a, 0x17, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x6d, - 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x57, - 0x0a, 0x0b, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x32, 0x0a, 0x16, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x18, 0x0a, 0x07, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0c, 0x52, 0x07, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x8b, 0x01, 0x0a, 0x17, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2f, 0x0a, 0x13, 0x73, 0x6c, 0x61, 0x73, 0x68, + 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x50, 0x72, + 0x6f, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb1, 0x01, 0x0a, 0x16, 0x49, 0x6d, 0x70, + 0x6f, 0x72, 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x4b, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, - 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x0a, 0x72, 0x65, 0x6d, - 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x1a, 0x34, 0x0a, 0x08, 0x4b, 0x65, 0x79, 0x73, 0x74, - 0x6f, 0x72, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x75, - 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x5e, 0x0a, - 0x18, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x64, 0x61, 0x74, - 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x49, - 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, - 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x33, 0x0a, - 0x17, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x75, 0x62, 0x6b, - 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x75, 0x62, 0x6b, 0x65, - 0x79, 0x73, 0x22, 0x5d, 0x0a, 0x18, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x6d, 0x6f, - 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, - 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x52, 0x65, 0x6d, 0x6f, 0x74, - 0x65, 0x4b, 0x65, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x04, 0x64, 0x61, 0x74, - 0x61, 0x22, 0xc2, 0x01, 0x0a, 0x18, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x52, 0x65, - 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x4d, - 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x35, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x52, 0x65, - 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, - 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3d, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0c, - 0x0a, 0x08, 0x49, 0x4d, 0x50, 0x4f, 0x52, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, - 0x44, 0x55, 0x50, 0x4c, 0x49, 0x43, 0x41, 0x54, 0x45, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x45, - 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x22, 0xb2, 0x01, 0x0a, 0x17, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x64, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x4c, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x30, 0x0a, 0x06, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x0c, 0x0a, 0x08, 0x49, 0x4d, 0x50, 0x4f, 0x52, 0x54, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x44, 0x55, 0x50, 0x4c, 0x49, 0x43, 0x41, 0x54, 0x45, 0x10, + 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x22, 0xbe, 0x01, 0x0a, + 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x4a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3f, 0x0a, 0x06, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, + 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x4e, 0x4f, 0x54, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, + 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x22, 0xb5, 0x01, + 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x04, 0x64, + 0x61, 0x74, 0x61, 0x1a, 0x50, 0x0a, 0x08, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x12, + 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x61, + 0x64, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x61, + 0x64, 0x6f, 0x6e, 0x6c, 0x79, 0x22, 0xa8, 0x01, 0x0a, 0x17, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, + 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x57, 0x0a, 0x0b, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x49, 0x6d, + 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x0a, + 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x1a, 0x34, 0x0a, 0x08, 0x4b, 0x65, + 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, + 0x22, 0x5e, 0x0a, 0x18, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, + 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x04, + 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, + 0x4b, 0x65, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, + 0x22, 0x33, 0x0a, 0x17, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, + 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, + 0x75, 0x62, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x75, + 0x62, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x5d, 0x0a, 0x18, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, + 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x41, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x52, 0x65, + 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x04, + 0x64, 0x61, 0x74, 0x61, 0x22, 0xc2, 0x01, 0x0a, 0x18, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, + 0x64, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x4d, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x2f, 0x0a, 0x06, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, - 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x01, - 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x22, 0x27, 0x0a, 0x0d, 0x50, - 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, - 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x75, - 0x62, 0x6b, 0x65, 0x79, 0x22, 0xc1, 0x01, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x46, 0x65, 0x65, 0x52, - 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, - 0x74, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x50, - 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x65, - 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, - 0x1a, 0x46, 0x0a, 0x0c, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, - 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x74, 0x68, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x65, 0x74, - 0x68, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x58, 0x0a, 0x1e, 0x53, 0x65, 0x74, 0x46, + 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3d, 0x0a, 0x06, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, + 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x49, 0x4d, 0x50, 0x4f, 0x52, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, + 0x0d, 0x0a, 0x09, 0x44, 0x55, 0x50, 0x4c, 0x49, 0x43, 0x41, 0x54, 0x45, 0x10, 0x02, 0x12, 0x09, + 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x22, 0xb2, 0x01, 0x0a, 0x17, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x64, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x4c, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x64, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x2f, 0x0a, + 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x54, 0x5f, 0x46, + 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, + 0x44, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x22, 0x27, + 0x0a, 0x0d, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x22, 0xc1, 0x01, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, - 0x6b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, + 0x6b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x04, 0x64, + 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x47, 0x65, 0x74, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, + 0x42, 0x79, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x2e, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x04, 0x64, + 0x61, 0x74, 0x61, 0x1a, 0x46, 0x0a, 0x0c, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, + 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x65, + 0x74, 0x68, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x0a, 0x65, 0x74, 0x68, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x58, 0x0a, 0x1e, 0x53, + 0x65, 0x74, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x42, 0x79, + 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, + 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, + 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x74, 0x68, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x65, 0x74, 0x68, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x9e, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x47, 0x61, 0x73, + 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, + 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x47, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x47, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, + 0x04, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x3f, 0x0a, 0x08, 0x47, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, + 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x61, 0x73, + 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x67, 0x61, + 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0x49, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x47, 0x61, 0x73, + 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, + 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x75, + 0x62, 0x6b, 0x65, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x61, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x67, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, + 0x74, 0x22, 0x2f, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x47, 0x61, 0x73, 0x4c, 0x69, + 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, - 0x65, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x74, 0x68, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x65, 0x74, 0x68, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x22, 0x9e, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x47, 0x61, 0x73, 0x4c, 0x69, 0x6d, - 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x04, 0x64, 0x61, - 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, - 0x47, 0x65, 0x74, 0x47, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x2e, 0x47, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x04, 0x64, 0x61, - 0x74, 0x61, 0x1a, 0x3f, 0x0a, 0x08, 0x47, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x16, - 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, - 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x61, 0x73, 0x5f, 0x6c, 0x69, - 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x67, 0x61, 0x73, 0x4c, 0x69, - 0x6d, 0x69, 0x74, 0x22, 0x49, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x47, 0x61, 0x73, 0x4c, 0x69, 0x6d, - 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, - 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x61, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x67, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0x2f, - 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x47, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x22, - 0x97, 0x01, 0x0a, 0x17, 0x53, 0x65, 0x74, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, - 0x45, 0x78, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x06, 0x70, - 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, - 0x02, 0x34, 0x38, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x5c, 0x0a, 0x05, 0x65, - 0x70, 0x6f, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, - 0x34, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, - 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x22, 0xfe, 0x03, 0x0a, 0x18, 0x53, 0x65, - 0x74, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x65, 0x74, 0x56, - 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, - 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x89, - 0x03, 0x0a, 0x13, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, - 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x12, 0x6a, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x50, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, - 0x65, 0x74, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, - 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x2e, 0x56, 0x6f, 0x6c, 0x75, - 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 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, - 0x1a, 0xe7, 0x01, 0x0a, 0x0d, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, - 0x69, 0x74, 0x12, 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, - 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x34, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, - 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, - 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, - 0x12, 0x78, 0x0a, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, - 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, - 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x34, - 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x32, 0xc9, 0x0f, 0x0a, 0x0d, 0x4b, - 0x65, 0x79, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x78, 0x0a, 0x0d, - 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x12, 0x1a, 0x2f, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x6b, 0x65, 0x79, - 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x95, 0x01, 0x0a, 0x0f, 0x49, 0x6d, 0x70, 0x6f, 0x72, - 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x2c, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, - 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x3a, - 0x01, 0x2a, 0x22, 0x1a, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, + 0x65, 0x79, 0x32, 0x96, 0x0e, 0x0a, 0x0d, 0x4b, 0x65, 0x79, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x78, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x73, + 0x74, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x2b, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x1c, 0x12, 0x1a, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x95, - 0x01, 0x0a, 0x0f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, + 0x01, 0x0a, 0x0f, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x3a, 0x01, 0x2a, 0x2a, 0x1a, 0x2f, 0x69, 0x6e, 0x74, + 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x3a, 0x01, 0x2a, 0x22, 0x1a, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x6b, 0x65, 0x79, - 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x7b, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, - 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x1a, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x6d, 0x6f, - 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x6b, - 0x65, 0x79, 0x73, 0x12, 0x99, 0x01, 0x0a, 0x10, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, - 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, - 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x49, - 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, - 0x01, 0x2a, 0x22, 0x1b, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, - 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x6b, 0x65, 0x79, 0x73, 0x12, - 0x99, 0x01, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, - 0x4b, 0x65, 0x79, 0x73, 0x12, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, 0x2a, 0x2a, 0x1b, - 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, - 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x6b, 0x65, 0x79, 0x73, 0x12, 0xb0, 0x01, 0x0a, 0x18, - 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, - 0x42, 0x79, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x23, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, - 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, - 0x69, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x38, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x32, 0x12, 0x30, 0x2f, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x7b, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, - 0x7d, 0x2f, 0x66, 0x65, 0x65, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0xa4, - 0x01, 0x0a, 0x17, 0x53, 0x65, 0x74, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, - 0x6e, 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x34, 0x2e, 0x65, 0x74, 0x68, + 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x95, 0x01, 0x0a, 0x0f, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x2e, 0x53, 0x65, 0x74, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, - 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x3b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x35, - 0x3a, 0x01, 0x2a, 0x22, 0x30, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, - 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, - 0x7b, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x7d, 0x2f, 0x66, 0x65, 0x65, 0x72, 0x65, 0x63, 0x69, - 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x96, 0x01, 0x0a, 0x1a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x3a, + 0x01, 0x2a, 0x2a, 0x1a, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, + 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x7b, + 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, + 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, + 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, + 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x6b, 0x65, 0x79, 0x73, 0x12, 0x99, 0x01, 0x0a, 0x10, + 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, + 0x12, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, + 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x6d, + 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, 0x2a, 0x22, 0x1b, 0x2f, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x6d, + 0x6f, 0x74, 0x65, 0x6b, 0x65, 0x79, 0x73, 0x12, 0x99, 0x01, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x2d, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, + 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4b, + 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x20, 0x3a, 0x01, 0x2a, 0x2a, 0x1b, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x6b, + 0x65, 0x79, 0x73, 0x12, 0xb0, 0x01, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, 0x65, 0x52, + 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, + 0x12, 0x23, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x50, 0x75, - 0x62, 0x6b, 0x65, 0x79, 0x12, 0x23, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x50, 0x75, 0x62, 0x6b, - 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x62, 0x6b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x38, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x32, 0x12, 0x30, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, + 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x2f, 0x7b, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x7d, 0x2f, 0x66, 0x65, 0x65, 0x72, 0x65, 0x63, + 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0xa4, 0x01, 0x0a, 0x17, 0x53, 0x65, 0x74, 0x46, 0x65, + 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, 0x6b, + 0x65, 0x79, 0x12, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x65, 0x74, 0x46, 0x65, 0x65, + 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, 0x6b, 0x65, + 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x22, 0x3b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x35, 0x3a, 0x01, 0x2a, 0x22, 0x30, 0x2f, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x7b, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x7d, + 0x2f, 0x66, 0x65, 0x65, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x96, 0x01, + 0x0a, 0x1a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, + 0x69, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x23, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x3b, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x35, 0x3a, 0x01, 0x2a, 0x2a, 0x30, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, + 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x2f, 0x7b, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x7d, 0x2f, 0x66, 0x65, 0x65, 0x72, 0x65, 0x63, + 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x94, 0x01, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x47, 0x61, + 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x23, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x50, 0x75, + 0x62, 0x6b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x47, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x35, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x12, 0x2d, + 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, + 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x7b, 0x70, 0x75, 0x62, 0x6b, + 0x65, 0x79, 0x7d, 0x2f, 0x67, 0x61, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x89, 0x01, + 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x47, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x28, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x65, 0x74, 0x47, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, + 0x38, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x32, 0x3a, 0x01, 0x2a, 0x22, 0x2d, 0x2f, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x7b, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x7d, 0x2f, + 0x67, 0x61, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x8f, 0x01, 0x0a, 0x0e, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x47, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x2b, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x47, 0x61, 0x73, 0x4c, 0x69, 0x6d, + 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x22, 0x3b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x35, 0x3a, 0x01, 0x2a, 0x2a, 0x30, 0x2f, 0x69, + 0x79, 0x22, 0x38, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x32, 0x3a, 0x01, 0x2a, 0x2a, 0x2d, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x7b, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, - 0x7d, 0x2f, 0x66, 0x65, 0x65, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x94, - 0x01, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x47, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x23, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x47, 0x61, - 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x35, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x12, 0x2d, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x2f, 0x7b, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x7d, 0x2f, 0x67, 0x61, 0x73, 0x5f, - 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x89, 0x01, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x47, 0x61, 0x73, - 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x65, 0x74, - 0x47, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x38, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x32, 0x3a, - 0x01, 0x2a, 0x22, 0x2d, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, - 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x7b, - 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x7d, 0x2f, 0x67, 0x61, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, - 0x74, 0x12, 0x8f, 0x01, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x47, 0x61, 0x73, 0x4c, - 0x69, 0x6d, 0x69, 0x74, 0x12, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x47, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x38, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x32, 0x3a, 0x01, 0x2a, 0x2a, 0x2d, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, - 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x2f, 0x7b, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x7d, 0x2f, 0x67, 0x61, 0x73, 0x5f, 0x6c, 0x69, - 0x6d, 0x69, 0x74, 0x12, 0xb0, 0x01, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x56, 0x6f, 0x6c, 0x75, 0x6e, - 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x12, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, - 0x53, 0x65, 0x74, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, - 0x65, 0x74, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x37, 0x3a, - 0x01, 0x2a, 0x22, 0x32, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x65, 0x74, - 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x7b, - 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x7d, 0x2f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, - 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x42, 0x9a, 0x01, 0x0a, 0x18, 0x6f, 0x72, 0x67, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x42, 0x19, 0x4b, 0x65, 0x79, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, - 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, - 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, - 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x2f, 0x76, 0x34, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0xaa, 0x02, 0x14, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xca, 0x02, 0x14, 0x45, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x7d, 0x2f, 0x67, 0x61, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x42, 0x9a, 0x01, 0x0a, 0x18, + 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x19, 0x4b, 0x65, 0x79, 0x4d, 0x61, 0x6e, + 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, + 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x34, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, + 0x74, 0x68, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xaa, 0x02, 0x14, 0x45, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0xca, 0x02, 0x14, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, + 0x5c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2107,90 +1838,82 @@ func file_proto_eth_service_key_management_proto_rawDescGZIP() []byte { } var file_proto_eth_service_key_management_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_proto_eth_service_key_management_proto_msgTypes = make([]protoimpl.MessageInfo, 29) +var file_proto_eth_service_key_management_proto_msgTypes = make([]protoimpl.MessageInfo, 25) var file_proto_eth_service_key_management_proto_goTypes = []interface{}{ - (ImportedKeystoreStatus_Status)(0), // 0: ethereum.eth.service.ImportedKeystoreStatus.Status - (DeletedKeystoreStatus_Status)(0), // 1: ethereum.eth.service.DeletedKeystoreStatus.Status - (ImportedRemoteKeysStatus_Status)(0), // 2: ethereum.eth.service.ImportedRemoteKeysStatus.Status - (DeletedRemoteKeysStatus_Status)(0), // 3: ethereum.eth.service.DeletedRemoteKeysStatus.Status - (*ListKeystoresResponse)(nil), // 4: ethereum.eth.service.ListKeystoresResponse - (*ImportKeystoresRequest)(nil), // 5: ethereum.eth.service.ImportKeystoresRequest - (*ImportKeystoresResponse)(nil), // 6: ethereum.eth.service.ImportKeystoresResponse - (*DeleteKeystoresRequest)(nil), // 7: ethereum.eth.service.DeleteKeystoresRequest - (*DeleteKeystoresResponse)(nil), // 8: ethereum.eth.service.DeleteKeystoresResponse - (*ImportedKeystoreStatus)(nil), // 9: ethereum.eth.service.ImportedKeystoreStatus - (*DeletedKeystoreStatus)(nil), // 10: ethereum.eth.service.DeletedKeystoreStatus - (*ListRemoteKeysResponse)(nil), // 11: ethereum.eth.service.ListRemoteKeysResponse - (*ImportRemoteKeysRequest)(nil), // 12: ethereum.eth.service.ImportRemoteKeysRequest - (*ImportRemoteKeysResponse)(nil), // 13: ethereum.eth.service.ImportRemoteKeysResponse - (*DeleteRemoteKeysRequest)(nil), // 14: ethereum.eth.service.DeleteRemoteKeysRequest - (*DeleteRemoteKeysResponse)(nil), // 15: ethereum.eth.service.DeleteRemoteKeysResponse - (*ImportedRemoteKeysStatus)(nil), // 16: ethereum.eth.service.ImportedRemoteKeysStatus - (*DeletedRemoteKeysStatus)(nil), // 17: ethereum.eth.service.DeletedRemoteKeysStatus - (*PubkeyRequest)(nil), // 18: ethereum.eth.service.PubkeyRequest - (*GetFeeRecipientByPubkeyResponse)(nil), // 19: ethereum.eth.service.GetFeeRecipientByPubkeyResponse - (*SetFeeRecipientByPubkeyRequest)(nil), // 20: ethereum.eth.service.SetFeeRecipientByPubkeyRequest - (*GetGasLimitResponse)(nil), // 21: ethereum.eth.service.GetGasLimitResponse - (*SetGasLimitRequest)(nil), // 22: ethereum.eth.service.SetGasLimitRequest - (*DeleteGasLimitRequest)(nil), // 23: ethereum.eth.service.DeleteGasLimitRequest - (*SetVoluntaryExitRequest)(nil), // 24: ethereum.eth.service.SetVoluntaryExitRequest - (*SetVoluntaryExitResponse)(nil), // 25: ethereum.eth.service.SetVoluntaryExitResponse - (*ListKeystoresResponse_Keystore)(nil), // 26: ethereum.eth.service.ListKeystoresResponse.Keystore - (*ListRemoteKeysResponse_Keystore)(nil), // 27: ethereum.eth.service.ListRemoteKeysResponse.Keystore - (*ImportRemoteKeysRequest_Keystore)(nil), // 28: ethereum.eth.service.ImportRemoteKeysRequest.Keystore - (*GetFeeRecipientByPubkeyResponse_FeeRecipient)(nil), // 29: ethereum.eth.service.GetFeeRecipientByPubkeyResponse.FeeRecipient - (*GetGasLimitResponse_GasLimit)(nil), // 30: ethereum.eth.service.GetGasLimitResponse.GasLimit - (*SetVoluntaryExitResponse_SignedVoluntaryExit)(nil), // 31: ethereum.eth.service.SetVoluntaryExitResponse.SignedVoluntaryExit - (*SetVoluntaryExitResponse_SignedVoluntaryExit_VoluntaryExit)(nil), // 32: ethereum.eth.service.SetVoluntaryExitResponse.SignedVoluntaryExit.VoluntaryExit - (*emptypb.Empty)(nil), // 33: google.protobuf.Empty + (ImportedKeystoreStatus_Status)(0), // 0: ethereum.eth.service.ImportedKeystoreStatus.Status + (DeletedKeystoreStatus_Status)(0), // 1: ethereum.eth.service.DeletedKeystoreStatus.Status + (ImportedRemoteKeysStatus_Status)(0), // 2: ethereum.eth.service.ImportedRemoteKeysStatus.Status + (DeletedRemoteKeysStatus_Status)(0), // 3: ethereum.eth.service.DeletedRemoteKeysStatus.Status + (*ListKeystoresResponse)(nil), // 4: ethereum.eth.service.ListKeystoresResponse + (*ImportKeystoresRequest)(nil), // 5: ethereum.eth.service.ImportKeystoresRequest + (*ImportKeystoresResponse)(nil), // 6: ethereum.eth.service.ImportKeystoresResponse + (*DeleteKeystoresRequest)(nil), // 7: ethereum.eth.service.DeleteKeystoresRequest + (*DeleteKeystoresResponse)(nil), // 8: ethereum.eth.service.DeleteKeystoresResponse + (*ImportedKeystoreStatus)(nil), // 9: ethereum.eth.service.ImportedKeystoreStatus + (*DeletedKeystoreStatus)(nil), // 10: ethereum.eth.service.DeletedKeystoreStatus + (*ListRemoteKeysResponse)(nil), // 11: ethereum.eth.service.ListRemoteKeysResponse + (*ImportRemoteKeysRequest)(nil), // 12: ethereum.eth.service.ImportRemoteKeysRequest + (*ImportRemoteKeysResponse)(nil), // 13: ethereum.eth.service.ImportRemoteKeysResponse + (*DeleteRemoteKeysRequest)(nil), // 14: ethereum.eth.service.DeleteRemoteKeysRequest + (*DeleteRemoteKeysResponse)(nil), // 15: ethereum.eth.service.DeleteRemoteKeysResponse + (*ImportedRemoteKeysStatus)(nil), // 16: ethereum.eth.service.ImportedRemoteKeysStatus + (*DeletedRemoteKeysStatus)(nil), // 17: ethereum.eth.service.DeletedRemoteKeysStatus + (*PubkeyRequest)(nil), // 18: ethereum.eth.service.PubkeyRequest + (*GetFeeRecipientByPubkeyResponse)(nil), // 19: ethereum.eth.service.GetFeeRecipientByPubkeyResponse + (*SetFeeRecipientByPubkeyRequest)(nil), // 20: ethereum.eth.service.SetFeeRecipientByPubkeyRequest + (*GetGasLimitResponse)(nil), // 21: ethereum.eth.service.GetGasLimitResponse + (*SetGasLimitRequest)(nil), // 22: ethereum.eth.service.SetGasLimitRequest + (*DeleteGasLimitRequest)(nil), // 23: ethereum.eth.service.DeleteGasLimitRequest + (*ListKeystoresResponse_Keystore)(nil), // 24: ethereum.eth.service.ListKeystoresResponse.Keystore + (*ListRemoteKeysResponse_Keystore)(nil), // 25: ethereum.eth.service.ListRemoteKeysResponse.Keystore + (*ImportRemoteKeysRequest_Keystore)(nil), // 26: ethereum.eth.service.ImportRemoteKeysRequest.Keystore + (*GetFeeRecipientByPubkeyResponse_FeeRecipient)(nil), // 27: ethereum.eth.service.GetFeeRecipientByPubkeyResponse.FeeRecipient + (*GetGasLimitResponse_GasLimit)(nil), // 28: ethereum.eth.service.GetGasLimitResponse.GasLimit + (*emptypb.Empty)(nil), // 29: google.protobuf.Empty } var file_proto_eth_service_key_management_proto_depIdxs = []int32{ - 26, // 0: ethereum.eth.service.ListKeystoresResponse.data:type_name -> ethereum.eth.service.ListKeystoresResponse.Keystore + 24, // 0: ethereum.eth.service.ListKeystoresResponse.data:type_name -> ethereum.eth.service.ListKeystoresResponse.Keystore 9, // 1: ethereum.eth.service.ImportKeystoresResponse.data:type_name -> ethereum.eth.service.ImportedKeystoreStatus 10, // 2: ethereum.eth.service.DeleteKeystoresResponse.data:type_name -> ethereum.eth.service.DeletedKeystoreStatus 0, // 3: ethereum.eth.service.ImportedKeystoreStatus.status:type_name -> ethereum.eth.service.ImportedKeystoreStatus.Status 1, // 4: ethereum.eth.service.DeletedKeystoreStatus.status:type_name -> ethereum.eth.service.DeletedKeystoreStatus.Status - 27, // 5: ethereum.eth.service.ListRemoteKeysResponse.data:type_name -> ethereum.eth.service.ListRemoteKeysResponse.Keystore - 28, // 6: ethereum.eth.service.ImportRemoteKeysRequest.remote_keys:type_name -> ethereum.eth.service.ImportRemoteKeysRequest.Keystore + 25, // 5: ethereum.eth.service.ListRemoteKeysResponse.data:type_name -> ethereum.eth.service.ListRemoteKeysResponse.Keystore + 26, // 6: ethereum.eth.service.ImportRemoteKeysRequest.remote_keys:type_name -> ethereum.eth.service.ImportRemoteKeysRequest.Keystore 16, // 7: ethereum.eth.service.ImportRemoteKeysResponse.data:type_name -> ethereum.eth.service.ImportedRemoteKeysStatus 17, // 8: ethereum.eth.service.DeleteRemoteKeysResponse.data:type_name -> ethereum.eth.service.DeletedRemoteKeysStatus 2, // 9: ethereum.eth.service.ImportedRemoteKeysStatus.status:type_name -> ethereum.eth.service.ImportedRemoteKeysStatus.Status 3, // 10: ethereum.eth.service.DeletedRemoteKeysStatus.status:type_name -> ethereum.eth.service.DeletedRemoteKeysStatus.Status - 29, // 11: ethereum.eth.service.GetFeeRecipientByPubkeyResponse.data:type_name -> ethereum.eth.service.GetFeeRecipientByPubkeyResponse.FeeRecipient - 30, // 12: ethereum.eth.service.GetGasLimitResponse.data:type_name -> ethereum.eth.service.GetGasLimitResponse.GasLimit - 31, // 13: ethereum.eth.service.SetVoluntaryExitResponse.data:type_name -> ethereum.eth.service.SetVoluntaryExitResponse.SignedVoluntaryExit - 32, // 14: ethereum.eth.service.SetVoluntaryExitResponse.SignedVoluntaryExit.message:type_name -> ethereum.eth.service.SetVoluntaryExitResponse.SignedVoluntaryExit.VoluntaryExit - 33, // 15: ethereum.eth.service.KeyManagement.ListKeystores:input_type -> google.protobuf.Empty - 5, // 16: ethereum.eth.service.KeyManagement.ImportKeystores:input_type -> ethereum.eth.service.ImportKeystoresRequest - 7, // 17: ethereum.eth.service.KeyManagement.DeleteKeystores:input_type -> ethereum.eth.service.DeleteKeystoresRequest - 33, // 18: ethereum.eth.service.KeyManagement.ListRemoteKeys:input_type -> google.protobuf.Empty - 12, // 19: ethereum.eth.service.KeyManagement.ImportRemoteKeys:input_type -> ethereum.eth.service.ImportRemoteKeysRequest - 14, // 20: ethereum.eth.service.KeyManagement.DeleteRemoteKeys:input_type -> ethereum.eth.service.DeleteRemoteKeysRequest - 18, // 21: ethereum.eth.service.KeyManagement.ListFeeRecipientByPubkey:input_type -> ethereum.eth.service.PubkeyRequest - 20, // 22: ethereum.eth.service.KeyManagement.SetFeeRecipientByPubkey:input_type -> ethereum.eth.service.SetFeeRecipientByPubkeyRequest - 18, // 23: ethereum.eth.service.KeyManagement.DeleteFeeRecipientByPubkey:input_type -> ethereum.eth.service.PubkeyRequest - 18, // 24: ethereum.eth.service.KeyManagement.GetGasLimit:input_type -> ethereum.eth.service.PubkeyRequest - 22, // 25: ethereum.eth.service.KeyManagement.SetGasLimit:input_type -> ethereum.eth.service.SetGasLimitRequest - 23, // 26: ethereum.eth.service.KeyManagement.DeleteGasLimit:input_type -> ethereum.eth.service.DeleteGasLimitRequest - 24, // 27: ethereum.eth.service.KeyManagement.SetVoluntaryExit:input_type -> ethereum.eth.service.SetVoluntaryExitRequest - 4, // 28: ethereum.eth.service.KeyManagement.ListKeystores:output_type -> ethereum.eth.service.ListKeystoresResponse - 6, // 29: ethereum.eth.service.KeyManagement.ImportKeystores:output_type -> ethereum.eth.service.ImportKeystoresResponse - 8, // 30: ethereum.eth.service.KeyManagement.DeleteKeystores:output_type -> ethereum.eth.service.DeleteKeystoresResponse - 11, // 31: ethereum.eth.service.KeyManagement.ListRemoteKeys:output_type -> ethereum.eth.service.ListRemoteKeysResponse - 13, // 32: ethereum.eth.service.KeyManagement.ImportRemoteKeys:output_type -> ethereum.eth.service.ImportRemoteKeysResponse - 15, // 33: ethereum.eth.service.KeyManagement.DeleteRemoteKeys:output_type -> ethereum.eth.service.DeleteRemoteKeysResponse - 19, // 34: ethereum.eth.service.KeyManagement.ListFeeRecipientByPubkey:output_type -> ethereum.eth.service.GetFeeRecipientByPubkeyResponse - 33, // 35: ethereum.eth.service.KeyManagement.SetFeeRecipientByPubkey:output_type -> google.protobuf.Empty - 33, // 36: ethereum.eth.service.KeyManagement.DeleteFeeRecipientByPubkey:output_type -> google.protobuf.Empty - 21, // 37: ethereum.eth.service.KeyManagement.GetGasLimit:output_type -> ethereum.eth.service.GetGasLimitResponse - 33, // 38: ethereum.eth.service.KeyManagement.SetGasLimit:output_type -> google.protobuf.Empty - 33, // 39: ethereum.eth.service.KeyManagement.DeleteGasLimit:output_type -> google.protobuf.Empty - 25, // 40: ethereum.eth.service.KeyManagement.SetVoluntaryExit:output_type -> ethereum.eth.service.SetVoluntaryExitResponse - 28, // [28:41] is the sub-list for method output_type - 15, // [15:28] is the sub-list for method input_type - 15, // [15:15] is the sub-list for extension type_name - 15, // [15:15] is the sub-list for extension extendee - 0, // [0:15] is the sub-list for field type_name + 27, // 11: ethereum.eth.service.GetFeeRecipientByPubkeyResponse.data:type_name -> ethereum.eth.service.GetFeeRecipientByPubkeyResponse.FeeRecipient + 28, // 12: ethereum.eth.service.GetGasLimitResponse.data:type_name -> ethereum.eth.service.GetGasLimitResponse.GasLimit + 29, // 13: ethereum.eth.service.KeyManagement.ListKeystores:input_type -> google.protobuf.Empty + 5, // 14: ethereum.eth.service.KeyManagement.ImportKeystores:input_type -> ethereum.eth.service.ImportKeystoresRequest + 7, // 15: ethereum.eth.service.KeyManagement.DeleteKeystores:input_type -> ethereum.eth.service.DeleteKeystoresRequest + 29, // 16: ethereum.eth.service.KeyManagement.ListRemoteKeys:input_type -> google.protobuf.Empty + 12, // 17: ethereum.eth.service.KeyManagement.ImportRemoteKeys:input_type -> ethereum.eth.service.ImportRemoteKeysRequest + 14, // 18: ethereum.eth.service.KeyManagement.DeleteRemoteKeys:input_type -> ethereum.eth.service.DeleteRemoteKeysRequest + 18, // 19: ethereum.eth.service.KeyManagement.ListFeeRecipientByPubkey:input_type -> ethereum.eth.service.PubkeyRequest + 20, // 20: ethereum.eth.service.KeyManagement.SetFeeRecipientByPubkey:input_type -> ethereum.eth.service.SetFeeRecipientByPubkeyRequest + 18, // 21: ethereum.eth.service.KeyManagement.DeleteFeeRecipientByPubkey:input_type -> ethereum.eth.service.PubkeyRequest + 18, // 22: ethereum.eth.service.KeyManagement.GetGasLimit:input_type -> ethereum.eth.service.PubkeyRequest + 22, // 23: ethereum.eth.service.KeyManagement.SetGasLimit:input_type -> ethereum.eth.service.SetGasLimitRequest + 23, // 24: ethereum.eth.service.KeyManagement.DeleteGasLimit:input_type -> ethereum.eth.service.DeleteGasLimitRequest + 4, // 25: ethereum.eth.service.KeyManagement.ListKeystores:output_type -> ethereum.eth.service.ListKeystoresResponse + 6, // 26: ethereum.eth.service.KeyManagement.ImportKeystores:output_type -> ethereum.eth.service.ImportKeystoresResponse + 8, // 27: ethereum.eth.service.KeyManagement.DeleteKeystores:output_type -> ethereum.eth.service.DeleteKeystoresResponse + 11, // 28: ethereum.eth.service.KeyManagement.ListRemoteKeys:output_type -> ethereum.eth.service.ListRemoteKeysResponse + 13, // 29: ethereum.eth.service.KeyManagement.ImportRemoteKeys:output_type -> ethereum.eth.service.ImportRemoteKeysResponse + 15, // 30: ethereum.eth.service.KeyManagement.DeleteRemoteKeys:output_type -> ethereum.eth.service.DeleteRemoteKeysResponse + 19, // 31: ethereum.eth.service.KeyManagement.ListFeeRecipientByPubkey:output_type -> ethereum.eth.service.GetFeeRecipientByPubkeyResponse + 29, // 32: ethereum.eth.service.KeyManagement.SetFeeRecipientByPubkey:output_type -> google.protobuf.Empty + 29, // 33: ethereum.eth.service.KeyManagement.DeleteFeeRecipientByPubkey:output_type -> google.protobuf.Empty + 21, // 34: ethereum.eth.service.KeyManagement.GetGasLimit:output_type -> ethereum.eth.service.GetGasLimitResponse + 29, // 35: ethereum.eth.service.KeyManagement.SetGasLimit:output_type -> google.protobuf.Empty + 29, // 36: ethereum.eth.service.KeyManagement.DeleteGasLimit:output_type -> google.protobuf.Empty + 25, // [25:37] is the sub-list for method output_type + 13, // [13:25] is the sub-list for method input_type + 13, // [13:13] is the sub-list for extension type_name + 13, // [13:13] is the sub-list for extension extendee + 0, // [0:13] is the sub-list for field type_name } func init() { file_proto_eth_service_key_management_proto_init() } @@ -2440,30 +2163,6 @@ func file_proto_eth_service_key_management_proto_init() { } } file_proto_eth_service_key_management_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetVoluntaryExitRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_service_key_management_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetVoluntaryExitResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_service_key_management_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListKeystoresResponse_Keystore); i { case 0: return &v.state @@ -2475,7 +2174,7 @@ func file_proto_eth_service_key_management_proto_init() { return nil } } - file_proto_eth_service_key_management_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + file_proto_eth_service_key_management_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListRemoteKeysResponse_Keystore); i { case 0: return &v.state @@ -2487,7 +2186,7 @@ func file_proto_eth_service_key_management_proto_init() { return nil } } - file_proto_eth_service_key_management_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + file_proto_eth_service_key_management_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ImportRemoteKeysRequest_Keystore); i { case 0: return &v.state @@ -2499,7 +2198,7 @@ func file_proto_eth_service_key_management_proto_init() { return nil } } - file_proto_eth_service_key_management_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + file_proto_eth_service_key_management_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetFeeRecipientByPubkeyResponse_FeeRecipient); i { case 0: return &v.state @@ -2511,7 +2210,7 @@ func file_proto_eth_service_key_management_proto_init() { return nil } } - file_proto_eth_service_key_management_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + file_proto_eth_service_key_management_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetGasLimitResponse_GasLimit); i { case 0: return &v.state @@ -2523,30 +2222,6 @@ func file_proto_eth_service_key_management_proto_init() { return nil } } - file_proto_eth_service_key_management_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetVoluntaryExitResponse_SignedVoluntaryExit); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_service_key_management_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetVoluntaryExitResponse_SignedVoluntaryExit_VoluntaryExit); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } } type x struct{} out := protoimpl.TypeBuilder{ @@ -2554,7 +2229,7 @@ func file_proto_eth_service_key_management_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_eth_service_key_management_proto_rawDesc, NumEnums: 4, - NumMessages: 29, + NumMessages: 25, NumExtensions: 0, NumServices: 1, }, @@ -2593,7 +2268,6 @@ type KeyManagementClient interface { GetGasLimit(ctx context.Context, in *PubkeyRequest, opts ...grpc.CallOption) (*GetGasLimitResponse, error) SetGasLimit(ctx context.Context, in *SetGasLimitRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) DeleteGasLimit(ctx context.Context, in *DeleteGasLimitRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) - SetVoluntaryExit(ctx context.Context, in *SetVoluntaryExitRequest, opts ...grpc.CallOption) (*SetVoluntaryExitResponse, error) } type keyManagementClient struct { @@ -2712,15 +2386,6 @@ func (c *keyManagementClient) DeleteGasLimit(ctx context.Context, in *DeleteGasL return out, nil } -func (c *keyManagementClient) SetVoluntaryExit(ctx context.Context, in *SetVoluntaryExitRequest, opts ...grpc.CallOption) (*SetVoluntaryExitResponse, error) { - out := new(SetVoluntaryExitResponse) - err := c.cc.Invoke(ctx, "/ethereum.eth.service.KeyManagement/SetVoluntaryExit", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - // KeyManagementServer is the server API for KeyManagement service. type KeyManagementServer interface { ListKeystores(context.Context, *emptypb.Empty) (*ListKeystoresResponse, error) @@ -2735,7 +2400,6 @@ type KeyManagementServer interface { GetGasLimit(context.Context, *PubkeyRequest) (*GetGasLimitResponse, error) SetGasLimit(context.Context, *SetGasLimitRequest) (*emptypb.Empty, error) DeleteGasLimit(context.Context, *DeleteGasLimitRequest) (*emptypb.Empty, error) - SetVoluntaryExit(context.Context, *SetVoluntaryExitRequest) (*SetVoluntaryExitResponse, error) } // UnimplementedKeyManagementServer can be embedded to have forward compatible implementations. @@ -2778,9 +2442,6 @@ func (*UnimplementedKeyManagementServer) SetGasLimit(context.Context, *SetGasLim func (*UnimplementedKeyManagementServer) DeleteGasLimit(context.Context, *DeleteGasLimitRequest) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method DeleteGasLimit not implemented") } -func (*UnimplementedKeyManagementServer) SetVoluntaryExit(context.Context, *SetVoluntaryExitRequest) (*SetVoluntaryExitResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method SetVoluntaryExit not implemented") -} func RegisterKeyManagementServer(s *grpc.Server, srv KeyManagementServer) { s.RegisterService(&_KeyManagement_serviceDesc, srv) @@ -3002,24 +2663,6 @@ func _KeyManagement_DeleteGasLimit_Handler(srv interface{}, ctx context.Context, return interceptor(ctx, in, info, handler) } -func _KeyManagement_SetVoluntaryExit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(SetVoluntaryExitRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(KeyManagementServer).SetVoluntaryExit(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ethereum.eth.service.KeyManagement/SetVoluntaryExit", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(KeyManagementServer).SetVoluntaryExit(ctx, req.(*SetVoluntaryExitRequest)) - } - return interceptor(ctx, in, info, handler) -} - var _KeyManagement_serviceDesc = grpc.ServiceDesc{ ServiceName: "ethereum.eth.service.KeyManagement", HandlerType: (*KeyManagementServer)(nil), @@ -3072,10 +2715,6 @@ var _KeyManagement_serviceDesc = grpc.ServiceDesc{ MethodName: "DeleteGasLimit", Handler: _KeyManagement_DeleteGasLimit_Handler, }, - { - MethodName: "SetVoluntaryExit", - Handler: _KeyManagement_SetVoluntaryExit_Handler, - }, }, Streams: []grpc.StreamDesc{}, Metadata: "proto/eth/service/key_management.proto", diff --git a/proto/eth/service/key_management.pb.gw.go b/proto/eth/service/key_management.pb.gw.go index 7f56afe10a..3f0e686f53 100755 --- a/proto/eth/service/key_management.pb.gw.go +++ b/proto/eth/service/key_management.pb.gw.go @@ -595,76 +595,6 @@ func local_request_KeyManagement_DeleteGasLimit_0(ctx context.Context, marshaler } -func request_KeyManagement_SetVoluntaryExit_0(ctx context.Context, marshaler runtime.Marshaler, client KeyManagementClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SetVoluntaryExitRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["pubkey"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "pubkey") - } - - pubkey, err := runtime.Bytes(val) - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "pubkey", err) - } - protoReq.Pubkey = (pubkey) - - msg, err := client.SetVoluntaryExit(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_KeyManagement_SetVoluntaryExit_0(ctx context.Context, marshaler runtime.Marshaler, server KeyManagementServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SetVoluntaryExitRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["pubkey"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "pubkey") - } - - pubkey, err := runtime.Bytes(val) - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "pubkey", err) - } - protoReq.Pubkey = (pubkey) - - msg, err := server.SetVoluntaryExit(ctx, &protoReq) - return msg, metadata, err - -} - // RegisterKeyManagementHandlerServer registers the http handlers for service KeyManagement to "mux". // UnaryRPC :call KeyManagementServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -947,29 +877,6 @@ func RegisterKeyManagementHandlerServer(ctx context.Context, mux *runtime.ServeM }) - mux.Handle("POST", pattern_KeyManagement_SetVoluntaryExit_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.service.KeyManagement/SetVoluntaryExit") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_KeyManagement_SetVoluntaryExit_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_KeyManagement_SetVoluntaryExit_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - return nil } @@ -1251,26 +1158,6 @@ func RegisterKeyManagementHandlerClient(ctx context.Context, mux *runtime.ServeM }) - mux.Handle("POST", pattern_KeyManagement_SetVoluntaryExit_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.service.KeyManagement/SetVoluntaryExit") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_KeyManagement_SetVoluntaryExit_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_KeyManagement_SetVoluntaryExit_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - return nil } @@ -1298,8 +1185,6 @@ var ( pattern_KeyManagement_SetGasLimit_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"internal", "eth", "v1", "validator", "pubkey", "gas_limit"}, "")) pattern_KeyManagement_DeleteGasLimit_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"internal", "eth", "v1", "validator", "pubkey", "gas_limit"}, "")) - - pattern_KeyManagement_SetVoluntaryExit_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"internal", "eth", "v1", "validator", "pubkey", "voluntary_exit"}, "")) ) var ( @@ -1326,6 +1211,4 @@ var ( forward_KeyManagement_SetGasLimit_0 = runtime.ForwardResponseMessage forward_KeyManagement_DeleteGasLimit_0 = runtime.ForwardResponseMessage - - forward_KeyManagement_SetVoluntaryExit_0 = runtime.ForwardResponseMessage ) diff --git a/proto/eth/service/key_management.proto b/proto/eth/service/key_management.proto index 9ebf4b9080..4ebd364be3 100644 --- a/proto/eth/service/key_management.proto +++ b/proto/eth/service/key_management.proto @@ -18,7 +18,6 @@ package ethereum.eth.service; import "google/api/annotations.proto"; import "google/protobuf/descriptor.proto"; import "google/protobuf/empty.proto"; -import "proto/eth/ext/options.proto"; option csharp_namespace = "Ethereum.Eth.Service"; option go_package = "github.com/prysmaticlabs/prysm/v4/proto/eth/service"; @@ -217,25 +216,6 @@ service KeyManagement { body: "*" }; } - - // SetVoluntaryExit creates a signed voluntary exit message and returns a VoluntaryExit object. - // - // Spec page: https://ethereum.github.io/keymanager-APIs/?urls.primaryName=dev#/Voluntary%20Exit/signVoluntaryExit - // - // HTTP response status codes: - // - 200: Successfully created and signed voluntary exit - // - 400: Bad request, malformed request - // - 401: Unauthorized, no token is found. - // - 403: Forbidden, a token is found but is invalid - // - 404: Path not found - // - 500: Validator internal error - rpc SetVoluntaryExit(SetVoluntaryExitRequest) returns (SetVoluntaryExitResponse) { - option (google.api.http) = { - post: "/internal/eth/v1/validator/{pubkey}/voluntary_exit", - body: "*" - }; - } - } message ListKeystoresResponse { @@ -371,20 +351,3 @@ message SetGasLimitRequest { message DeleteGasLimitRequest { bytes pubkey = 1; } - -message SetVoluntaryExitRequest { - bytes pubkey = 1 [(ethereum.eth.ext.ssz_size) = "48"]; - uint64 epoch = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives.Epoch"]; -} - -message SetVoluntaryExitResponse { - message SignedVoluntaryExit { - message VoluntaryExit { - uint64 epoch = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives.Epoch"]; - uint64 validator_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives.ValidatorIndex"]; - } - VoluntaryExit message = 1; - bytes signature = 2; - } - SignedVoluntaryExit data = 1; -} diff --git a/validator/node/BUILD.bazel b/validator/node/BUILD.bazel index 2da3678828..3bf40ed338 100644 --- a/validator/node/BUILD.bazel +++ b/validator/node/BUILD.bazel @@ -41,6 +41,7 @@ go_library( deps = [ "//api/gateway:go_default_library", "//api/gateway/apimiddleware:go_default_library", + "//api/server:go_default_library", "//async/event:go_default_library", "//cmd:go_default_library", "//cmd/validator/flags:go_default_library", diff --git a/validator/node/node.go b/validator/node/node.go index 64a6cad2dc..16bacc29a4 100644 --- a/validator/node/node.go +++ b/validator/node/node.go @@ -28,6 +28,7 @@ import ( fastssz "github.com/prysmaticlabs/fastssz" "github.com/prysmaticlabs/prysm/v4/api/gateway" "github.com/prysmaticlabs/prysm/v4/api/gateway/apimiddleware" + "github.com/prysmaticlabs/prysm/v4/api/server" "github.com/prysmaticlabs/prysm/v4/async/event" "github.com/prysmaticlabs/prysm/v4/cmd" "github.com/prysmaticlabs/prysm/v4/cmd/validator/flags" @@ -129,6 +130,9 @@ func NewValidatorClient(cliCtx *cli.Context) (*ValidatorClient, error) { configureFastSSZHashingAlgorithm() + // initialize router used for endpoints + router := mux.NewRouter() + router.Use(server.NormalizeQueryValuesHandler) // If the --web flag is enabled to administer the validator // client via a web portal, we start the validator client in a different way. // Change Web flag name to enable keymanager API, look at merging initializeFromCLI and initializeForWeb maybe after WebUI DEPRECATED. @@ -137,13 +141,13 @@ func NewValidatorClient(cliCtx *cli.Context) (*ValidatorClient, error) { log.Warn("Remote Keymanager API enabled. Prysm web does not properly support web3signer at this time") } log.Info("Enabling web portal to manage the validator client") - if err := validatorClient.initializeForWeb(cliCtx); err != nil { + if err := validatorClient.initializeForWeb(cliCtx, router); err != nil { return nil, err } return validatorClient, nil } - if err := validatorClient.initializeFromCLI(cliCtx); err != nil { + if err := validatorClient.initializeFromCLI(cliCtx, router); err != nil { return nil, err } @@ -195,7 +199,7 @@ func (c *ValidatorClient) Close() { close(c.stop) } -func (c *ValidatorClient) initializeFromCLI(cliCtx *cli.Context) error { +func (c *ValidatorClient) initializeFromCLI(cliCtx *cli.Context, router *mux.Router) error { var err error dataDir := cliCtx.String(flags.WalletDirFlag.Name) if !cliCtx.IsSet(flags.InteropNumValidators.Name) { @@ -267,17 +271,17 @@ func (c *ValidatorClient) initializeFromCLI(cliCtx *cli.Context) error { return err } if cliCtx.Bool(flags.EnableRPCFlag.Name) { - if err := c.registerRPCService(cliCtx); err != nil { + if err := c.registerRPCService(router); err != nil { return err } - if err := c.registerRPCGatewayService(cliCtx); err != nil { + if err := c.registerRPCGatewayService(router); err != nil { return err } } return nil } -func (c *ValidatorClient) initializeForWeb(cliCtx *cli.Context) error { +func (c *ValidatorClient) initializeForWeb(cliCtx *cli.Context, router *mux.Router) error { var err error dataDir := cliCtx.String(flags.WalletDirFlag.Name) if cliCtx.IsSet(flags.Web3SignerURLFlag.Name) { @@ -342,10 +346,11 @@ func (c *ValidatorClient) initializeForWeb(cliCtx *cli.Context) error { if err := c.registerValidatorService(cliCtx); err != nil { return err } - if err := c.registerRPCService(cliCtx); err != nil { + + if err := c.registerRPCService(router); err != nil { return err } - if err := c.registerRPCGatewayService(cliCtx); err != nil { + if err := c.registerRPCGatewayService(router); err != nil { return err } gatewayHost := cliCtx.String(flags.GRPCGatewayHost.Name) @@ -722,26 +727,26 @@ func reviewGasLimit(gasLimit validator.Uint64) validator.Uint64 { return gasLimit } -func (c *ValidatorClient) registerRPCService(cliCtx *cli.Context) error { +func (c *ValidatorClient) registerRPCService(router *mux.Router) error { var vs *client.ValidatorService if err := c.services.FetchService(&vs); err != nil { return err } - validatorGatewayHost := cliCtx.String(flags.GRPCGatewayHost.Name) - validatorGatewayPort := cliCtx.Int(flags.GRPCGatewayPort.Name) - validatorMonitoringHost := cliCtx.String(cmd.MonitoringHostFlag.Name) - validatorMonitoringPort := cliCtx.Int(flags.MonitoringPortFlag.Name) - rpcHost := cliCtx.String(flags.RPCHost.Name) - rpcPort := cliCtx.Int(flags.RPCPort.Name) - nodeGatewayEndpoint := cliCtx.String(flags.BeaconRPCGatewayProviderFlag.Name) - beaconClientEndpoint := cliCtx.String(flags.BeaconRPCProviderFlag.Name) + validatorGatewayHost := c.cliCtx.String(flags.GRPCGatewayHost.Name) + validatorGatewayPort := c.cliCtx.Int(flags.GRPCGatewayPort.Name) + validatorMonitoringHost := c.cliCtx.String(cmd.MonitoringHostFlag.Name) + validatorMonitoringPort := c.cliCtx.Int(flags.MonitoringPortFlag.Name) + rpcHost := c.cliCtx.String(flags.RPCHost.Name) + rpcPort := c.cliCtx.Int(flags.RPCPort.Name) + nodeGatewayEndpoint := c.cliCtx.String(flags.BeaconRPCGatewayProviderFlag.Name) + beaconClientEndpoint := c.cliCtx.String(flags.BeaconRPCProviderFlag.Name) maxCallRecvMsgSize := c.cliCtx.Int(cmd.GrpcMaxCallRecvMsgSizeFlag.Name) grpcRetries := c.cliCtx.Uint(flags.GrpcRetriesFlag.Name) grpcRetryDelay := c.cliCtx.Duration(flags.GrpcRetryDelayFlag.Name) - walletDir := cliCtx.String(flags.WalletDirFlag.Name) + walletDir := c.cliCtx.String(flags.WalletDirFlag.Name) grpcHeaders := c.cliCtx.String(flags.GrpcHeadersFlag.Name) clientCert := c.cliCtx.String(flags.CertFlag.Name) - server := rpc.NewServer(cliCtx.Context, &rpc.Config{ + server := rpc.NewServer(c.cliCtx.Context, &rpc.Config{ ValDB: c.db, Host: rpcHost, Port: fmt.Sprintf("%d", rpcPort), @@ -762,31 +767,32 @@ func (c *ValidatorClient) registerRPCService(cliCtx *cli.Context) error { ClientGrpcRetryDelay: grpcRetryDelay, ClientGrpcHeaders: strings.Split(grpcHeaders, ","), ClientWithCert: clientCert, + Router: router, }) return c.services.RegisterService(server) } -func (c *ValidatorClient) registerRPCGatewayService(cliCtx *cli.Context) error { - gatewayHost := cliCtx.String(flags.GRPCGatewayHost.Name) +func (c *ValidatorClient) registerRPCGatewayService(router *mux.Router) error { + gatewayHost := c.cliCtx.String(flags.GRPCGatewayHost.Name) if gatewayHost != flags.DefaultGatewayHost { log.WithField("web-host", gatewayHost).Warn( "You are using a non-default web host. Web traffic is served by HTTP, so be wary of " + "changing this parameter if you are exposing this host to the Internet!", ) } - gatewayPort := cliCtx.Int(flags.GRPCGatewayPort.Name) - rpcHost := cliCtx.String(flags.RPCHost.Name) - rpcPort := cliCtx.Int(flags.RPCPort.Name) + gatewayPort := c.cliCtx.Int(flags.GRPCGatewayPort.Name) + rpcHost := c.cliCtx.String(flags.RPCHost.Name) + rpcPort := c.cliCtx.Int(flags.RPCPort.Name) rpcAddr := net.JoinHostPort(rpcHost, fmt.Sprintf("%d", rpcPort)) gatewayAddress := net.JoinHostPort(gatewayHost, fmt.Sprintf("%d", gatewayPort)) - timeout := cliCtx.Int(cmd.ApiTimeoutFlag.Name) + timeout := c.cliCtx.Int(cmd.ApiTimeoutFlag.Name) var allowedOrigins []string - if cliCtx.IsSet(flags.GPRCGatewayCorsDomain.Name) { - allowedOrigins = strings.Split(cliCtx.String(flags.GPRCGatewayCorsDomain.Name), ",") + if c.cliCtx.IsSet(flags.GPRCGatewayCorsDomain.Name) { + allowedOrigins = strings.Split(c.cliCtx.String(flags.GPRCGatewayCorsDomain.Name), ",") } else { allowedOrigins = strings.Split(flags.GPRCGatewayCorsDomain.Value, ",") } - maxCallSize := cliCtx.Uint64(cmd.GrpcMaxCallRecvMsgSizeFlag.Name) + maxCallSize := c.cliCtx.Uint64(cmd.GrpcMaxCallRecvMsgSizeFlag.Name) registrations := []gateway.PbHandlerRegistration{ validatorpb.RegisterAuthHandler, @@ -837,11 +843,15 @@ func (c *ValidatorClient) registerRPCGatewayService(cliCtx *cli.Context) error { // remove "/accounts/", "/v2/" after WebUI DEPRECATED pbHandler := &gateway.PbMux{ Registrations: registrations, - Patterns: []string{"/accounts/", "/v2/", "/internal/eth/v1/"}, - Mux: gwmux, + Patterns: []string{ + "/accounts/", + "/v2/", + "/internal/eth/v1/", + }, + Mux: gwmux, } opts := []gateway.Option{ - gateway.WithRouter(mux.NewRouter()), + gateway.WithRouter(router), gateway.WithRemoteAddr(rpcAddr), gateway.WithGatewayAddr(gatewayAddress), gateway.WithMaxCallRecvMsgSize(maxCallSize), @@ -851,7 +861,7 @@ func (c *ValidatorClient) registerRPCGatewayService(cliCtx *cli.Context) error { gateway.WithMuxHandler(muxHandler), gateway.WithTimeout(uint64(timeout)), } - gw, err := gateway.New(cliCtx.Context, opts...) + gw, err := gateway.New(c.cliCtx.Context, opts...) if err != nil { return err } diff --git a/validator/rpc/BUILD.bazel b/validator/rpc/BUILD.bazel index c4c2e14f2c..a529679a67 100644 --- a/validator/rpc/BUILD.bazel +++ b/validator/rpc/BUILD.bazel @@ -6,12 +6,14 @@ go_library( "accounts.go", "auth_token.go", "beacon.go", + "handlers_keymanager.go", "health.go", "intercepter.go", "log.go", "server.go", "slashing.go", "standard_api.go", + "structs.go", "wallet.go", ], importpath = "github.com/prysmaticlabs/prysm/v4/validator/rpc", @@ -23,11 +25,13 @@ go_library( "//api/grpc:go_default_library", "//api/pagination:go_default_library", "//async/event:go_default_library", + "//beacon-chain/rpc/eth/shared:go_default_library", "//cmd:go_default_library", "//config/features:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//config/validator/service:go_default_library", + "//consensus-types/primitives:go_default_library", "//consensus-types/validator:go_default_library", "//crypto/bls:go_default_library", "//crypto/rand:go_default_library", @@ -36,6 +40,7 @@ go_library( "//io/logs:go_default_library", "//io/prompt:go_default_library", "//monitoring/tracing:go_default_library", + "//network/http:go_default_library", "//proto/eth/service:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/validator-client:go_default_library", @@ -60,6 +65,7 @@ go_library( "@com_github_fsnotify_fsnotify//:go_default_library", "@com_github_golang_jwt_jwt_v4//:go_default_library", "@com_github_golang_protobuf//ptypes/empty", + "@com_github_gorilla_mux//:go_default_library", "@com_github_grpc_ecosystem_go_grpc_middleware//:go_default_library", "@com_github_grpc_ecosystem_go_grpc_middleware//recovery:go_default_library", "@com_github_grpc_ecosystem_go_grpc_middleware//retry:go_default_library", @@ -71,6 +77,7 @@ go_library( "@com_github_tyler_smith_go_bip39//wordlists:go_default_library", "@com_github_wealdtech_go_eth2_wallet_encryptor_keystorev4//:go_default_library", "@io_opencensus_go//plugin/ocgrpc:go_default_library", + "@io_opencensus_go//trace:go_default_library", "@org_golang_google_grpc//:go_default_library", "@org_golang_google_grpc//codes:go_default_library", "@org_golang_google_grpc//credentials:go_default_library", @@ -87,6 +94,7 @@ go_test( "accounts_test.go", "auth_token_test.go", "beacon_test.go", + "handlers_keymanager_test.go", "health_test.go", "intercepter_test.go", "server_test.go", @@ -132,6 +140,7 @@ go_test( "@com_github_golang_mock//gomock:go_default_library", "@com_github_golang_protobuf//ptypes/empty", "@com_github_google_uuid//:go_default_library", + "@com_github_gorilla_mux//:go_default_library", "@com_github_grpc_ecosystem_grpc_gateway_v2//runtime:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_tyler_smith_go_bip39//:go_default_library", diff --git a/validator/rpc/apimiddleware/BUILD.bazel b/validator/rpc/apimiddleware/BUILD.bazel index 5303b02c37..634d560005 100644 --- a/validator/rpc/apimiddleware/BUILD.bazel +++ b/validator/rpc/apimiddleware/BUILD.bazel @@ -3,7 +3,6 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ - "custom_hooks.go", "endpoint_factory.go", "structs.go", ], @@ -17,17 +16,11 @@ go_library( go_test( name = "go_default_test", - srcs = [ - "custom_hooks_test.go", - "structs_test.go", - ], + srcs = ["structs_test.go"], embed = [":go_default_library"], deps = [ - "//api/gateway/apimiddleware:go_default_library", "//config/fieldparams:go_default_library", "//proto/eth/service:go_default_library", - "//testing/assert:go_default_library", "//testing/require:go_default_library", - "@com_github_pkg_errors//:go_default_library", ], ) diff --git a/validator/rpc/apimiddleware/custom_hooks.go b/validator/rpc/apimiddleware/custom_hooks.go deleted file mode 100644 index a00dd91345..0000000000 --- a/validator/rpc/apimiddleware/custom_hooks.go +++ /dev/null @@ -1,39 +0,0 @@ -package apimiddleware - -import ( - "bytes" - "encoding/json" - "io" - "net/http" - "strconv" - - "github.com/prysmaticlabs/prysm/v4/api/gateway/apimiddleware" -) - -// "/eth/v1/validator/{pubkey}/voluntary_exit" POST expects epoch as a query param. -// This hook adds the query param to the body so that it is a valid POST request as -// grpc-gateway does not handle query params in POST requests. -func setVoluntaryExitEpoch( - endpoint *apimiddleware.Endpoint, - _ http.ResponseWriter, - req *http.Request, -) (apimiddleware.RunDefault, apimiddleware.ErrorJson) { - if _, ok := endpoint.PostRequest.(*SetVoluntaryExitRequestJson); ok { - var epoch = req.URL.Query().Get("epoch") - // To handle the request without the query param - if epoch == "" { - epoch = "0" - } - _, err := strconv.ParseUint(epoch, 10, 64) - if err != nil { - return false, apimiddleware.InternalServerErrorWithMessage(err, "invalid epoch") - } - j := &SetVoluntaryExitRequestJson{Epoch: epoch} - b, err := json.Marshal(j) - if err != nil { - return false, apimiddleware.InternalServerErrorWithMessage(err, "could not marshal epoch") - } - req.Body = io.NopCloser(bytes.NewReader(b)) - } - return true, nil -} diff --git a/validator/rpc/apimiddleware/custom_hooks_test.go b/validator/rpc/apimiddleware/custom_hooks_test.go deleted file mode 100644 index dbaa9a6487..0000000000 --- a/validator/rpc/apimiddleware/custom_hooks_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package apimiddleware - -import ( - "bytes" - "encoding/json" - "fmt" - "net/http/httptest" - "testing" - - "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/v4/api/gateway/apimiddleware" - "github.com/prysmaticlabs/prysm/v4/testing/assert" - "github.com/prysmaticlabs/prysm/v4/testing/require" -) - -func TestSetVoluntaryExitEpoch(t *testing.T) { - t.Run("ok", func(t *testing.T) { - endpoint := &apimiddleware.Endpoint{ - PostRequest: &SetVoluntaryExitRequestJson{}, - } - epoch := "300" - - var body bytes.Buffer - request := httptest.NewRequest("POST", fmt.Sprintf("http://foo.example?epoch=%s", epoch), &body) - - runDefault, errJson := setVoluntaryExitEpoch(endpoint, nil, request) - require.Equal(t, true, errJson == nil) - assert.Equal(t, apimiddleware.RunDefault(true), runDefault) - - var b SetVoluntaryExitRequestJson - err := json.NewDecoder(request.Body).Decode(&b) - require.NoError(t, err) - require.Equal(t, epoch, b.Epoch) - }) - t.Run("invalid query returns error", func(t *testing.T) { - endpoint := &apimiddleware.Endpoint{ - PostRequest: &SetVoluntaryExitRequestJson{}, - } - epoch := "/12" - var body bytes.Buffer - request := httptest.NewRequest("POST", fmt.Sprintf("http://foo.example?epoch=%s", epoch), &body) - - runDefault, errJson := setVoluntaryExitEpoch(endpoint, nil, request) - assert.NotNil(t, errJson) - assert.Equal(t, apimiddleware.RunDefault(false), runDefault) - err := errors.New(errJson.Msg()) - assert.ErrorContains(t, "invalid epoch", err) - }) -} diff --git a/validator/rpc/apimiddleware/endpoint_factory.go b/validator/rpc/apimiddleware/endpoint_factory.go index 92e92f6308..50a6f875c6 100644 --- a/validator/rpc/apimiddleware/endpoint_factory.go +++ b/validator/rpc/apimiddleware/endpoint_factory.go @@ -20,7 +20,6 @@ func (*ValidatorEndpointFactory) Paths() []string { "/eth/v1/remotekeys", "/eth/v1/validator/{pubkey}/feerecipient", "/eth/v1/validator/{pubkey}/gas_limit", - "/eth/v1/validator/{pubkey}/voluntary_exit", } } @@ -48,12 +47,6 @@ func (*ValidatorEndpointFactory) Create(path string) (*apimiddleware.Endpoint, e endpoint.GetResponse = &GetGasLimitResponseJson{} endpoint.PostRequest = &SetGasLimitRequestJson{} endpoint.DeleteRequest = &DeleteGasLimitRequestJson{} - case "/eth/v1/validator/{pubkey}/voluntary_exit": - endpoint.PostRequest = &SetVoluntaryExitRequestJson{} - endpoint.PostResponse = &SetVoluntaryExitResponseJson{} - endpoint.Hooks = apimiddleware.HookCollection{ - OnPreDeserializeRequestBodyIntoContainer: setVoluntaryExitEpoch, - } default: return nil, errors.New("invalid path") } diff --git a/validator/rpc/apimiddleware/structs.go b/validator/rpc/apimiddleware/structs.go index 9c80f1e064..6f3937c12d 100644 --- a/validator/rpc/apimiddleware/structs.go +++ b/validator/rpc/apimiddleware/structs.go @@ -100,22 +100,3 @@ type SetGasLimitRequestJson struct { type DeleteGasLimitRequestJson struct { Pubkey string `json:"pubkey" hex:"true"` } - -type SetVoluntaryExitRequestJson struct { - Pubkey string `json:"pubkey" hex:"true"` - Epoch string `json:"epoch"` -} - -type SetVoluntaryExitResponseJson struct { - SignedVoluntaryExit *SignedVoluntaryExitJson `json:"data"` -} - -type SignedVoluntaryExitJson struct { - VoluntaryExit *VoluntaryExitJson `json:"message"` - Signature string `json:"signature" hex:"true"` -} - -type VoluntaryExitJson struct { - Epoch string `json:"epoch"` - ValidatorIndex string `json:"validator_index"` -} diff --git a/validator/rpc/handlers_keymanager.go b/validator/rpc/handlers_keymanager.go new file mode 100644 index 0000000000..cb34ecfa82 --- /dev/null +++ b/validator/rpc/handlers_keymanager.go @@ -0,0 +1,94 @@ +package rpc + +import ( + "fmt" + "net/http" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/gorilla/mux" + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared" + fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams" + "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives" + http2 "github.com/prysmaticlabs/prysm/v4/network/http" + "github.com/prysmaticlabs/prysm/v4/validator/client" + "go.opencensus.io/trace" + "google.golang.org/protobuf/types/known/emptypb" +) + +// SetVoluntaryExit creates a signed voluntary exit message and returns a VoluntaryExit object. +func (s *Server) SetVoluntaryExit(w http.ResponseWriter, r *http.Request) { + ctx, span := trace.StartSpan(r.Context(), "validator.keymanagerAPI.SetVoluntaryExit") + defer span.End() + + if s.validatorService == nil { + http2.HandleError(w, "Validator service not ready", http.StatusServiceUnavailable) + return + } + + if s.wallet == nil { + http2.HandleError(w, "No wallet found", http.StatusServiceUnavailable) + return + } + + km, err := s.validatorService.Keymanager() + if err != nil { + http2.HandleError(w, err.Error(), http.StatusInternalServerError) + return + } + + rawPubkey := mux.Vars(r)["pubkey"] + if rawPubkey == "" { + http2.HandleError(w, "pubkey is required in URL params", http.StatusBadRequest) + return + } + + pubkey, valid := shared.ValidateHex(w, "pubkey", rawPubkey, fieldparams.BLSPubkeyLength) + if !valid { + return + } + + var epoch primitives.Epoch + ok, _, e := shared.UintFromQuery(w, r, "epoch") + if !ok { + http2.HandleError(w, "Invalid epoch", http.StatusBadRequest) + return + } + epoch = primitives.Epoch(e) + + if epoch == 0 { + genesisResponse, err := s.beaconNodeClient.GetGenesis(ctx, &emptypb.Empty{}) + if err != nil { + http2.HandleError(w, errors.Wrap(err, "Failed to get genesis time").Error(), http.StatusInternalServerError) + return + } + currentEpoch, err := client.CurrentEpoch(genesisResponse.GenesisTime) + if err != nil { + http2.HandleError(w, errors.Wrap(err, "Failed to get current epoch").Error(), http.StatusInternalServerError) + return + } + epoch = currentEpoch + } + sve, err := client.CreateSignedVoluntaryExit( + ctx, + s.beaconNodeValidatorClient, + km.Sign, + pubkey, + epoch, + ) + if err != nil { + http2.HandleError(w, errors.Wrap(err, "Could not create voluntary exit").Error(), http.StatusInternalServerError) + return + } + + response := &SetVoluntaryExitResponse{ + Data: &shared.SignedVoluntaryExit{ + Message: &shared.VoluntaryExit{ + Epoch: fmt.Sprintf("%d", sve.Exit.Epoch), + ValidatorIndex: fmt.Sprintf("%d", sve.Exit.ValidatorIndex), + }, + Signature: hexutil.Encode(sve.Signature), + }, + } + http2.WriteJson(w, response) +} diff --git a/validator/rpc/handlers_keymanager_test.go b/validator/rpc/handlers_keymanager_test.go new file mode 100644 index 0000000000..1369a6b574 --- /dev/null +++ b/validator/rpc/handlers_keymanager_test.go @@ -0,0 +1,218 @@ +package rpc + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "net/http" + "net/http/httptest" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/golang/mock/gomock" + "github.com/gorilla/mux" + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives" + eth "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v4/testing/assert" + "github.com/prysmaticlabs/prysm/v4/testing/require" + validatormock "github.com/prysmaticlabs/prysm/v4/testing/validator-mock" + "github.com/prysmaticlabs/prysm/v4/validator/accounts" + "github.com/prysmaticlabs/prysm/v4/validator/accounts/iface" + mock "github.com/prysmaticlabs/prysm/v4/validator/accounts/testing" + "github.com/prysmaticlabs/prysm/v4/validator/client" + "github.com/prysmaticlabs/prysm/v4/validator/keymanager" + "github.com/prysmaticlabs/prysm/v4/validator/keymanager/derived" + mocks "github.com/prysmaticlabs/prysm/v4/validator/testing" + "google.golang.org/grpc" + "google.golang.org/protobuf/types/known/emptypb" + "google.golang.org/protobuf/types/known/timestamppb" +) + +func TestServer_SetVoluntaryExit(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + ctx := grpc.NewContextWithServerTransportStream(context.Background(), &runtime.ServerTransportStream{}) + defaultWalletPath = setupWalletDir(t) + opts := []accounts.Option{ + accounts.WithWalletDir(defaultWalletPath), + accounts.WithKeymanagerType(keymanager.Derived), + accounts.WithWalletPassword(strongPass), + accounts.WithSkipMnemonicConfirm(true), + } + acc, err := accounts.NewCLIManager(opts...) + require.NoError(t, err) + w, err := acc.WalletCreate(ctx) + require.NoError(t, err) + km, err := w.InitializeKeymanager(ctx, iface.InitKeymanagerConfig{ListenForChanges: false}) + require.NoError(t, err) + + m := &mock.MockValidator{Km: km} + vs, err := client.NewValidatorService(ctx, &client.Config{ + Validator: m, + }) + require.NoError(t, err) + + dr, ok := km.(*derived.Keymanager) + require.Equal(t, true, ok) + err = dr.RecoverAccountsFromMnemonic(ctx, mocks.TestMnemonic, derived.DefaultMnemonicLanguage, "", 1) + require.NoError(t, err) + pubKeys, err := dr.FetchValidatingPublicKeys(ctx) + require.NoError(t, err) + + beaconClient := validatormock.NewMockValidatorClient(ctrl) + mockNodeClient := validatormock.NewMockNodeClient(ctrl) + // Any time in the past will suffice + genesisTime := ×tamppb.Timestamp{ + Seconds: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC).Unix(), + } + + beaconClient.EXPECT().ValidatorIndex(gomock.Any(), ð.ValidatorIndexRequest{PublicKey: pubKeys[0][:]}). + Times(3). + Return(ð.ValidatorIndexResponse{Index: 2}, nil) + + beaconClient.EXPECT().DomainData( + gomock.Any(), // ctx + gomock.Any(), // epoch + ).Times(3). + Return(ð.DomainResponse{SignatureDomain: make([]byte, common.HashLength)}, nil /*err*/) + + mockNodeClient.EXPECT(). + GetGenesis(gomock.Any(), gomock.Any()). + Times(3). + Return(ð.Genesis{GenesisTime: genesisTime}, nil) + + s := &Server{ + validatorService: vs, + beaconNodeValidatorClient: beaconClient, + wallet: w, + beaconNodeClient: mockNodeClient, + } + + type want struct { + epoch primitives.Epoch + validatorIndex uint64 + signature []byte + } + + type wantError struct { + expectedStatusCode int + expectedErrorMsg string + } + + tests := []struct { + name string + epoch int + pubkey string + w want + wError *wantError + mockSetup func(s *Server) error + }{ + { + name: "Ok: with epoch", + epoch: 30000000, + pubkey: hexutil.Encode(pubKeys[0][:]), + w: want{ + epoch: 30000000, + validatorIndex: 2, + signature: []uint8{175, 157, 5, 134, 253, 2, 193, 35, 176, 43, 217, 36, 39, 240, 24, 79, 207, 133, 150, 7, 237, 16, 54, 244, 64, 27, 244, 17, 8, 225, 140, 1, 172, 24, 35, 95, 178, 116, 172, 213, 113, 182, 193, 61, 192, 65, 162, 253, 19, 202, 111, 164, 195, 215, 0, 205, 95, 7, 30, 251, 244, 157, 210, 155, 238, 30, 35, 219, 177, 232, 174, 62, 218, 69, 23, 249, 180, 140, 60, 29, 190, 249, 229, 95, 235, 236, 81, 33, 60, 4, 201, 227, 70, 239, 167, 2}, + }, + }, + { + name: "Ok: epoch not set", + pubkey: hexutil.Encode(pubKeys[0][:]), + w: want{ + epoch: 0, + validatorIndex: 2, + signature: []uint8{}, + }, + }, + { + name: "Error: Missing Public Key in URL Params", + epoch: 30000000, + wError: &wantError{ + expectedStatusCode: http.StatusBadRequest, + expectedErrorMsg: "pubkey is required in URL params", + }, + }, + { + name: "Error: Invalid Public Key Length", + epoch: 30000000, + pubkey: "0x1asd1231", + wError: &wantError{ + expectedStatusCode: http.StatusBadRequest, + expectedErrorMsg: "pubkey is invalid: invalid hex string", + }, + }, + { + name: "Error: No Wallet Found", + epoch: 30000000, + pubkey: hexutil.Encode(pubKeys[0][:]), + wError: &wantError{ + expectedStatusCode: http.StatusServiceUnavailable, + expectedErrorMsg: "No wallet found", + }, + mockSetup: func(s *Server) error { + s.wallet = nil + return nil + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.mockSetup != nil { + require.NoError(t, tt.mockSetup(s)) + } + req := httptest.NewRequest("POST", fmt.Sprintf("/eth/v1/validator/{pubkey}/voluntary_exit?epoch=%d", tt.epoch), nil) + req = mux.SetURLVars(req, map[string]string{"pubkey": tt.pubkey}) + w := httptest.NewRecorder() + w.Body = &bytes.Buffer{} + + s.SetVoluntaryExit(w, req) + if tt.wError != nil { + assert.Equal(t, tt.wError.expectedStatusCode, w.Code) + require.StringContains(t, tt.wError.expectedErrorMsg, w.Body.String()) + return + } else { + assert.Equal(t, http.StatusOK, w.Code) + } + resp := &SetVoluntaryExitResponse{} + require.NoError(t, json.Unmarshal(w.Body.Bytes(), resp)) + if tt.w.epoch == 0 { + genesisResponse, err := s.beaconNodeClient.GetGenesis(ctx, &emptypb.Empty{}) + require.NoError(t, err) + tt.w.epoch, err = client.CurrentEpoch(genesisResponse.GenesisTime) + require.NoError(t, err) + req2 := httptest.NewRequest("POST", fmt.Sprintf("/eth/v1/validator/{pubkey}/voluntary_exit?epoch=%d", tt.epoch), nil) + req2 = mux.SetURLVars(req2, map[string]string{"pubkey": hexutil.Encode(pubKeys[0][:])}) + w2 := httptest.NewRecorder() + w2.Body = &bytes.Buffer{} + s.SetVoluntaryExit(w2, req2) + if tt.wError != nil { + assert.Equal(t, tt.wError.expectedStatusCode, w2.Code) + require.StringContains(t, tt.wError.expectedErrorMsg, w2.Body.String()) + } else { + assert.Equal(t, http.StatusOK, w2.Code) + resp2 := &SetVoluntaryExitResponse{} + require.NoError(t, json.Unmarshal(w2.Body.Bytes(), resp2)) + tt.w.signature, err = hexutil.Decode(resp2.Data.Signature) + require.NoError(t, err) + } + + } + if tt.wError == nil { + require.Equal(t, fmt.Sprintf("%d", tt.w.epoch), resp.Data.Message.Epoch) + require.Equal(t, fmt.Sprintf("%d", tt.w.validatorIndex), resp.Data.Message.ValidatorIndex) + require.NotEmpty(t, resp.Data.Signature) + bSig, err := hexutil.Decode(resp.Data.Signature) + require.NoError(t, err) + ok = bytes.Equal(tt.w.signature, bSig) + require.Equal(t, true, ok) + } + }) + } +} diff --git a/validator/rpc/server.go b/validator/rpc/server.go index 17daabc17a..8096ae3af2 100644 --- a/validator/rpc/server.go +++ b/validator/rpc/server.go @@ -4,9 +4,11 @@ import ( "context" "fmt" "net" + "net/http" "path/filepath" "time" + "github.com/gorilla/mux" middleware "github.com/grpc-ecosystem/go-grpc-middleware" recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" grpcopentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing" @@ -51,6 +53,7 @@ type Config struct { GenesisFetcher client.GenesisFetcher WalletInitializedFeed *event.Feed NodeGatewayEndpoint string + Router *mux.Router Wallet *wallet.Wallet } @@ -93,6 +96,7 @@ type Server struct { validatorGatewayPort int beaconApiEndpoint string beaconApiTimeout time.Duration + router *mux.Router } // NewServer instantiates a new gRPC server. @@ -126,6 +130,7 @@ func NewServer(ctx context.Context, cfg *Config) *Server { validatorMonitoringPort: cfg.ValidatorMonitoringPort, validatorGatewayHost: cfg.ValidatorGatewayHost, validatorGatewayPort: cfg.ValidatorGatewayPort, + router: cfg.Router, } } @@ -153,7 +158,6 @@ func (s *Server) Start() { )), } grpcprometheus.EnableHandlingTimeHistogram() - if s.withCert != "" && s.withKey != "" { creds, err := credentials.NewServerTLSFromFile(s.withCert, s.withKey) if err != nil { @@ -189,6 +193,7 @@ func (s *Server) Start() { } } }() + log.WithField("address", address).Info("gRPC server listening on address") if s.walletDir != "" { token, err := s.initializeAuthToken(s.walletDir) @@ -201,6 +206,8 @@ func (s *Server) Start() { logValidatorWebAuth(validatorWebAddr, token, authTokenPath) go s.refreshAuthTokenFromFileChanges(s.ctx, authTokenPath) } + + s.router.HandleFunc("/eth/v1/validator/{pubkey}/voluntary_exit", s.SetVoluntaryExit).Methods(http.MethodPost) } // Stop the gRPC server. diff --git a/validator/rpc/standard_api.go b/validator/rpc/standard_api.go index 450eb7bba5..702decf48e 100644 --- a/validator/rpc/standard_api.go +++ b/validator/rpc/standard_api.go @@ -16,7 +16,6 @@ import ( "github.com/prysmaticlabs/prysm/v4/encoding/bytesutil" ethpbservice "github.com/prysmaticlabs/prysm/v4/proto/eth/service" eth "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v4/validator/client" "github.com/prysmaticlabs/prysm/v4/validator/keymanager" "github.com/prysmaticlabs/prysm/v4/validator/keymanager/derived" slashingprotection "github.com/prysmaticlabs/prysm/v4/validator/slashing-protection-history" @@ -25,7 +24,6 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" - "google.golang.org/protobuf/types/known/emptypb" ) // ListKeystores implements the standard validator key management API. @@ -681,51 +679,3 @@ func validatePublicKey(pubkey []byte) error { } return nil } - -// SetVoluntaryExit creates a signed voluntary exit message and returns a VoluntaryExit object. -func (s *Server) SetVoluntaryExit(ctx context.Context, req *ethpbservice.SetVoluntaryExitRequest) (*ethpbservice.SetVoluntaryExitResponse, error) { - if s.validatorService == nil { - return nil, status.Error(codes.FailedPrecondition, "Validator service not ready") - } - if err := validatePublicKey(req.Pubkey); err != nil { - return nil, status.Error(codes.FailedPrecondition, err.Error()) - } - if s.wallet == nil { - return nil, status.Error(codes.FailedPrecondition, "No wallet found") - } - km, err := s.validatorService.Keymanager() - if err != nil { - return nil, err - } - if req.Epoch == 0 { - genesisResponse, err := s.beaconNodeClient.GetGenesis(ctx, &emptypb.Empty{}) - if err != nil { - return nil, status.Errorf(codes.Internal, "Could not create voluntary exit: %v", err) - } - epoch, err := client.CurrentEpoch(genesisResponse.GenesisTime) - if err != nil { - return nil, status.Errorf(codes.Internal, "gRPC call to get genesis time failed: %v", err) - } - req.Epoch = epoch - } - sve, err := client.CreateSignedVoluntaryExit( - ctx, - s.beaconNodeValidatorClient, - km.Sign, - req.Pubkey, - req.Epoch, - ) - if err != nil { - return nil, status.Errorf(codes.Internal, "Could not create voluntary exit: %v", err) - } - - return ðpbservice.SetVoluntaryExitResponse{ - Data: ðpbservice.SetVoluntaryExitResponse_SignedVoluntaryExit{ - Message: ðpbservice.SetVoluntaryExitResponse_SignedVoluntaryExit_VoluntaryExit{ - Epoch: uint64(sve.Exit.Epoch), - ValidatorIndex: uint64(sve.Exit.ValidatorIndex), - }, - Signature: sve.Signature, - }, - }, nil -} diff --git a/validator/rpc/standard_api_test.go b/validator/rpc/standard_api_test.go index 678478543c..acb1948ced 100644 --- a/validator/rpc/standard_api_test.go +++ b/validator/rpc/standard_api_test.go @@ -1,14 +1,12 @@ package rpc import ( - "bytes" "context" "encoding/hex" "encoding/json" "errors" "fmt" "testing" - "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -19,7 +17,6 @@ import ( fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams" "github.com/prysmaticlabs/prysm/v4/config/params" validatorserviceconfig "github.com/prysmaticlabs/prysm/v4/config/validator/service" - "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v4/consensus-types/validator" "github.com/prysmaticlabs/prysm/v4/crypto/bls" "github.com/prysmaticlabs/prysm/v4/encoding/bytesutil" @@ -44,8 +41,6 @@ import ( keystorev4 "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4" "google.golang.org/grpc" "google.golang.org/grpc/codes" - "google.golang.org/protobuf/types/known/emptypb" - "google.golang.org/protobuf/types/known/timestamppb" ) func TestServer_ListKeystores(t *testing.T) { @@ -1551,116 +1546,3 @@ func TestServer_DeleteGasLimit(t *testing.T) { }) } } - -func TestServer_SetVoluntaryExit(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - ctx := grpc.NewContextWithServerTransportStream(context.Background(), &runtime.ServerTransportStream{}) - defaultWalletPath = setupWalletDir(t) - opts := []accounts.Option{ - accounts.WithWalletDir(defaultWalletPath), - accounts.WithKeymanagerType(keymanager.Derived), - accounts.WithWalletPassword(strongPass), - accounts.WithSkipMnemonicConfirm(true), - } - acc, err := accounts.NewCLIManager(opts...) - require.NoError(t, err) - w, err := acc.WalletCreate(ctx) - require.NoError(t, err) - km, err := w.InitializeKeymanager(ctx, iface.InitKeymanagerConfig{ListenForChanges: false}) - require.NoError(t, err) - - m := &mock.MockValidator{Km: km} - vs, err := client.NewValidatorService(ctx, &client.Config{ - Validator: m, - }) - require.NoError(t, err) - - dr, ok := km.(*derived.Keymanager) - require.Equal(t, true, ok) - err = dr.RecoverAccountsFromMnemonic(ctx, mocks.TestMnemonic, derived.DefaultMnemonicLanguage, "", 1) - require.NoError(t, err) - pubKeys, err := dr.FetchValidatingPublicKeys(ctx) - require.NoError(t, err) - - beaconClient := validatormock.NewMockValidatorClient(ctrl) - mockNodeClient := validatormock.NewMockNodeClient(ctrl) - // Any time in the past will suffice - genesisTime := ×tamppb.Timestamp{ - Seconds: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC).Unix(), - } - - beaconClient.EXPECT().ValidatorIndex(gomock.Any(), ð.ValidatorIndexRequest{PublicKey: pubKeys[0][:]}). - Times(3). - Return(ð.ValidatorIndexResponse{Index: 2}, nil) - - beaconClient.EXPECT().DomainData( - gomock.Any(), // ctx - gomock.Any(), // epoch - ).Times(3). - Return(ð.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/) - - mockNodeClient.EXPECT(). - GetGenesis(gomock.Any(), gomock.Any()). - Times(3). - Return(ð.Genesis{GenesisTime: genesisTime}, nil) - - s := &Server{ - validatorService: vs, - beaconNodeValidatorClient: beaconClient, - wallet: w, - beaconNodeClient: mockNodeClient, - } - - type want struct { - epoch primitives.Epoch - validatorIndex uint64 - signature []byte - } - - tests := []struct { - name string - pubkey []byte - epoch primitives.Epoch - w want - }{ - { - name: "Ok: with epoch", - epoch: 30000000, - w: want{ - epoch: 30000000, - validatorIndex: 2, - signature: []uint8{175, 157, 5, 134, 253, 2, 193, 35, 176, 43, 217, 36, 39, 240, 24, 79, 207, 133, 150, 7, 237, 16, 54, 244, 64, 27, 244, 17, 8, 225, 140, 1, 172, 24, 35, 95, 178, 116, 172, 213, 113, 182, 193, 61, 192, 65, 162, 253, 19, 202, 111, 164, 195, 215, 0, 205, 95, 7, 30, 251, 244, 157, 210, 155, 238, 30, 35, 219, 177, 232, 174, 62, 218, 69, 23, 249, 180, 140, 60, 29, 190, 249, 229, 95, 235, 236, 81, 33, 60, 4, 201, 227, 70, 239, 167, 2}, - }, - }, - { - name: "Ok: epoch not set", - w: want{ - epoch: 0, - validatorIndex: 2, - signature: []uint8{}, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - resp, err := s.SetVoluntaryExit(ctx, ðpbservice.SetVoluntaryExitRequest{Pubkey: pubKeys[0][:], Epoch: tt.epoch}) - require.NoError(t, err) - if tt.w.epoch == 0 { - genesisResponse, err := s.beaconNodeClient.GetGenesis(ctx, &emptypb.Empty{}) - require.NoError(t, err) - tt.w.epoch, err = client.CurrentEpoch(genesisResponse.GenesisTime) - require.NoError(t, err) - resp2, err := s.SetVoluntaryExit(ctx, ðpbservice.SetVoluntaryExitRequest{Pubkey: pubKeys[0][:], Epoch: tt.epoch}) - require.NoError(t, err) - tt.w.signature = resp2.Data.Signature - } - require.Equal(t, uint64(tt.w.epoch), resp.Data.Message.Epoch) - require.Equal(t, tt.w.validatorIndex, resp.Data.Message.ValidatorIndex) - require.NotEmpty(t, resp.Data.Signature) - ok = bytes.Equal(tt.w.signature, resp.Data.Signature) - require.Equal(t, true, ok) - }) - } -} diff --git a/validator/rpc/structs.go b/validator/rpc/structs.go new file mode 100644 index 0000000000..e377c4923e --- /dev/null +++ b/validator/rpc/structs.go @@ -0,0 +1,7 @@ +package rpc + +import "github.com/prysmaticlabs/prysm/v4/beacon-chain/rpc/eth/shared" + +type SetVoluntaryExitResponse struct { + Data *shared.SignedVoluntaryExit `json:"data"` +}