diff --git a/CHANGELOG.md b/CHANGELOG.md index dc8a1135..56bf1350 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) * [#184](https://github.com/babylonlabs-io/finality-provider/pull/184) eots manager sign record store * [#189](https://github.com/babylonlabs-io/finality-provider/pull/189) Remove `fpd register-finality-provider` cmd * [#190](https://github.com/babylonlabs-io/finality-provider/pull/190) Benchmark pub rand +* [#193](https://github.com/babylonlabs-io/finality-provider/pull/193) adds unsafeSignEOTS for e2e tests +* [#195](https://github.com/babylonlabs-io/finality-provider/pull/195) Not block unjailing * [#197](https://github.com/babylonlabs-io/finality-provider/pull/197) Bump Babylon to v0.18.0 ### Bug Fixes diff --git a/eotsmanager/client/rpcclient.go b/eotsmanager/client/rpcclient.go index 821ecb18..c306e830 100644 --- a/eotsmanager/client/rpcclient.go +++ b/eotsmanager/client/rpcclient.go @@ -118,6 +118,25 @@ func (c *EOTSManagerGRpcClient) SignEOTS(uid, chaiID, msg []byte, height uint64, return &s, nil } +func (c *EOTSManagerGRpcClient) UnsafeSignEOTS(uid, chaiID, msg []byte, height uint64, passphrase string) (*btcec.ModNScalar, error) { + req := &proto.SignEOTSRequest{ + Uid: uid, + ChainId: chaiID, + Msg: msg, + Height: height, + Passphrase: passphrase, + } + res, err := c.client.UnsafeSignEOTS(context.Background(), req) + if err != nil { + return nil, err + } + + var s btcec.ModNScalar + s.SetByteSlice(res.Sig) + + return &s, nil +} + func (c *EOTSManagerGRpcClient) SignSchnorrSig(uid, msg []byte, passphrase string) (*schnorr.Signature, error) { req := &proto.SignSchnorrSigRequest{Uid: uid, Msg: msg, Passphrase: passphrase} res, err := c.client.SignSchnorrSig(context.Background(), req) diff --git a/eotsmanager/eotsmanager.go b/eotsmanager/eotsmanager.go index 04d02316..017bd941 100644 --- a/eotsmanager/eotsmanager.go +++ b/eotsmanager/eotsmanager.go @@ -28,9 +28,15 @@ type EOTSManager interface { // SignEOTS signs an EOTS using the private key of the finality provider and the corresponding // secret randomness of the given chain at the given height // It fails if the finality provider does not exist or there's no randomness committed to the given height - // or passPhrase is incorrect + // or passPhrase is incorrect. Has built-in anti-slashing mechanism to ensure signature + // for the same height will not be signed twice. SignEOTS(uid []byte, chainID []byte, msg []byte, height uint64, passphrase string) (*btcec.ModNScalar, error) + // UnsafeSignEOTS should only be used in e2e tests for demonstration purposes. + // Does not offer double sign protection. + // Use SignEOTS for real operations. + UnsafeSignEOTS(uid []byte, chainID []byte, msg []byte, height uint64, passphrase string) (*btcec.ModNScalar, error) + // SignSchnorrSig signs a Schnorr signature using the private key of the finality provider // It fails if the finality provider does not exist or the message size is not 32 bytes // or passPhrase is incorrect diff --git a/eotsmanager/localmanager.go b/eotsmanager/localmanager.go index 45c57a28..45bd5ee5 100644 --- a/eotsmanager/localmanager.go +++ b/eotsmanager/localmanager.go @@ -205,6 +205,14 @@ func (lm *LocalEOTSManager) SignEOTS(fpPk []byte, chainID []byte, msg []byte, he return &s, nil } + lm.logger.Error( + "double sign error protection", + zap.String("fp", hex.EncodeToString(fpPk)), + zap.String("msg", hex.EncodeToString(msg)), + zap.Uint64("height", height), + zap.String("chainID", string(chainID)), + ) + return nil, eotstypes.ErrDoubleSign } @@ -235,6 +243,25 @@ func (lm *LocalEOTSManager) SignEOTS(fpPk []byte, chainID []byte, msg []byte, he return signedBytes, nil } +// UnsafeSignEOTS should only be used in e2e test to demonstrate double sign +func (lm *LocalEOTSManager) UnsafeSignEOTS(fpPk []byte, chainID []byte, msg []byte, height uint64, passphrase string) (*btcec.ModNScalar, error) { + privRand, _, err := lm.getRandomnessPair(fpPk, chainID, height, passphrase) + if err != nil { + return nil, fmt.Errorf("failed to get private randomness: %w", err) + } + + privKey, err := lm.getEOTSPrivKey(fpPk, passphrase) + if err != nil { + return nil, fmt.Errorf("failed to get EOTS private key: %w", err) + } + + // Update metrics + lm.metrics.IncrementEotsFpTotalEotsSignCounter(hex.EncodeToString(fpPk)) + lm.metrics.SetEotsFpLastEotsSignHeight(hex.EncodeToString(fpPk), float64(height)) + + return eots.Sign(privKey, privRand, msg) +} + func (lm *LocalEOTSManager) SignSchnorrSig(fpPk []byte, msg []byte, passphrase string) (*schnorr.Signature, error) { privKey, err := lm.getEOTSPrivKey(fpPk, passphrase) if err != nil { diff --git a/eotsmanager/proto/eotsmanager.pb.go b/eotsmanager/proto/eotsmanager.pb.go index eaf5ac07..d1fa3a55 100644 --- a/eotsmanager/proto/eotsmanager.pb.go +++ b/eotsmanager/proto/eotsmanager.pb.go @@ -760,7 +760,7 @@ var file_eotsmanager_proto_rawDesc = []byte{ 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x22, 0x2a, 0x0a, 0x16, 0x53, 0x69, 0x67, 0x6e, 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, 0x72, 0x53, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x03, 0x73, 0x69, 0x67, 0x32, 0xb7, 0x03, 0x0a, 0x0b, 0x45, 0x4f, 0x54, 0x53, + 0x28, 0x0c, 0x52, 0x03, 0x73, 0x69, 0x67, 0x32, 0xfa, 0x03, 0x0a, 0x0b, 0x45, 0x4f, 0x54, 0x53, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x2f, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x69, 0x6e, 0x67, @@ -783,16 +783,20 @@ var file_eotsmanager_proto_rawDesc = []byte{ 0x53, 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x45, 0x4f, 0x54, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x45, 0x4f, 0x54, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0e, 0x53, 0x69, 0x67, 0x6e, 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, - 0x72, 0x53, 0x69, 0x67, 0x12, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x67, - 0x6e, 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, 0x72, 0x53, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x53, - 0x63, 0x68, 0x6e, 0x6f, 0x72, 0x72, 0x53, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x42, 0x3f, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x6c, 0x61, 0x62, 0x73, 0x2d, 0x69, 0x6f, 0x2f, 0x66, - 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x2d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, - 0x2f, 0x65, 0x6f, 0x74, 0x73, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0e, 0x55, 0x6e, 0x73, 0x61, 0x66, 0x65, 0x53, 0x69, 0x67, 0x6e, + 0x45, 0x4f, 0x54, 0x53, 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x45, 0x4f, 0x54, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x45, 0x4f, 0x54, 0x53, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0e, 0x53, 0x69, 0x67, 0x6e, 0x53, 0x63, 0x68, + 0x6e, 0x6f, 0x72, 0x72, 0x53, 0x69, 0x67, 0x12, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x53, 0x69, 0x67, 0x6e, 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, 0x72, 0x53, 0x69, 0x67, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, + 0x67, 0x6e, 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, 0x72, 0x53, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3f, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x6c, 0x61, 0x62, 0x73, 0x2d, 0x69, + 0x6f, 0x2f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x2d, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x2f, 0x65, 0x6f, 0x74, 0x73, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -828,15 +832,17 @@ var file_eotsmanager_proto_depIdxs = []int32{ 4, // 2: proto.EOTSManager.CreateRandomnessPairList:input_type -> proto.CreateRandomnessPairListRequest 6, // 3: proto.EOTSManager.KeyRecord:input_type -> proto.KeyRecordRequest 8, // 4: proto.EOTSManager.SignEOTS:input_type -> proto.SignEOTSRequest - 10, // 5: proto.EOTSManager.SignSchnorrSig:input_type -> proto.SignSchnorrSigRequest - 1, // 6: proto.EOTSManager.Ping:output_type -> proto.PingResponse - 3, // 7: proto.EOTSManager.CreateKey:output_type -> proto.CreateKeyResponse - 5, // 8: proto.EOTSManager.CreateRandomnessPairList:output_type -> proto.CreateRandomnessPairListResponse - 7, // 9: proto.EOTSManager.KeyRecord:output_type -> proto.KeyRecordResponse - 9, // 10: proto.EOTSManager.SignEOTS:output_type -> proto.SignEOTSResponse - 11, // 11: proto.EOTSManager.SignSchnorrSig:output_type -> proto.SignSchnorrSigResponse - 6, // [6:12] is the sub-list for method output_type - 0, // [0:6] is the sub-list for method input_type + 8, // 5: proto.EOTSManager.UnsafeSignEOTS:input_type -> proto.SignEOTSRequest + 10, // 6: proto.EOTSManager.SignSchnorrSig:input_type -> proto.SignSchnorrSigRequest + 1, // 7: proto.EOTSManager.Ping:output_type -> proto.PingResponse + 3, // 8: proto.EOTSManager.CreateKey:output_type -> proto.CreateKeyResponse + 5, // 9: proto.EOTSManager.CreateRandomnessPairList:output_type -> proto.CreateRandomnessPairListResponse + 7, // 10: proto.EOTSManager.KeyRecord:output_type -> proto.KeyRecordResponse + 9, // 11: proto.EOTSManager.SignEOTS:output_type -> proto.SignEOTSResponse + 9, // 12: proto.EOTSManager.UnsafeSignEOTS:output_type -> proto.SignEOTSResponse + 11, // 13: proto.EOTSManager.SignSchnorrSig:output_type -> proto.SignSchnorrSigResponse + 7, // [7:14] is the sub-list for method output_type + 0, // [0:7] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name diff --git a/eotsmanager/proto/eotsmanager.proto b/eotsmanager/proto/eotsmanager.proto index cc7efec0..ad32b192 100644 --- a/eotsmanager/proto/eotsmanager.proto +++ b/eotsmanager/proto/eotsmanager.proto @@ -23,6 +23,10 @@ service EOTSManager { rpc SignEOTS (SignEOTSRequest) returns (SignEOTSResponse); + // UnsafeSignEOTS used only for testing purpose. Use SignEOTS for real operations + rpc UnsafeSignEOTS (SignEOTSRequest) + returns (SignEOTSResponse); + // SignSchnorrSig signs a Schnorr sig with the EOTS private key rpc SignSchnorrSig (SignSchnorrSigRequest) returns (SignSchnorrSigResponse); diff --git a/eotsmanager/proto/eotsmanager_grpc.pb.go b/eotsmanager/proto/eotsmanager_grpc.pb.go index 0a8814ad..3028009f 100644 --- a/eotsmanager/proto/eotsmanager_grpc.pb.go +++ b/eotsmanager/proto/eotsmanager_grpc.pb.go @@ -24,6 +24,7 @@ const ( EOTSManager_CreateRandomnessPairList_FullMethodName = "/proto.EOTSManager/CreateRandomnessPairList" EOTSManager_KeyRecord_FullMethodName = "/proto.EOTSManager/KeyRecord" EOTSManager_SignEOTS_FullMethodName = "/proto.EOTSManager/SignEOTS" + EOTSManager_UnsafeSignEOTS_FullMethodName = "/proto.EOTSManager/UnsafeSignEOTS" EOTSManager_SignSchnorrSig_FullMethodName = "/proto.EOTSManager/SignSchnorrSig" ) @@ -40,6 +41,8 @@ type EOTSManagerClient interface { KeyRecord(ctx context.Context, in *KeyRecordRequest, opts ...grpc.CallOption) (*KeyRecordResponse, error) // SignEOTS signs an EOTS with the EOTS private key and the relevant randomness SignEOTS(ctx context.Context, in *SignEOTSRequest, opts ...grpc.CallOption) (*SignEOTSResponse, error) + // UnsafeSignEOTS used only for testing purpose. Use SignEOTS for real operations + UnsafeSignEOTS(ctx context.Context, in *SignEOTSRequest, opts ...grpc.CallOption) (*SignEOTSResponse, error) // SignSchnorrSig signs a Schnorr sig with the EOTS private key SignSchnorrSig(ctx context.Context, in *SignSchnorrSigRequest, opts ...grpc.CallOption) (*SignSchnorrSigResponse, error) } @@ -97,6 +100,15 @@ func (c *eOTSManagerClient) SignEOTS(ctx context.Context, in *SignEOTSRequest, o return out, nil } +func (c *eOTSManagerClient) UnsafeSignEOTS(ctx context.Context, in *SignEOTSRequest, opts ...grpc.CallOption) (*SignEOTSResponse, error) { + out := new(SignEOTSResponse) + err := c.cc.Invoke(ctx, EOTSManager_UnsafeSignEOTS_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *eOTSManagerClient) SignSchnorrSig(ctx context.Context, in *SignSchnorrSigRequest, opts ...grpc.CallOption) (*SignSchnorrSigResponse, error) { out := new(SignSchnorrSigResponse) err := c.cc.Invoke(ctx, EOTSManager_SignSchnorrSig_FullMethodName, in, out, opts...) @@ -119,6 +131,8 @@ type EOTSManagerServer interface { KeyRecord(context.Context, *KeyRecordRequest) (*KeyRecordResponse, error) // SignEOTS signs an EOTS with the EOTS private key and the relevant randomness SignEOTS(context.Context, *SignEOTSRequest) (*SignEOTSResponse, error) + // UnsafeSignEOTS used only for testing purpose. Use SignEOTS for real operations + UnsafeSignEOTS(context.Context, *SignEOTSRequest) (*SignEOTSResponse, error) // SignSchnorrSig signs a Schnorr sig with the EOTS private key SignSchnorrSig(context.Context, *SignSchnorrSigRequest) (*SignSchnorrSigResponse, error) mustEmbedUnimplementedEOTSManagerServer() @@ -143,6 +157,9 @@ func (UnimplementedEOTSManagerServer) KeyRecord(context.Context, *KeyRecordReque func (UnimplementedEOTSManagerServer) SignEOTS(context.Context, *SignEOTSRequest) (*SignEOTSResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method SignEOTS not implemented") } +func (UnimplementedEOTSManagerServer) UnsafeSignEOTS(context.Context, *SignEOTSRequest) (*SignEOTSResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UnsafeSignEOTS not implemented") +} func (UnimplementedEOTSManagerServer) SignSchnorrSig(context.Context, *SignSchnorrSigRequest) (*SignSchnorrSigResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method SignSchnorrSig not implemented") } @@ -249,6 +266,24 @@ func _EOTSManager_SignEOTS_Handler(srv interface{}, ctx context.Context, dec fun return interceptor(ctx, in, info, handler) } +func _EOTSManager_UnsafeSignEOTS_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SignEOTSRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EOTSManagerServer).UnsafeSignEOTS(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EOTSManager_UnsafeSignEOTS_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EOTSManagerServer).UnsafeSignEOTS(ctx, req.(*SignEOTSRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _EOTSManager_SignSchnorrSig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(SignSchnorrSigRequest) if err := dec(in); err != nil { @@ -294,6 +329,10 @@ var EOTSManager_ServiceDesc = grpc.ServiceDesc{ MethodName: "SignEOTS", Handler: _EOTSManager_SignEOTS_Handler, }, + { + MethodName: "UnsafeSignEOTS", + Handler: _EOTSManager_UnsafeSignEOTS_Handler, + }, { MethodName: "SignSchnorrSig", Handler: _EOTSManager_SignSchnorrSig_Handler, diff --git a/eotsmanager/service/rpcserver.go b/eotsmanager/service/rpcserver.go index e13f44b5..7827bbee 100644 --- a/eotsmanager/service/rpcserver.go +++ b/eotsmanager/service/rpcserver.go @@ -98,6 +98,19 @@ func (r *rpcServer) SignEOTS(_ context.Context, req *proto.SignEOTSRequest) ( return &proto.SignEOTSResponse{Sig: sigBytes[:]}, nil } +// UnsafeSignEOTS only used for testing purposes. Doesn't offer slashing protection! +func (r *rpcServer) UnsafeSignEOTS(_ context.Context, req *proto.SignEOTSRequest) ( + *proto.SignEOTSResponse, error) { + sig, err := r.em.UnsafeSignEOTS(req.Uid, req.ChainId, req.Msg, req.Height, req.Passphrase) + if err != nil { + return nil, err + } + + sigBytes := sig.Bytes() + + return &proto.SignEOTSResponse{Sig: sigBytes[:]}, nil +} + // SignSchnorrSig signs a Schnorr sig with the EOTS private key func (r *rpcServer) SignSchnorrSig(_ context.Context, req *proto.SignSchnorrSigRequest) ( *proto.SignSchnorrSigResponse, error) { diff --git a/finality-provider/cmd/fpd/daemon/daemon_commands.go b/finality-provider/cmd/fpd/daemon/daemon_commands.go index 3708d045..a943c824 100644 --- a/finality-provider/cmd/fpd/daemon/daemon_commands.go +++ b/finality-provider/cmd/fpd/daemon/daemon_commands.go @@ -359,6 +359,8 @@ func CommandAddFinalitySig() *cobra.Command { } cmd.Flags().String(fpdDaemonAddressFlag, defaultFpdDaemonAddress, "The RPC server address of fpd") cmd.Flags().String(appHashFlag, defaultAppHashStr, "The last commit hash of the chain block") + cmd.Flags().Bool(checkDoubleSignFlag, true, "If 'true', uses anti-slashing protection when doing EOTS sign") + return cmd } @@ -383,6 +385,11 @@ func runCommandAddFinalitySig(cmd *cobra.Command, args []string) error { return fmt.Errorf("failed to read flag %s: %w", appHashFlag, err) } + checkDoubleSign, err := flags.GetBool(checkDoubleSignFlag) + if err != nil { + return fmt.Errorf("failed to read flag %s: %w", checkDoubleSignFlag, err) + } + client, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) if err != nil { return err @@ -398,7 +405,7 @@ func runCommandAddFinalitySig(cmd *cobra.Command, args []string) error { return err } - res, err := client.AddFinalitySignature(context.Background(), fpPk.MarshalHex(), blkHeight, appHash) + res, err := client.AddFinalitySignature(context.Background(), fpPk.MarshalHex(), blkHeight, appHash, checkDoubleSign) if err != nil { return err } diff --git a/finality-provider/cmd/fpd/daemon/flags.go b/finality-provider/cmd/fpd/daemon/flags.go index d0f6b6f6..e20a2fe3 100644 --- a/finality-provider/cmd/fpd/daemon/flags.go +++ b/finality-provider/cmd/fpd/daemon/flags.go @@ -11,6 +11,7 @@ const ( hdPathFlag = "hd-path" chainIDFlag = "chain-id" signedFlag = "signed" + checkDoubleSignFlag = "check-double-sign" // flags for description monikerFlag = "moniker" diff --git a/finality-provider/proto/finality_providers.pb.go b/finality-provider/proto/finality_providers.pb.go index fa9de0f6..2a1bb8e5 100644 --- a/finality-provider/proto/finality_providers.pb.go +++ b/finality-provider/proto/finality_providers.pb.go @@ -349,6 +349,8 @@ type AddFinalitySignatureRequest struct { Height uint64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` // app_hash is the AppHash of the chain block AppHash []byte `protobuf:"bytes,3,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` + // check_double_sign use double sign protection when doing EOTS sign + CheckDoubleSign bool `protobuf:"varint,4,opt,name=check_double_sign,json=checkDoubleSign,proto3" json:"check_double_sign,omitempty"` } func (x *AddFinalitySignatureRequest) Reset() { @@ -404,6 +406,13 @@ func (x *AddFinalitySignatureRequest) GetAppHash() []byte { return nil } +func (x *AddFinalitySignatureRequest) GetCheckDoubleSign() bool { + if x != nil { + return x.CheckDoubleSign + } + return false +} + type AddFinalitySignatureResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1406,198 +1415,201 @@ var file_finality_providers_proto_rawDesc = []byte{ 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x10, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x22, 0x67, 0x0a, 0x1b, - 0x41, 0x64, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x62, - 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, - 0x50, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, - 0x70, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x70, - 0x70, 0x48, 0x61, 0x73, 0x68, 0x22, 0x83, 0x01, 0x0a, 0x1c, 0x41, 0x64, 0x64, 0x46, 0x69, 0x6e, - 0x61, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, - 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, - 0x28, 0x0a, 0x10, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x6b, 0x5f, - 0x68, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x72, 0x61, - 0x63, 0x74, 0x65, 0x64, 0x53, 0x6b, 0x48, 0x65, 0x78, 0x12, 0x20, 0x0a, 0x0c, 0x6c, 0x6f, 0x63, - 0x61, 0x6c, 0x5f, 0x73, 0x6b, 0x5f, 0x68, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x6b, 0x48, 0x65, 0x78, 0x22, 0x36, 0x0a, 0x1d, 0x55, - 0x6e, 0x6a, 0x61, 0x69, 0x6c, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x22, 0x93, 0x01, 0x0a, + 0x1b, 0x41, 0x64, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, - 0x63, 0x50, 0x6b, 0x22, 0x39, 0x0a, 0x1e, 0x55, 0x6e, 0x6a, 0x61, 0x69, 0x6c, 0x46, 0x69, 0x6e, - 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x22, 0x35, - 0x0a, 0x1c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, - 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x62, 0x74, 0x63, 0x50, 0x6b, 0x22, 0x69, 0x0a, 0x1d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, - 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x11, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, - 0x74, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, - 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x10, - 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, - 0x22, 0x22, 0x0a, 0x20, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, - 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x22, 0x6f, 0x0a, 0x21, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, - 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x66, 0x69, 0x6e, - 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, - 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x11, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, - 0x69, 0x64, 0x65, 0x72, 0x73, 0x22, 0xc1, 0x02, 0x0a, 0x10, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, - 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x31, 0x0a, 0x07, 0x66, 0x70, - 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, - 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x66, 0x70, 0x41, 0x64, 0x64, 0x72, 0x12, 0x15, 0x0a, - 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, - 0x74, 0x63, 0x50, 0x6b, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x63, 0x50, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x61, + 0x70, 0x70, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, + 0x70, 0x70, 0x48, 0x61, 0x73, 0x68, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, + 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x53, 0x69, + 0x67, 0x6e, 0x22, 0x83, 0x01, 0x0a, 0x1c, 0x41, 0x64, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, + 0x74, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, 0x28, 0x0a, 0x10, + 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x6b, 0x5f, 0x68, 0x65, 0x78, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x65, + 0x64, 0x53, 0x6b, 0x48, 0x65, 0x78, 0x12, 0x20, 0x0a, 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, + 0x73, 0x6b, 0x5f, 0x68, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x53, 0x6b, 0x48, 0x65, 0x78, 0x22, 0x36, 0x0a, 0x1d, 0x55, 0x6e, 0x6a, 0x61, + 0x69, 0x6c, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, + 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, + 0x22, 0x39, 0x0a, 0x1e, 0x55, 0x6e, 0x6a, 0x61, 0x69, 0x6c, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, + 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x22, 0x35, 0x0a, 0x1c, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x62, + 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, + 0x50, 0x6b, 0x22, 0x69, 0x0a, 0x1d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x11, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x10, 0x66, 0x69, 0x6e, + 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x22, 0x22, 0x0a, + 0x20, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x22, 0x6f, 0x0a, 0x21, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, + 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, + 0x74, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x11, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x73, 0x22, 0xc1, 0x02, 0x0a, 0x10, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x31, 0x0a, 0x07, 0x66, 0x70, 0x5f, 0x61, 0x64, + 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x52, 0x06, 0x66, 0x70, 0x41, 0x64, 0x64, 0x72, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, + 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, + 0x6b, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x43, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x23, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, + 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, + 0x74, 0x68, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x44, 0x65, 0x63, 0x52, 0x0a, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, + 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, + 0x6e, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x76, 0x6f, 0x74, 0x65, + 0x64, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, + 0x6c, 0x61, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x64, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, + 0x35, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, + 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xc5, 0x02, 0x0a, 0x14, 0x46, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, + 0x31, 0x0a, 0x07, 0x66, 0x70, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x66, 0x70, 0x41, 0x64, + 0x64, 0x72, 0x12, 0x1c, 0x0a, 0x0a, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x5f, 0x68, 0x65, 0x78, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x48, 0x65, 0x78, + 0x12, 0x34, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x43, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x23, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x44, 0x65, 0x63, 0x52, - 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x63, - 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, - 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x76, - 0x6f, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x64, 0x48, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x12, 0x35, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6e, 0x61, 0x6c, - 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xc5, 0x02, 0x0a, 0x14, 0x46, 0x69, - 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, - 0x66, 0x6f, 0x12, 0x31, 0x0a, 0x07, 0x66, 0x70, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x66, - 0x70, 0x41, 0x64, 0x64, 0x72, 0x12, 0x1c, 0x0a, 0x0a, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x5f, - 0x68, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x74, 0x63, 0x50, 0x6b, - 0x48, 0x65, 0x78, 0x12, 0x34, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x43, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x23, 0xc8, - 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, - 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x44, - 0x65, 0x63, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2a, - 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x56, - 0x6f, 0x74, 0x65, 0x64, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, - 0x67, 0x22, 0xa2, 0x01, 0x0a, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f, 0x6e, 0x69, 0x6b, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x6d, 0x6f, 0x6e, 0x69, 0x6b, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x69, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x77, 0x65, 0x62, 0x73, 0x69, - 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x77, 0x65, 0x62, 0x73, 0x69, 0x74, - 0x65, 0x12, 0x29, 0x0a, 0x10, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x63, 0x6f, - 0x6e, 0x74, 0x61, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x65, 0x63, - 0x75, 0x72, 0x69, 0x74, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, - 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, - 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x2c, 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x4f, - 0x66, 0x50, 0x6f, 0x73, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x62, - 0x74, 0x63, 0x5f, 0x73, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x62, 0x74, - 0x63, 0x53, 0x69, 0x67, 0x22, 0x47, 0x0a, 0x0f, 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, 0x72, 0x52, - 0x61, 0x6e, 0x64, 0x50, 0x61, 0x69, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x75, 0x62, 0x5f, 0x72, - 0x61, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x75, 0x62, 0x52, 0x61, - 0x6e, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x65, 0x63, 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x65, 0x63, 0x52, 0x61, 0x6e, 0x64, 0x22, 0x94, 0x01, - 0x0a, 0x1e, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x46, 0x72, 0x6f, - 0x6d, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x1e, 0x0a, 0x0b, 0x6d, 0x73, 0x67, 0x5f, 0x74, 0x6f, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x6d, 0x73, 0x67, 0x54, 0x6f, 0x53, 0x69, 0x67, 0x6e, - 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x70, - 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x68, - 0x64, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x68, 0x64, - 0x50, 0x61, 0x74, 0x68, 0x22, 0x3f, 0x0a, 0x1f, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4b, 0x65, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xb9, 0x01, 0x0a, 0x1b, 0x45, 0x64, 0x69, 0x74, 0x46, 0x69, - 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x12, 0x34, 0x0a, 0x0b, - 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x4d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2d, 0xda, 0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x4c, 0x65, - 0x67, 0x61, 0x63, 0x79, 0x44, 0x65, 0x63, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2e, 0x44, 0x65, 0x63, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x22, 0x0f, 0x0a, 0x0d, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2a, 0xa4, 0x01, 0x0a, 0x16, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1e, 0x0a, - 0x0a, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x45, 0x44, 0x10, 0x00, 0x1a, 0x0e, 0x8a, - 0x9d, 0x20, 0x0a, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x45, 0x44, 0x12, 0x16, 0x0a, - 0x06, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x01, 0x1a, 0x0a, 0x8a, 0x9d, 0x20, 0x06, 0x41, - 0x43, 0x54, 0x49, 0x56, 0x45, 0x12, 0x1a, 0x0a, 0x08, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, - 0x45, 0x10, 0x02, 0x1a, 0x0c, 0x8a, 0x9d, 0x20, 0x08, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, - 0x45, 0x12, 0x18, 0x0a, 0x07, 0x53, 0x4c, 0x41, 0x53, 0x48, 0x45, 0x44, 0x10, 0x03, 0x1a, 0x0b, - 0x8a, 0x9d, 0x20, 0x07, 0x53, 0x4c, 0x41, 0x53, 0x48, 0x45, 0x44, 0x12, 0x16, 0x0a, 0x06, 0x4a, - 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x04, 0x1a, 0x0a, 0x8a, 0x9d, 0x20, 0x06, 0x4a, 0x41, 0x49, - 0x4c, 0x45, 0x44, 0x1a, 0x04, 0x88, 0xa3, 0x1e, 0x00, 0x32, 0x8c, 0x06, 0x0a, 0x11, 0x46, 0x69, - 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, - 0x38, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x15, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, - 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x16, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x12, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, - 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x5f, 0x0a, 0x14, 0x41, 0x64, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x53, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x41, 0x64, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x64, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, - 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x65, 0x0a, 0x16, 0x55, 0x6e, 0x6a, 0x61, 0x69, 0x6c, 0x46, 0x69, 0x6e, 0x61, 0x6c, - 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x24, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x55, 0x6e, 0x6a, 0x61, 0x69, 0x6c, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, - 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x55, 0x6e, 0x6a, 0x61, 0x69, 0x6c, + 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x6c, + 0x61, 0x73, 0x74, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, + 0x64, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x22, 0xa2, + 0x01, 0x0a, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, + 0x0a, 0x07, 0x6d, 0x6f, 0x6e, 0x69, 0x6b, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x6d, 0x6f, 0x6e, 0x69, 0x6b, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x77, 0x65, 0x62, 0x73, 0x69, 0x74, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x77, 0x65, 0x62, 0x73, 0x69, 0x74, 0x65, 0x12, 0x29, + 0x0a, 0x10, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, + 0x74, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x74, + 0x61, 0x69, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, + 0x69, 0x6c, 0x73, 0x22, 0x2c, 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x4f, 0x66, 0x50, 0x6f, + 0x73, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x62, 0x74, 0x63, 0x5f, + 0x73, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x62, 0x74, 0x63, 0x53, 0x69, + 0x67, 0x22, 0x47, 0x0a, 0x0f, 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, 0x72, 0x52, 0x61, 0x6e, 0x64, + 0x50, 0x61, 0x69, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x75, 0x62, 0x5f, 0x72, 0x61, 0x6e, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x75, 0x62, 0x52, 0x61, 0x6e, 0x64, 0x12, + 0x19, 0x0a, 0x08, 0x73, 0x65, 0x63, 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x07, 0x73, 0x65, 0x63, 0x52, 0x61, 0x6e, 0x64, 0x22, 0x94, 0x01, 0x0a, 0x1e, 0x53, + 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, + 0x0b, 0x6d, 0x73, 0x67, 0x5f, 0x74, 0x6f, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x09, 0x6d, 0x73, 0x67, 0x54, 0x6f, 0x53, 0x69, 0x67, 0x6e, 0x12, 0x19, 0x0a, + 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x6b, 0x65, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x61, 0x73, 0x73, + 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, + 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x68, 0x64, 0x5f, 0x70, + 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x68, 0x64, 0x50, 0x61, 0x74, + 0x68, 0x22, 0x3f, 0x0a, 0x1f, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x22, 0xb9, 0x01, 0x0a, 0x1b, 0x45, 0x64, 0x69, 0x74, 0x46, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x12, 0x34, 0x0a, 0x0b, 0x64, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x4d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x2d, 0xda, 0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, + 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, + 0x79, 0x44, 0x65, 0x63, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x44, + 0x65, 0x63, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x0f, + 0x0a, 0x0d, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, + 0xa4, 0x01, 0x0a, 0x16, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x52, 0x45, + 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x45, 0x44, 0x10, 0x00, 0x1a, 0x0e, 0x8a, 0x9d, 0x20, 0x0a, + 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x45, 0x44, 0x12, 0x16, 0x0a, 0x06, 0x41, 0x43, + 0x54, 0x49, 0x56, 0x45, 0x10, 0x01, 0x1a, 0x0a, 0x8a, 0x9d, 0x20, 0x06, 0x41, 0x43, 0x54, 0x49, + 0x56, 0x45, 0x12, 0x1a, 0x0a, 0x08, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x02, + 0x1a, 0x0c, 0x8a, 0x9d, 0x20, 0x08, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x12, 0x18, + 0x0a, 0x07, 0x53, 0x4c, 0x41, 0x53, 0x48, 0x45, 0x44, 0x10, 0x03, 0x1a, 0x0b, 0x8a, 0x9d, 0x20, + 0x07, 0x53, 0x4c, 0x41, 0x53, 0x48, 0x45, 0x44, 0x12, 0x16, 0x0a, 0x06, 0x4a, 0x41, 0x49, 0x4c, + 0x45, 0x44, 0x10, 0x04, 0x1a, 0x0a, 0x8a, 0x9d, 0x20, 0x06, 0x4a, 0x41, 0x49, 0x4c, 0x45, 0x44, + 0x1a, 0x04, 0x88, 0xa3, 0x1e, 0x00, 0x32, 0x8c, 0x06, 0x0a, 0x11, 0x46, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x38, 0x0a, 0x07, + 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x15, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x72, 0x12, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, + 0x12, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, + 0x14, 0x41, 0x64, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x64, + 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x41, 0x64, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, + 0x0a, 0x16, 0x55, 0x6e, 0x6a, 0x61, 0x69, 0x6c, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, + 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x55, 0x6e, 0x6a, 0x61, 0x69, 0x6c, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x55, 0x6e, 0x6a, 0x61, 0x69, 0x6c, 0x46, 0x69, 0x6e, + 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x15, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, + 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x23, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, + 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x19, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x27, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, - 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x19, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x27, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, - 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x17, - 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x4b, 0x65, 0x79, 0x12, 0x25, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4b, 0x65, 0x79, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x14, 0x45, 0x64, 0x69, 0x74, 0x46, 0x69, - 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x22, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x46, 0x69, 0x6e, 0x61, 0x6c, - 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x45, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x6c, 0x61, - 0x62, 0x73, 0x2d, 0x69, 0x6f, 0x2f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x2d, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, - 0x2d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x69, 0x64, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x28, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, + 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4c, 0x69, 0x73, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x17, 0x53, 0x69, 0x67, + 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4b, 0x65, 0x79, 0x12, 0x25, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x46, + 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x14, 0x45, 0x64, 0x69, 0x74, 0x46, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x22, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, + 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x45, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x6c, 0x61, 0x62, 0x73, 0x2d, + 0x69, 0x6f, 0x2f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x2d, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x2f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x2d, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/finality-provider/proto/finality_providers.proto b/finality-provider/proto/finality_providers.proto index 3ec97fe4..10c617a5 100644 --- a/finality-provider/proto/finality_providers.proto +++ b/finality-provider/proto/finality_providers.proto @@ -81,6 +81,8 @@ message AddFinalitySignatureRequest { uint64 height = 2; // app_hash is the AppHash of the chain block bytes app_hash = 3; + // check_double_sign use double sign protection when doing EOTS sign + bool check_double_sign = 4; } message AddFinalitySignatureResponse { diff --git a/finality-provider/service/app.go b/finality-provider/service/app.go index d2ac1932..9105794e 100644 --- a/finality-provider/service/app.go +++ b/finality-provider/service/app.go @@ -49,6 +49,7 @@ type FinalityProviderApp struct { metrics *metrics.FpMetrics createFinalityProviderRequestChan chan *CreateFinalityProviderRequest + unjailFinalityProviderRequestChan chan *UnjailFinalityProviderRequest criticalErrChan chan *CriticalError } @@ -114,6 +115,7 @@ func NewFinalityProviderApp( eotsManager: em, metrics: fpMetrics, quit: make(chan struct{}), + unjailFinalityProviderRequestChan: make(chan *UnjailFinalityProviderRequest), createFinalityProviderRequestChan: make(chan *CreateFinalityProviderRequest), criticalErrChan: make(chan *CriticalError), }, nil @@ -251,12 +253,13 @@ func (app *FinalityProviderApp) Start() error { app.startOnce.Do(func() { app.logger.Info("Starting FinalityProviderApp") - app.wg.Add(5) + app.wg.Add(6) go app.syncChainFpStatusLoop() - go app.registrationLoop() go app.metricsUpdateLoop() go app.monitorCriticalErr() go app.monitorStatusUpdate() + go app.registrationLoop() + go app.unjailFpLoop() }) return startErr @@ -374,34 +377,39 @@ func (app *FinalityProviderApp) CreateFinalityProvider( } // UnjailFinalityProvider sends a transaction to unjail a finality-provider -func (app *FinalityProviderApp) UnjailFinalityProvider(fpPk *bbntypes.BIP340PubKey) (string, error) { - _, err := app.fps.GetFinalityProvider(fpPk.MustToBTCPK()) - if err != nil { - return "", fmt.Errorf("failed to get finality provider from db: %w", err) +func (app *FinalityProviderApp) UnjailFinalityProvider(fpPk *bbntypes.BIP340PubKey) (*UnjailFinalityProviderResponse, error) { + // send request to the loop to avoid blocking the main thread + request := &UnjailFinalityProviderRequest{ + btcPubKey: fpPk, + errResponse: make(chan error, 1), + successResponse: make(chan *UnjailFinalityProviderResponse, 1), } - // Send unjail transaction - res, err := app.cc.UnjailFinalityProvider(fpPk.MustToBTCPK()) - if err != nil { - return "", fmt.Errorf("failed to send unjail transaction: %w", err) - } + app.unjailFinalityProviderRequestChan <- request - // Update finality-provider status in the local store - // set it to INACTIVE for now and it will be updated to - // ACTIVE if the fp has voting power - err = app.fps.SetFpStatus(fpPk.MustToBTCPK(), proto.FinalityProviderStatus_INACTIVE) - if err != nil { - return "", fmt.Errorf("failed to update finality-provider status after unjailing: %w", err) - } + select { + case err := <-request.errResponse: + return nil, err + case successResponse := <-request.successResponse: + _, err := app.fps.GetFinalityProvider(fpPk.MustToBTCPK()) + if err != nil { + return nil, fmt.Errorf("failed to get finality provider from db: %w", err) + } - app.metrics.RecordFpStatus(fpPk.MarshalHex(), proto.FinalityProviderStatus_INACTIVE) + // Update finality-provider status in the local store + // set it to INACTIVE for now and it will be updated to + // ACTIVE if the fp has voting power + err = app.fps.SetFpStatus(fpPk.MustToBTCPK(), proto.FinalityProviderStatus_INACTIVE) + if err != nil { + return nil, fmt.Errorf("failed to update finality-provider status after unjailing: %w", err) + } - app.logger.Info("successfully unjailed finality-provider", - zap.String("btc_pk", fpPk.MarshalHex()), - zap.String("txHash", res.TxHash), - ) + app.metrics.RecordFpStatus(fpPk.MarshalHex(), proto.FinalityProviderStatus_INACTIVE) - return res.TxHash, nil + return successResponse, nil + case <-app.quit: + return nil, fmt.Errorf("finality-provider app is shutting down") + } } func (app *FinalityProviderApp) CreatePop(fpAddress sdk.AccAddress, fpPk *bbntypes.BIP340PubKey, passphrase string) (*bstypes.ProofOfPossessionBTC, error) { diff --git a/finality-provider/service/app_test.go b/finality-provider/service/app_test.go index f45d910f..78ab04eb 100644 --- a/finality-provider/service/app_test.go +++ b/finality-provider/service/app_test.go @@ -214,7 +214,7 @@ func FuzzUnjailFinalityProvider(f *testing.F) { // set voting power to be positive so that the fp should eventually become ACTIVE mockClientController.EXPECT().QueryFinalityProviderVotingPower(gomock.Any(), gomock.Any()).Return(uint64(0), nil).AnyTimes() mockClientController.EXPECT().QueryActivatedHeight().Return(uint64(1), nil).AnyTimes() - mockClientController.EXPECT().QueryFinalityProviderSlashedOrJailed(gomock.Any()).Return(false, false, nil).AnyTimes() + mockClientController.EXPECT().QueryFinalityProviderSlashedOrJailed(gomock.Any()).Return(false, true, nil).AnyTimes() mockClientController.EXPECT().QueryFinalityProviderHighestVotedHeight(gomock.Any()).Return(uint64(0), nil).AnyTimes() // Create fp app @@ -223,9 +223,9 @@ func FuzzUnjailFinalityProvider(f *testing.F) { expectedTxHash := datagen.GenRandomHexStr(r, 32) mockClientController.EXPECT().UnjailFinalityProvider(fpPk.MustToBTCPK()).Return(&types.TxResponse{TxHash: expectedTxHash}, nil) - txHash, err := app.UnjailFinalityProvider(fpPk) + res, err := app.UnjailFinalityProvider(fpPk) require.NoError(t, err) - require.Equal(t, expectedTxHash, txHash) + require.Equal(t, expectedTxHash, res.TxHash) fpInfo, err := app.GetFinalityProviderInfo(fpPk) require.NoError(t, err) require.Equal(t, proto.FinalityProviderStatus_INACTIVE.String(), fpInfo.GetStatus()) diff --git a/finality-provider/service/client/rpcclient.go b/finality-provider/service/client/rpcclient.go index 894f5923..b40bc3fa 100644 --- a/finality-provider/service/client/rpcclient.go +++ b/finality-provider/service/client/rpcclient.go @@ -74,11 +74,18 @@ func (c *FinalityProviderServiceGRpcClient) CreateFinalityProvider( return res, nil } -func (c *FinalityProviderServiceGRpcClient) AddFinalitySignature(ctx context.Context, fpPk string, height uint64, appHash []byte) (*proto.AddFinalitySignatureResponse, error) { +func (c *FinalityProviderServiceGRpcClient) AddFinalitySignature( + ctx context.Context, + fpPk string, + height uint64, + appHash []byte, + checkDoubleSign bool, +) (*proto.AddFinalitySignatureResponse, error) { req := &proto.AddFinalitySignatureRequest{ - BtcPk: fpPk, - Height: height, - AppHash: appHash, + BtcPk: fpPk, + Height: height, + AppHash: appHash, + CheckDoubleSign: checkDoubleSign, } res, err := c.client.AddFinalitySignature(ctx, req) diff --git a/finality-provider/service/event_loops.go b/finality-provider/service/event_loops.go index abf5c7bc..b0ce8204 100644 --- a/finality-provider/service/event_loops.go +++ b/finality-provider/service/event_loops.go @@ -2,13 +2,48 @@ package service import ( "errors" + "fmt" "time" + sdkmath "cosmossdk.io/math" + bbntypes "github.com/babylonlabs-io/babylon/types" + btcstakingtypes "github.com/babylonlabs-io/babylon/x/btcstaking/types" + sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "go.uber.org/zap" "github.com/babylonlabs-io/finality-provider/finality-provider/proto" ) +type CreateFinalityProviderRequest struct { + fpAddr sdk.AccAddress + btcPubKey *bbntypes.BIP340PubKey + pop *btcstakingtypes.ProofOfPossessionBTC + description *stakingtypes.Description + commission *sdkmath.LegacyDec + errResponse chan error + successResponse chan *RegisterFinalityProviderResponse +} + +type RegisterFinalityProviderResponse struct { + txHash string +} + +type CreateFinalityProviderResult struct { + FpInfo *proto.FinalityProviderInfo + TxHash string +} + +type UnjailFinalityProviderRequest struct { + btcPubKey *bbntypes.BIP340PubKey + errResponse chan error + successResponse chan *UnjailFinalityProviderResponse +} + +type UnjailFinalityProviderResponse struct { + TxHash string +} + // monitorStatusUpdate periodically check the status of the running finality provider and update // it accordingly. We update the status by querying the latest voting power and the slashed_height. // In particular, we perform the following status transitions (REGISTERED, ACTIVE, INACTIVE, SLASHED): @@ -201,6 +236,57 @@ func (app *FinalityProviderApp) registrationLoop() { } } +// event loop for unjailing fp +func (app *FinalityProviderApp) unjailFpLoop() { + defer app.wg.Done() + for { + select { + case req := <-app.unjailFinalityProviderRequestChan: + pkHex := req.btcPubKey.MarshalHex() + isSlashed, isJailed, err := app.cc.QueryFinalityProviderSlashedOrJailed(req.btcPubKey.MustToBTCPK()) + if err != nil { + req.errResponse <- fmt.Errorf("failed to query jailing status of the finality provider %s: %w", pkHex, err) + continue + } + if isSlashed { + req.errResponse <- fmt.Errorf("the finality provider %s is already slashed", pkHex) + continue + } + if !isJailed { + req.errResponse <- fmt.Errorf("the finality provider %s is not jailed", pkHex) + continue + } + + res, err := app.cc.UnjailFinalityProvider( + req.btcPubKey.MustToBTCPK(), + ) + + if err != nil { + app.logger.Error( + "failed to unjail finality-provider", + zap.String("pk", req.btcPubKey.MarshalHex()), + zap.Error(err), + ) + req.errResponse <- err + continue + } + + app.logger.Info( + "successfully unjailed finality-provider on babylon", + zap.String("btc_pk", req.btcPubKey.MarshalHex()), + zap.String("txHash", res.TxHash), + ) + + req.successResponse <- &UnjailFinalityProviderResponse{ + TxHash: res.TxHash, + } + case <-app.quit: + app.logger.Info("exiting unjailing fp loop") + return + } + } +} + // event loop for metrics update func (app *FinalityProviderApp) metricsUpdateLoop() { defer app.wg.Done() diff --git a/finality-provider/service/fp_instance.go b/finality-provider/service/fp_instance.go index 6b7883ca..1c688f4a 100644 --- a/finality-provider/service/fp_instance.go +++ b/finality-provider/service/fp_instance.go @@ -152,7 +152,7 @@ func (fp *FinalityProviderInstance) Stop() error { close(fp.quit) fp.wg.Wait() - fp.logger.Info("the finality-provider instance %s is successfully stopped", zap.String("pk", fp.GetBtcPkHex())) + fp.logger.Info("the finality-provider instance is successfully stopped", zap.String("pk", fp.GetBtcPkHex())) return nil } @@ -681,7 +681,9 @@ func (fp *FinalityProviderInstance) SubmitBatchFinalitySignatures(blocks []*type // TestSubmitFinalitySignatureAndExtractPrivKey is exposed for presentation/testing purpose to allow manual sending finality signature // this API is the same as SubmitBatchFinalitySignatures except that we don't constraint the voting height and update status // Note: this should not be used in the submission loop -func (fp *FinalityProviderInstance) TestSubmitFinalitySignatureAndExtractPrivKey(b *types.BlockInfo) (*types.TxResponse, *btcec.PrivateKey, error) { +func (fp *FinalityProviderInstance) TestSubmitFinalitySignatureAndExtractPrivKey( + b *types.BlockInfo, useSafeEOTSFunc bool, +) (*types.TxResponse, *btcec.PrivateKey, error) { // get public randomness prList, err := fp.getPubRandList(b.Height, 1) if err != nil { @@ -695,8 +697,22 @@ func (fp *FinalityProviderInstance) TestSubmitFinalitySignatureAndExtractPrivKey return nil, nil, fmt.Errorf("failed to get public randomness inclusion proof: %w", err) } + eotsSignerFunc := func(b *types.BlockInfo) (*bbntypes.SchnorrEOTSSig, error) { + msgToSign := getMsgToSignForVote(b.Height, b.Hash) + sig, err := fp.em.UnsafeSignEOTS(fp.btcPk.MustMarshal(), fp.GetChainID(), msgToSign, b.Height, fp.passphrase) + if err != nil { + return nil, fmt.Errorf("failed to sign EOTS: %w", err) + } + + return bbntypes.NewSchnorrEOTSSigFromModNScalar(sig), nil + } + + if useSafeEOTSFunc { + eotsSignerFunc = fp.signFinalitySig + } + // sign block - eotsSig, err := fp.signFinalitySig(b) + eotsSig, err := eotsSignerFunc(b) if err != nil { return nil, nil, err } diff --git a/finality-provider/service/fp_store_adapter.go b/finality-provider/service/fp_store_adapter.go index 18290af3..da1c0190 100644 --- a/finality-provider/service/fp_store_adapter.go +++ b/finality-provider/service/fp_store_adapter.go @@ -3,37 +3,14 @@ package service import ( "sync" - sdkmath "cosmossdk.io/math" bbntypes "github.com/babylonlabs-io/babylon/types" - btcstakingtypes "github.com/babylonlabs-io/babylon/x/btcstaking/types" "github.com/btcsuite/btcd/btcec/v2" - sdk "github.com/cosmos/cosmos-sdk/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "go.uber.org/zap" "github.com/babylonlabs-io/finality-provider/finality-provider/proto" "github.com/babylonlabs-io/finality-provider/finality-provider/store" ) -type CreateFinalityProviderRequest struct { - fpAddr sdk.AccAddress - btcPubKey *bbntypes.BIP340PubKey - pop *btcstakingtypes.ProofOfPossessionBTC - description *stakingtypes.Description - commission *sdkmath.LegacyDec - errResponse chan error - successResponse chan *RegisterFinalityProviderResponse -} - -type RegisterFinalityProviderResponse struct { - txHash string -} - -type CreateFinalityProviderResult struct { - FpInfo *proto.FinalityProviderInfo - TxHash string -} - type fpState struct { mu sync.Mutex fp *store.StoredFinalityProvider diff --git a/finality-provider/service/rpcserver.go b/finality-provider/service/rpcserver.go index 0269c138..e86544af 100644 --- a/finality-provider/service/rpcserver.go +++ b/finality-provider/service/rpcserver.go @@ -156,7 +156,7 @@ func (r *rpcServer) AddFinalitySignature(_ context.Context, req *proto.AddFinali Hash: req.AppHash, } - txRes, privKey, err := fpi.TestSubmitFinalitySignatureAndExtractPrivKey(b) + txRes, privKey, err := fpi.TestSubmitFinalitySignatureAndExtractPrivKey(b, req.CheckDoubleSign) if err != nil { return nil, err } @@ -201,7 +201,7 @@ func (r *rpcServer) UnjailFinalityProvider(_ context.Context, req *proto.UnjailF return nil, err } - txHash, err := r.app.UnjailFinalityProvider(fpPk) + res, err := r.app.UnjailFinalityProvider(fpPk) if err != nil { return nil, fmt.Errorf("failed to unjail the finality-provider: %w", err) } @@ -211,7 +211,7 @@ func (r *rpcServer) UnjailFinalityProvider(_ context.Context, req *proto.UnjailF return nil, fmt.Errorf("failed to start the finality provider instance after unjailing: %w", err) } - return &proto.UnjailFinalityProviderResponse{TxHash: txHash}, nil + return &proto.UnjailFinalityProviderResponse{TxHash: res.TxHash}, nil } // QueryFinalityProvider queries the information of the finality-provider diff --git a/itest/e2e_test.go b/itest/e2e_test.go index 364dff18..e35e1b8a 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -1,6 +1,3 @@ -//go:build e2e -// +build e2e - package e2etest import ( @@ -85,7 +82,7 @@ func TestDoubleSigning(t *testing.T) { finalizedBlocks := tm.WaitForNFinalizedBlocks(t, 1) // test duplicate vote which should be ignored - res, extractedKey, err := fpIns.TestSubmitFinalitySignatureAndExtractPrivKey(finalizedBlocks[0]) + res, extractedKey, err := fpIns.TestSubmitFinalitySignatureAndExtractPrivKey(finalizedBlocks[0], false) require.NoError(t, err) require.Nil(t, extractedKey) require.Empty(t, res) @@ -98,14 +95,17 @@ func TestDoubleSigning(t *testing.T) { Height: finalizedBlocks[0].Height, Hash: datagen.GenRandomByteArray(r, 32), } - _, _, err = fpIns.TestSubmitFinalitySignatureAndExtractPrivKey(b) + + // confirm we have double sign protection + _, _, err = fpIns.TestSubmitFinalitySignatureAndExtractPrivKey(b, true) require.Error(t, err) + require.Contains(t, err.Error(), "double sign") - // todo(lazar): implement UnsafeSignEOTS, containing logic without double sign protection - //require.NoError(t, err) - //require.NotNil(t, extractedKey) - //localKey := tm.GetFpPrivKey(t, fpIns.GetBtcPkBIP340().MustMarshal()) - //require.True(t, localKey.Key.Equals(&extractedKey.Key) || localKey.Key.Negate().Equals(&extractedKey.Key)) + _, extractedKey, err = fpIns.TestSubmitFinalitySignatureAndExtractPrivKey(b, false) + require.NoError(t, err) + require.NotNil(t, extractedKey) + localKey := tm.GetFpPrivKey(t, fpIns.GetBtcPkBIP340().MustMarshal()) + require.True(t, localKey.Key.Equals(&extractedKey.Key) || localKey.Key.Negate().Equals(&extractedKey.Key)) t.Logf("the equivocation attack is successful") }