From 0902dbd3a9abad004d75204d7d657d9204e28157 Mon Sep 17 00:00:00 2001 From: louisinger Date: Wed, 15 Jan 2025 14:37:22 +0100 Subject: [PATCH 01/21] client and application update --- .../swagger/ark/v1/service.swagger.json | 17 +- api-spec/protobuf/ark/v1/service.proto | 8 +- api-spec/protobuf/gen/ark/v1/admin.pb.gw.go | 286 ++---- api-spec/protobuf/gen/ark/v1/service.pb.go | 894 +++++++++--------- api-spec/protobuf/gen/ark/v1/service.pb.gw.go | 740 +++++---------- api-spec/protobuf/gen/ark/v1/wallet.pb.gw.go | 352 +++---- common/bitcointree/builder.go | 240 ++--- common/bitcointree/musig2.go | 662 ++++++++----- common/bitcointree/musig2_test.go | 185 ++-- common/tree/type.go | 15 +- pkg/client-sdk/ark_sdk.go | 7 +- pkg/client-sdk/client/client.go | 11 +- pkg/client-sdk/client/grpc/client.go | 14 +- pkg/client-sdk/client/grpc/types.go | 21 +- pkg/client-sdk/client/rest/client.go | 37 +- ..._register_inputs_for_next_round_request.go | 9 +- .../service/models/v1_round_signing_event.go | 3 - pkg/client-sdk/covenant_client.go | 8 +- pkg/client-sdk/covenantless_client.go | 201 +++- server/internal/core/application/covenant.go | 16 +- .../internal/core/application/covenantless.go | 138 ++- .../core/application/covenantless_event.go | 2 - server/internal/core/application/types.go | 5 +- server/internal/core/application/utils.go | 49 +- server/internal/core/domain/payment.go | 23 +- server/internal/core/ports/tx_builder.go | 1 - .../tx-builder/covenant/builder.go | 1 - .../tx-builder/covenantless/builder.go | 29 +- .../tx-builder/covenantless/builder_test.go | 16 +- .../tx-builder/covenantless/utils.go | 6 +- .../interface/grpc/handlers/arkservice.go | 18 +- 31 files changed, 1899 insertions(+), 2115 deletions(-) diff --git a/api-spec/openapi/swagger/ark/v1/service.swagger.json b/api-spec/openapi/swagger/ark/v1/service.swagger.json index 24d4dcb88..b726e9ae7 100644 --- a/api-spec/openapi/swagger/ark/v1/service.swagger.json +++ b/api-spec/openapi/swagger/ark/v1/service.swagger.json @@ -808,14 +808,21 @@ "$ref": "#/definitions/v1Input" } }, - "ephemeralPubkey": { - "type": "string" + "signerPubkeys": { + "type": "array", + "items": { + "type": "string" + } }, "notes": { "type": "array", "items": { "type": "string" } + }, + "signingType": { + "type": "integer", + "format": "int64" } } }, @@ -935,12 +942,6 @@ "id": { "type": "string" }, - "cosignersPubkeys": { - "type": "array", - "items": { - "type": "string" - } - }, "unsignedVtxoTree": { "$ref": "#/definitions/v1Tree" }, diff --git a/api-spec/protobuf/ark/v1/service.proto b/api-spec/protobuf/ark/v1/service.proto index bc200b7ad..be06dc5ec 100755 --- a/api-spec/protobuf/ark/v1/service.proto +++ b/api-spec/protobuf/ark/v1/service.proto @@ -140,8 +140,9 @@ message GetBoardingAddressResponse { message RegisterInputsForNextRoundRequest { repeated Input inputs = 1; - optional string ephemeral_pubkey = 2; + repeated string signer_pubkeys = 2; repeated string notes = 3; + uint32 signing_type = 4; } message RegisterInputsForNextRoundResponse { string request_id = 1; @@ -246,9 +247,8 @@ message RoundFailed { message RoundSigningEvent { string id = 1; - repeated string cosigners_pubkeys = 2; - Tree unsigned_vtxo_tree = 3; - string unsigned_round_tx = 4; + Tree unsigned_vtxo_tree = 2; + string unsigned_round_tx = 3; } message RoundSigningNoncesGeneratedEvent { diff --git a/api-spec/protobuf/gen/ark/v1/admin.pb.gw.go b/api-spec/protobuf/gen/ark/v1/admin.pb.gw.go index 15b7c03fc..d3e1ba786 100644 --- a/api-spec/protobuf/gen/ark/v1/admin.pb.gw.go +++ b/api-spec/protobuf/gen/ark/v1/admin.pb.gw.go @@ -10,6 +10,7 @@ package arkv1 import ( "context" + "errors" "io" "net/http" @@ -24,177 +25,158 @@ import ( ) // Suppress "imported and not used" errors -var _ codes.Code -var _ io.Reader -var _ status.Status -var _ = runtime.String -var _ = utilities.NewDoubleArray -var _ = metadata.Join +var ( + _ codes.Code + _ io.Reader + _ status.Status + _ = errors.New + _ = runtime.String + _ = utilities.NewDoubleArray + _ = metadata.Join +) func request_AdminService_GetScheduledSweep_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetScheduledSweepRequest - var metadata runtime.ServerMetadata - + var ( + protoReq GetScheduledSweepRequest + metadata runtime.ServerMetadata + ) msg, err := client.GetScheduledSweep(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_AdminService_GetScheduledSweep_0(ctx context.Context, marshaler runtime.Marshaler, server AdminServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetScheduledSweepRequest - var metadata runtime.ServerMetadata - + var ( + protoReq GetScheduledSweepRequest + metadata runtime.ServerMetadata + ) msg, err := server.GetScheduledSweep(ctx, &protoReq) return msg, metadata, err - } func request_AdminService_GetRoundDetails_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetRoundDetailsRequest - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq GetRoundDetailsRequest + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["round_id"] + val, ok := pathParams["round_id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "round_id") } - protoReq.RoundId, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "round_id", err) } - msg, err := client.GetRoundDetails(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_AdminService_GetRoundDetails_0(ctx context.Context, marshaler runtime.Marshaler, server AdminServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetRoundDetailsRequest - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq GetRoundDetailsRequest + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["round_id"] + val, ok := pathParams["round_id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "round_id") } - protoReq.RoundId, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "round_id", err) } - msg, err := server.GetRoundDetails(ctx, &protoReq) return msg, metadata, err - } func request_AdminService_GetRounds_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetRoundsRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq GetRoundsRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.GetRounds(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_AdminService_GetRounds_0(ctx context.Context, marshaler runtime.Marshaler, server AdminServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetRoundsRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq GetRoundsRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.GetRounds(ctx, &protoReq) return msg, metadata, err - } func request_AdminService_CreateNote_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq CreateNoteRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq CreateNoteRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.CreateNote(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_AdminService_CreateNote_0(ctx context.Context, marshaler runtime.Marshaler, server AdminServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq CreateNoteRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq CreateNoteRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.CreateNote(ctx, &protoReq) return msg, metadata, err - } func request_AdminService_GetMarketHourConfig_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetMarketHourConfigRequest - var metadata runtime.ServerMetadata - + var ( + protoReq GetMarketHourConfigRequest + metadata runtime.ServerMetadata + ) msg, err := client.GetMarketHourConfig(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_AdminService_GetMarketHourConfig_0(ctx context.Context, marshaler runtime.Marshaler, server AdminServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetMarketHourConfigRequest - var metadata runtime.ServerMetadata - + var ( + protoReq GetMarketHourConfigRequest + metadata runtime.ServerMetadata + ) msg, err := server.GetMarketHourConfig(ctx, &protoReq) return msg, metadata, err - } func request_AdminService_UpdateMarketHourConfig_0(ctx context.Context, marshaler runtime.Marshaler, client AdminServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq UpdateMarketHourConfigRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq UpdateMarketHourConfigRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.UpdateMarketHourConfig(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_AdminService_UpdateMarketHourConfig_0(ctx context.Context, marshaler runtime.Marshaler, server AdminServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq UpdateMarketHourConfigRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq UpdateMarketHourConfigRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.UpdateMarketHourConfig(ctx, &protoReq) return msg, metadata, err - } // RegisterAdminServiceHandlerServer registers the http handlers for service AdminService to "mux". @@ -203,16 +185,13 @@ func local_request_AdminService_UpdateMarketHourConfig_0(ctx context.Context, ma // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterAdminServiceHandlerFromEndpoint instead. // GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. func RegisterAdminServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server AdminServiceServer) error { - - mux.Handle("GET", pattern_AdminService_GetScheduledSweep_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_AdminService_GetScheduledSweep_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.AdminService/GetScheduledSweep", runtime.WithHTTPPathPattern("/v1/admin/sweeps")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.AdminService/GetScheduledSweep", runtime.WithHTTPPathPattern("/v1/admin/sweeps")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -224,20 +203,15 @@ func RegisterAdminServiceHandlerServer(ctx context.Context, mux *runtime.ServeMu runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_AdminService_GetScheduledSweep_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_AdminService_GetRoundDetails_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_AdminService_GetRoundDetails_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.AdminService/GetRoundDetails", runtime.WithHTTPPathPattern("/v1/admin/round/{round_id}")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.AdminService/GetRoundDetails", runtime.WithHTTPPathPattern("/v1/admin/round/{round_id}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -249,20 +223,15 @@ func RegisterAdminServiceHandlerServer(ctx context.Context, mux *runtime.ServeMu runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_AdminService_GetRoundDetails_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_AdminService_GetRounds_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_AdminService_GetRounds_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.AdminService/GetRounds", runtime.WithHTTPPathPattern("/v1/admin/rounds")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.AdminService/GetRounds", runtime.WithHTTPPathPattern("/v1/admin/rounds")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -274,20 +243,15 @@ func RegisterAdminServiceHandlerServer(ctx context.Context, mux *runtime.ServeMu runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_AdminService_GetRounds_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_AdminService_CreateNote_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_AdminService_CreateNote_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.AdminService/CreateNote", runtime.WithHTTPPathPattern("/v1/admin/note")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.AdminService/CreateNote", runtime.WithHTTPPathPattern("/v1/admin/note")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -299,20 +263,15 @@ func RegisterAdminServiceHandlerServer(ctx context.Context, mux *runtime.ServeMu runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_AdminService_CreateNote_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_AdminService_GetMarketHourConfig_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_AdminService_GetMarketHourConfig_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.AdminService/GetMarketHourConfig", runtime.WithHTTPPathPattern("/v1/admin/market-hour")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.AdminService/GetMarketHourConfig", runtime.WithHTTPPathPattern("/v1/admin/market-hour")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -324,20 +283,15 @@ func RegisterAdminServiceHandlerServer(ctx context.Context, mux *runtime.ServeMu runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_AdminService_GetMarketHourConfig_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_AdminService_UpdateMarketHourConfig_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_AdminService_UpdateMarketHourConfig_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.AdminService/UpdateMarketHourConfig", runtime.WithHTTPPathPattern("/v1/admin/market-hour")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.AdminService/UpdateMarketHourConfig", runtime.WithHTTPPathPattern("/v1/admin/market-hour")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -349,9 +303,7 @@ func RegisterAdminServiceHandlerServer(ctx context.Context, mux *runtime.ServeMu runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_AdminService_UpdateMarketHourConfig_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) return nil @@ -378,7 +330,6 @@ func RegisterAdminServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.S } }() }() - return RegisterAdminServiceHandler(ctx, mux, conn) } @@ -394,14 +345,11 @@ func RegisterAdminServiceHandler(ctx context.Context, mux *runtime.ServeMux, con // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in // "AdminServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares. func RegisterAdminServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client AdminServiceClient) error { - - mux.Handle("GET", pattern_AdminService_GetScheduledSweep_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_AdminService_GetScheduledSweep_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.AdminService/GetScheduledSweep", runtime.WithHTTPPathPattern("/v1/admin/sweeps")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.AdminService/GetScheduledSweep", runtime.WithHTTPPathPattern("/v1/admin/sweeps")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -412,18 +360,13 @@ func RegisterAdminServiceHandlerClient(ctx context.Context, mux *runtime.ServeMu runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_AdminService_GetScheduledSweep_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_AdminService_GetRoundDetails_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_AdminService_GetRoundDetails_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.AdminService/GetRoundDetails", runtime.WithHTTPPathPattern("/v1/admin/round/{round_id}")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.AdminService/GetRoundDetails", runtime.WithHTTPPathPattern("/v1/admin/round/{round_id}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -434,18 +377,13 @@ func RegisterAdminServiceHandlerClient(ctx context.Context, mux *runtime.ServeMu runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_AdminService_GetRoundDetails_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_AdminService_GetRounds_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_AdminService_GetRounds_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.AdminService/GetRounds", runtime.WithHTTPPathPattern("/v1/admin/rounds")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.AdminService/GetRounds", runtime.WithHTTPPathPattern("/v1/admin/rounds")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -456,18 +394,13 @@ func RegisterAdminServiceHandlerClient(ctx context.Context, mux *runtime.ServeMu runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_AdminService_GetRounds_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_AdminService_CreateNote_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_AdminService_CreateNote_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.AdminService/CreateNote", runtime.WithHTTPPathPattern("/v1/admin/note")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.AdminService/CreateNote", runtime.WithHTTPPathPattern("/v1/admin/note")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -478,18 +411,13 @@ func RegisterAdminServiceHandlerClient(ctx context.Context, mux *runtime.ServeMu runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_AdminService_CreateNote_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_AdminService_GetMarketHourConfig_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_AdminService_GetMarketHourConfig_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.AdminService/GetMarketHourConfig", runtime.WithHTTPPathPattern("/v1/admin/market-hour")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.AdminService/GetMarketHourConfig", runtime.WithHTTPPathPattern("/v1/admin/market-hour")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -500,18 +428,13 @@ func RegisterAdminServiceHandlerClient(ctx context.Context, mux *runtime.ServeMu runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_AdminService_GetMarketHourConfig_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_AdminService_UpdateMarketHourConfig_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_AdminService_UpdateMarketHourConfig_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.AdminService/UpdateMarketHourConfig", runtime.WithHTTPPathPattern("/v1/admin/market-hour")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.AdminService/UpdateMarketHourConfig", runtime.WithHTTPPathPattern("/v1/admin/market-hour")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -522,38 +445,25 @@ func RegisterAdminServiceHandlerClient(ctx context.Context, mux *runtime.ServeMu runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_AdminService_UpdateMarketHourConfig_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - return nil } var ( - pattern_AdminService_GetScheduledSweep_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "admin", "sweeps"}, "")) - - pattern_AdminService_GetRoundDetails_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "admin", "round", "round_id"}, "")) - - pattern_AdminService_GetRounds_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "admin", "rounds"}, "")) - - pattern_AdminService_CreateNote_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "admin", "note"}, "")) - - pattern_AdminService_GetMarketHourConfig_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "admin", "market-hour"}, "")) - + pattern_AdminService_GetScheduledSweep_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "admin", "sweeps"}, "")) + pattern_AdminService_GetRoundDetails_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "admin", "round", "round_id"}, "")) + pattern_AdminService_GetRounds_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "admin", "rounds"}, "")) + pattern_AdminService_CreateNote_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "admin", "note"}, "")) + pattern_AdminService_GetMarketHourConfig_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "admin", "market-hour"}, "")) pattern_AdminService_UpdateMarketHourConfig_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "admin", "market-hour"}, "")) ) var ( - forward_AdminService_GetScheduledSweep_0 = runtime.ForwardResponseMessage - - forward_AdminService_GetRoundDetails_0 = runtime.ForwardResponseMessage - - forward_AdminService_GetRounds_0 = runtime.ForwardResponseMessage - - forward_AdminService_CreateNote_0 = runtime.ForwardResponseMessage - - forward_AdminService_GetMarketHourConfig_0 = runtime.ForwardResponseMessage - + forward_AdminService_GetScheduledSweep_0 = runtime.ForwardResponseMessage + forward_AdminService_GetRoundDetails_0 = runtime.ForwardResponseMessage + forward_AdminService_GetRounds_0 = runtime.ForwardResponseMessage + forward_AdminService_CreateNote_0 = runtime.ForwardResponseMessage + forward_AdminService_GetMarketHourConfig_0 = runtime.ForwardResponseMessage forward_AdminService_UpdateMarketHourConfig_0 = runtime.ForwardResponseMessage ) diff --git a/api-spec/protobuf/gen/ark/v1/service.pb.go b/api-spec/protobuf/gen/ark/v1/service.pb.go index 941ee403f..3c552abbb 100644 --- a/api-spec/protobuf/gen/ark/v1/service.pb.go +++ b/api-spec/protobuf/gen/ark/v1/service.pb.go @@ -376,9 +376,10 @@ type RegisterInputsForNextRoundRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Inputs []*Input `protobuf:"bytes,1,rep,name=inputs,proto3" json:"inputs,omitempty"` - EphemeralPubkey *string `protobuf:"bytes,2,opt,name=ephemeral_pubkey,json=ephemeralPubkey,proto3,oneof" json:"ephemeral_pubkey,omitempty"` - Notes []string `protobuf:"bytes,3,rep,name=notes,proto3" json:"notes,omitempty"` + Inputs []*Input `protobuf:"bytes,1,rep,name=inputs,proto3" json:"inputs,omitempty"` + SignerPubkeys []string `protobuf:"bytes,2,rep,name=signer_pubkeys,json=signerPubkeys,proto3" json:"signer_pubkeys,omitempty"` + Notes []string `protobuf:"bytes,3,rep,name=notes,proto3" json:"notes,omitempty"` + SigningType uint32 `protobuf:"varint,4,opt,name=signing_type,json=signingType,proto3" json:"signing_type,omitempty"` } func (x *RegisterInputsForNextRoundRequest) Reset() { @@ -420,11 +421,11 @@ func (x *RegisterInputsForNextRoundRequest) GetInputs() []*Input { return nil } -func (x *RegisterInputsForNextRoundRequest) GetEphemeralPubkey() string { - if x != nil && x.EphemeralPubkey != nil { - return *x.EphemeralPubkey +func (x *RegisterInputsForNextRoundRequest) GetSignerPubkeys() []string { + if x != nil { + return x.SignerPubkeys } - return "" + return nil } func (x *RegisterInputsForNextRoundRequest) GetNotes() []string { @@ -434,6 +435,13 @@ func (x *RegisterInputsForNextRoundRequest) GetNotes() []string { return nil } +func (x *RegisterInputsForNextRoundRequest) GetSigningType() uint32 { + if x != nil { + return x.SigningType + } + return 0 +} + type RegisterInputsForNextRoundResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1697,10 +1705,9 @@ type RoundSigningEvent struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - CosignersPubkeys []string `protobuf:"bytes,2,rep,name=cosigners_pubkeys,json=cosignersPubkeys,proto3" json:"cosigners_pubkeys,omitempty"` - UnsignedVtxoTree *Tree `protobuf:"bytes,3,opt,name=unsigned_vtxo_tree,json=unsignedVtxoTree,proto3" json:"unsigned_vtxo_tree,omitempty"` - UnsignedRoundTx string `protobuf:"bytes,4,opt,name=unsigned_round_tx,json=unsignedRoundTx,proto3" json:"unsigned_round_tx,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + UnsignedVtxoTree *Tree `protobuf:"bytes,2,opt,name=unsigned_vtxo_tree,json=unsignedVtxoTree,proto3" json:"unsigned_vtxo_tree,omitempty"` + UnsignedRoundTx string `protobuf:"bytes,3,opt,name=unsigned_round_tx,json=unsignedRoundTx,proto3" json:"unsigned_round_tx,omitempty"` } func (x *RoundSigningEvent) Reset() { @@ -1742,13 +1749,6 @@ func (x *RoundSigningEvent) GetId() string { return "" } -func (x *RoundSigningEvent) GetCosignersPubkeys() []string { - if x != nil { - return x.CosignersPubkeys - } - return nil -} - func (x *RoundSigningEvent) GetUnsignedVtxoTree() *Tree { if x != nil { return x.UnsignedVtxoTree @@ -3124,446 +3124,443 @@ var file_ark_v1_service_proto_rawDesc = []byte{ 0x72, 0x69, 0x70, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x48, 0x00, 0x52, 0x0a, 0x74, 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x42, 0x0e, 0x0a, - 0x0c, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x22, 0xa5, 0x01, + 0x0c, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x22, 0xaa, 0x01, 0x0a, 0x21, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x70, - 0x75, 0x74, 0x52, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x2e, 0x0a, 0x10, 0x65, 0x70, - 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0f, 0x65, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, - 0x6c, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x88, 0x01, 0x01, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, - 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x65, 0x73, - 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x65, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x5f, 0x70, - 0x75, 0x62, 0x6b, 0x65, 0x79, 0x22, 0x43, 0x0a, 0x22, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, - 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, - 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x22, 0x6d, 0x0a, 0x22, 0x52, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, - 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, - 0x28, 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x0e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, - 0x52, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x22, 0x25, 0x0a, 0x23, 0x52, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, + 0x75, 0x74, 0x52, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x69, + 0x67, 0x6e, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, + 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x69, 0x67, 0x6e, 0x69, + 0x6e, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x73, + 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x22, 0x43, 0x0a, 0x22, 0x52, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x6d, 0x0a, 0x17, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, - 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x72, - 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, - 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x1f, - 0x0a, 0x0b, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x22, - 0x1a, 0x0a, 0x18, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, - 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x79, 0x0a, 0x1b, 0x53, + 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x22, + 0x6d, 0x0a, 0x22, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, + 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, + 0x75, 0x74, 0x70, 0x75, 0x74, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x22, 0x25, + 0x0a, 0x23, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, + 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6d, 0x0a, 0x17, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, + 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x19, 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, + 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, + 0x6b, 0x65, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, + 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x72, 0x65, 0x65, 0x4e, 0x6f, + 0x6e, 0x63, 0x65, 0x73, 0x22, 0x1a, 0x0a, 0x18, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, + 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x79, 0x0a, 0x1b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x19, 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, + 0x62, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, + 0x65, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x72, 0x65, + 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x22, 0x1e, 0x0a, 0x1c, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x6f, - 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x6f, - 0x75, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x27, 0x0a, - 0x0f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x22, 0x1e, 0x0a, 0x1c, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, - 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x8e, 0x01, 0x0a, 0x1d, 0x53, 0x75, 0x62, 0x6d, 0x69, - 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x69, 0x67, 0x6e, - 0x65, 0x64, 0x5f, 0x66, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x5f, 0x74, 0x78, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, - 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x2b, 0x0a, 0x0f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, - 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, - 0x00, 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, - 0x88, 0x01, 0x01, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x72, - 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x22, 0x20, 0x0a, 0x1e, 0x53, 0x75, 0x62, 0x6d, 0x69, - 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x0a, 0x15, 0x47, 0x65, 0x74, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x22, 0xa7, 0x03, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, - 0x12, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, - 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x11, 0x72, 0x6f, 0x75, - 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x46, - 0x0a, 0x0f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0e, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, - 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x38, 0x0a, 0x0c, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, - 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x61, - 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x61, 0x69, 0x6c, 0x65, - 0x64, 0x48, 0x00, 0x52, 0x0b, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, - 0x12, 0x40, 0x0a, 0x0d, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, - 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, - 0x6e, 0x67, 0x12, 0x6f, 0x0a, 0x1e, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, 0x69, 0x67, 0x6e, - 0x69, 0x6e, 0x67, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, - 0x61, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x61, 0x72, 0x6b, - 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, - 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1b, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, - 0x6e, 0x69, 0x6e, 0x67, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, - 0x74, 0x65, 0x64, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x2c, 0x0a, 0x0b, - 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x22, 0x0e, 0x0a, 0x0c, 0x50, 0x69, - 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x0a, 0x15, 0x53, 0x75, - 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x5f, 0x74, 0x78, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, - 0x22, 0x42, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, - 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x69, - 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x5f, 0x74, 0x78, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x52, 0x65, 0x64, 0x65, - 0x65, 0x6d, 0x54, 0x78, 0x22, 0x25, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x22, 0x37, 0x0a, 0x10, 0x47, - 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x23, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, - 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x05, 0x72, - 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x25, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, - 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x3b, 0x0a, 0x14, 0x47, - 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, - 0x64, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x2c, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, - 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x79, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, - 0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x0f, 0x73, - 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x74, - 0x78, 0x6f, 0x52, 0x0e, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x74, 0x78, - 0x6f, 0x73, 0x12, 0x2d, 0x0a, 0x0b, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x74, 0x78, 0x6f, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x0a, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x56, 0x74, 0x78, 0x6f, - 0x73, 0x22, 0xbb, 0x01, 0x0a, 0x16, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, - 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, - 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x12, 0x29, 0x0a, 0x09, 0x76, 0x74, 0x78, 0x6f, 0x5f, - 0x74, 0x72, 0x65, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, - 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x52, 0x08, 0x76, 0x74, 0x78, 0x6f, 0x54, 0x72, - 0x65, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, - 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, - 0x72, 0x73, 0x12, 0x2b, 0x0a, 0x12, 0x6d, 0x69, 0x6e, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x5f, - 0x66, 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, - 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x46, 0x65, 0x65, 0x52, 0x61, 0x74, 0x65, 0x22, - 0x44, 0x0a, 0x13, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, - 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, - 0x74, 0x78, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x6f, 0x75, 0x6e, - 0x64, 0x54, 0x78, 0x69, 0x64, 0x22, 0x35, 0x0a, 0x0b, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x61, - 0x69, 0x6c, 0x65, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0xb8, 0x01, 0x0a, - 0x11, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, - 0x69, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x63, 0x6f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x5f, - 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x63, - 0x6f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x73, 0x12, - 0x3a, 0x0a, 0x12, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x76, 0x74, 0x78, 0x6f, - 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, - 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x52, 0x10, 0x75, 0x6e, 0x73, 0x69, 0x67, - 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, 0x54, 0x72, 0x65, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x75, - 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, - 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x22, 0x53, 0x0a, 0x20, 0x52, 0x6f, 0x75, 0x6e, 0x64, - 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x47, 0x65, 0x6e, - 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x74, - 0x72, 0x65, 0x65, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x74, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x22, 0xf0, 0x01, 0x0a, - 0x05, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, - 0x65, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x19, - 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x12, 0x29, 0x0a, 0x09, 0x76, 0x74, 0x78, - 0x6f, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, - 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x52, 0x08, 0x76, 0x74, 0x78, 0x6f, - 0x54, 0x72, 0x65, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x5f, - 0x74, 0x78, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x6f, 0x72, 0x66, 0x65, - 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x6f, 0x72, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x28, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, - 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x22, - 0x32, 0x0a, 0x08, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, - 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, - 0x12, 0x0a, 0x04, 0x76, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x76, - 0x6f, 0x75, 0x74, 0x22, 0x9d, 0x01, 0x0a, 0x05, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x2c, 0x0a, - 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x20, 0x0a, 0x0a, 0x64, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, - 0x00, 0x52, 0x0a, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x34, 0x0a, - 0x0a, 0x74, 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x70, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x73, 0x48, 0x00, 0x52, 0x0a, 0x74, 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x73, 0x42, 0x0e, 0x0a, 0x0c, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x74, - 0x72, 0x65, 0x65, 0x22, 0x3a, 0x0a, 0x06, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x18, 0x0a, - 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, - 0x31, 0x0a, 0x04, 0x54, 0x72, 0x65, 0x65, 0x12, 0x29, 0x0a, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x06, 0x6c, 0x65, 0x76, 0x65, - 0x6c, 0x73, 0x22, 0x2f, 0x0a, 0x09, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, - 0x22, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, - 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x6e, 0x6f, - 0x64, 0x65, 0x73, 0x22, 0x4b, 0x0a, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, - 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, - 0x0e, 0x0a, 0x02, 0x74, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x74, 0x78, 0x12, - 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x78, 0x69, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x54, 0x78, 0x69, 0x64, - 0x22, 0xc2, 0x02, 0x0a, 0x04, 0x56, 0x74, 0x78, 0x6f, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x75, 0x74, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, - 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, - 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x70, 0x65, 0x6e, 0x74, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x12, 0x1d, 0x0a, - 0x0a, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, - 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x73, 0x70, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, - 0x65, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x65, 0x78, 0x70, 0x69, - 0x72, 0x65, 0x41, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x77, 0x65, 0x70, 0x74, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x05, 0x73, 0x77, 0x65, 0x70, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, - 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, - 0x69, 0x73, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x64, - 0x65, 0x65, 0x6d, 0x5f, 0x74, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, - 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x16, - 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x1e, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x8c, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, - 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x48, 0x00, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x33, 0x0a, 0x06, 0x72, 0x65, 0x64, - 0x65, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x72, 0x6b, 0x2e, - 0x76, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x42, 0x04, - 0x0a, 0x02, 0x74, 0x78, 0x22, 0xd8, 0x01, 0x0a, 0x10, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x31, 0x0a, - 0x0b, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, + 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x8e, 0x01, 0x0a, 0x1d, + 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, + 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, + 0x12, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x66, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x5f, + 0x74, 0x78, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x73, 0x69, 0x67, 0x6e, 0x65, + 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x2b, 0x0a, 0x0f, 0x73, + 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x52, 0x6f, + 0x75, 0x6e, 0x64, 0x54, 0x78, 0x88, 0x01, 0x01, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x73, 0x69, 0x67, + 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x22, 0x20, 0x0a, 0x1e, + 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, + 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, + 0x0a, 0x15, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xa7, 0x03, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x12, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x66, 0x69, 0x6e, 0x61, + 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, + 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, + 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, + 0x52, 0x11, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x0a, 0x0f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x66, 0x69, 0x6e, + 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, + 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x7a, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0e, 0x72, 0x6f, 0x75, + 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x38, 0x0a, 0x0c, 0x72, + 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x13, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, + 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0b, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x46, + 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x40, 0x0a, 0x0d, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, + 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, + 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, + 0x6e, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x72, 0x6f, 0x75, 0x6e, 0x64, + 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x6f, 0x0a, 0x1e, 0x72, 0x6f, 0x75, 0x6e, 0x64, + 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x5f, + 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x28, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, + 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x47, 0x65, 0x6e, 0x65, 0x72, + 0x61, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1b, 0x72, 0x6f, 0x75, + 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x47, + 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x22, 0x2c, 0x0a, 0x0b, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x22, + 0x0e, 0x0a, 0x0c, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x34, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, + 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x64, 0x65, + 0x65, 0x6d, 0x5f, 0x74, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x64, + 0x65, 0x65, 0x6d, 0x54, 0x78, 0x22, 0x42, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, + 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x28, 0x0a, 0x10, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, + 0x5f, 0x74, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x69, 0x67, 0x6e, 0x65, + 0x64, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x22, 0x25, 0x0a, 0x0f, 0x47, 0x65, 0x74, + 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, + 0x22, 0x37, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, + 0x6e, 0x64, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x25, 0x0a, 0x13, 0x47, 0x65, 0x74, + 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, + 0x22, 0x3b, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x2c, 0x0a, + 0x10, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x79, 0x0a, 0x11, 0x4c, + 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x74, - 0x78, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, + 0x78, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x0e, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, - 0x6c, 0x65, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x46, 0x0a, 0x16, 0x63, 0x6c, 0x61, 0x69, 0x6d, - 0x65, 0x64, 0x5f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x75, 0x74, 0x78, 0x6f, - 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x14, 0x63, 0x6c, 0x61, 0x69, 0x6d, - 0x65, 0x64, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x22, - 0x91, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x31, 0x0a, 0x0b, 0x73, 0x70, 0x65, - 0x6e, 0x74, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, - 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x52, 0x0a, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x35, 0x0a, 0x0f, - 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, - 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x56, - 0x74, 0x78, 0x6f, 0x52, 0x0e, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x74, - 0x78, 0x6f, 0x73, 0x22, 0x6b, 0x0a, 0x0e, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, - 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x22, 0x70, 0x0a, 0x12, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, 0x4f, 0x75, - 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, - 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x77, 0x6e, - 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x05, 0x70, 0x72, 0x6f, - 0x6f, 0x66, 0x22, 0x75, 0x0a, 0x18, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, - 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, - 0x0a, 0x0f, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, - 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, - 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x52, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x1b, 0x0a, 0x19, 0x53, 0x65, 0x74, - 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4f, 0x0a, 0x1b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x52, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x1e, 0x0a, 0x1c, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x0a, 0x0a, 0x54, 0x61, 0x70, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x22, - 0x85, 0x02, 0x0a, 0x0a, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x48, 0x6f, 0x75, 0x72, 0x12, 0x42, - 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, - 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x74, - 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x6e, 0x65, 0x78, 0x74, 0x45, 0x6e, 0x64, 0x54, 0x69, - 0x6d, 0x65, 0x12, 0x31, 0x0a, 0x06, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x70, - 0x65, 0x72, 0x69, 0x6f, 0x64, 0x12, 0x40, 0x0a, 0x0e, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x2a, 0x98, 0x01, 0x0a, 0x0a, 0x52, 0x6f, 0x75, 0x6e, - 0x64, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, - 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, - 0x47, 0x45, 0x5f, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, - 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, - 0x5f, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12, - 0x19, 0x0a, 0x15, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x46, - 0x49, 0x4e, 0x41, 0x4c, 0x49, 0x5a, 0x45, 0x44, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x4f, - 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, - 0x10, 0x04, 0x32, 0xf0, 0x0e, 0x0a, 0x0a, 0x41, 0x72, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x12, 0x4c, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x61, - 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, - 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x66, 0x6f, 0x12, - 0x74, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x21, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x11, 0x3a, 0x01, 0x2a, 0x22, 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x6f, 0x61, - 0x72, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x98, 0x01, 0x0a, 0x1a, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, - 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, - 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x29, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, - 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, - 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, - 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x1d, 0x3a, 0x01, 0x2a, 0x22, 0x18, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, - 0x64, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, - 0x12, 0x9c, 0x01, 0x0a, 0x1b, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, + 0x6c, 0x65, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x2d, 0x0a, 0x0b, 0x73, 0x70, 0x65, 0x6e, 0x74, + 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, + 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x0a, 0x73, 0x70, 0x65, 0x6e, + 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x22, 0xbb, 0x01, 0x0a, 0x16, 0x52, 0x6f, 0x75, 0x6e, 0x64, + 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, + 0x64, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x12, 0x29, 0x0a, 0x09, + 0x76, 0x74, 0x78, 0x6f, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x52, 0x08, 0x76, + 0x74, 0x78, 0x6f, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x2b, 0x0a, 0x12, 0x6d, 0x69, 0x6e, 0x5f, 0x72, + 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x46, 0x65, 0x65, + 0x52, 0x61, 0x74, 0x65, 0x22, 0x44, 0x0a, 0x13, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, + 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, + 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x69, 0x64, 0x22, 0x35, 0x0a, 0x0b, 0x52, 0x6f, + 0x75, 0x6e, 0x64, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, + 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, + 0x6e, 0x22, 0x8b, 0x01, 0x0a, 0x11, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, + 0x6e, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x3a, 0x0a, 0x12, 0x75, 0x6e, 0x73, 0x69, 0x67, + 0x6e, 0x65, 0x64, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, + 0x65, 0x52, 0x10, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, 0x54, + 0x72, 0x65, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, + 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, + 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x22, + 0x53, 0x0a, 0x20, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4e, + 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x69, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, + 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x72, 0x65, 0x65, 0x4e, 0x6f, + 0x6e, 0x63, 0x65, 0x73, 0x22, 0xf0, 0x01, 0x0a, 0x05, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, + 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, + 0x74, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, + 0x78, 0x12, 0x29, 0x0a, 0x09, 0x76, 0x74, 0x78, 0x6f, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, + 0x65, 0x65, 0x52, 0x08, 0x76, 0x74, 0x78, 0x6f, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1f, 0x0a, 0x0b, + 0x66, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x5f, 0x74, 0x78, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x0a, 0x66, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x1e, 0x0a, + 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x28, 0x0a, + 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x61, + 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x67, 0x65, + 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x22, 0x32, 0x0a, 0x08, 0x4f, 0x75, 0x74, 0x70, 0x6f, + 0x69, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x76, 0x6f, 0x75, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x76, 0x6f, 0x75, 0x74, 0x22, 0x9d, 0x01, 0x0a, 0x05, + 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, + 0x69, 0x6e, 0x74, 0x12, 0x20, 0x0a, 0x0a, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x34, 0x0a, 0x0a, 0x74, 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x72, 0x6b, 0x2e, + 0x76, 0x31, 0x2e, 0x54, 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x48, 0x00, 0x52, + 0x0a, 0x74, 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x42, 0x0e, 0x0a, 0x0c, 0x74, + 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x22, 0x3a, 0x0a, 0x06, 0x4f, + 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, + 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x31, 0x0a, 0x04, 0x54, 0x72, 0x65, 0x65, 0x12, + 0x29, 0x0a, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x11, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x65, 0x76, + 0x65, 0x6c, 0x52, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x22, 0x2f, 0x0a, 0x09, 0x54, 0x72, + 0x65, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x22, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, + 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x4b, 0x0a, 0x04, 0x4e, + 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x78, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x02, 0x74, 0x78, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, + 0x74, 0x5f, 0x74, 0x78, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, + 0x72, 0x65, 0x6e, 0x74, 0x54, 0x78, 0x69, 0x64, 0x22, 0xc2, 0x02, 0x0a, 0x04, 0x56, 0x74, 0x78, + 0x6f, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, + 0x14, 0x0a, 0x05, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, + 0x73, 0x70, 0x65, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, + 0x78, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x6f, 0x75, 0x6e, 0x64, + 0x54, 0x78, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x12, + 0x1b, 0x0a, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x08, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x74, 0x12, 0x14, 0x0a, 0x05, + 0x73, 0x77, 0x65, 0x70, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x73, 0x77, 0x65, + 0x70, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, + 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x5f, 0x74, 0x78, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x12, 0x16, + 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, + 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x1d, + 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x1e, 0x0a, + 0x1c, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x8c, 0x01, + 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x30, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, + 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, + 0x64, 0x12, 0x33, 0x0a, 0x06, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x65, 0x65, + 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x06, + 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x42, 0x04, 0x0a, 0x02, 0x74, 0x78, 0x22, 0xd8, 0x01, 0x0a, + 0x10, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x31, 0x0a, 0x0b, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x76, + 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, + 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x73, 0x70, + 0x65, 0x6e, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x35, 0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, + 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, + 0x0e, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, + 0x46, 0x0a, 0x16, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x5f, 0x62, 0x6f, 0x61, 0x72, 0x64, + 0x69, 0x6e, 0x67, 0x5f, 0x75, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x52, 0x14, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, + 0x6e, 0x67, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x91, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x64, 0x65, + 0x65, 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, + 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, + 0x64, 0x12, 0x31, 0x0a, 0x0b, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, + 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x56, + 0x74, 0x78, 0x6f, 0x73, 0x12, 0x35, 0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, + 0x65, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, + 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x0e, 0x73, 0x70, 0x65, + 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x6b, 0x0a, 0x0e, 0x4f, + 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x23, 0x0a, + 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x70, 0x0a, 0x12, 0x53, 0x69, 0x67, 0x6e, + 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2c, + 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, + 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x05, + 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x72, + 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x72, + 0x6f, 0x6f, 0x66, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x75, 0x0a, 0x18, 0x53, 0x65, + 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x5f, + 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0e, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, + 0x30, 0x0a, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, + 0x78, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x05, 0x76, 0x74, 0x78, 0x6f, + 0x73, 0x22, 0x1b, 0x0a, 0x19, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, + 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4f, + 0x0a, 0x1b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, + 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, + 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, + 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, + 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x22, + 0x1e, 0x0a, 0x1c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, + 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x26, 0x0a, 0x0a, 0x54, 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x12, 0x18, 0x0a, + 0x07, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x22, 0x85, 0x02, 0x0a, 0x0a, 0x4d, 0x61, 0x72, 0x6b, + 0x65, 0x74, 0x48, 0x6f, 0x75, 0x72, 0x12, 0x42, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x6e, 0x65, 0x78, + 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0d, 0x6e, 0x65, + 0x78, 0x74, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x6e, + 0x65, 0x78, 0x74, 0x45, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x31, 0x0a, 0x06, 0x70, 0x65, + 0x72, 0x69, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x12, 0x40, 0x0a, + 0x0e, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x0d, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x2a, + 0x98, 0x01, 0x0a, 0x0a, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x1b, + 0x0a, 0x17, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x52, + 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x52, 0x45, 0x47, 0x49, 0x53, + 0x54, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, 0x55, + 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x49, 0x5a, + 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x52, 0x4f, 0x55, 0x4e, 0x44, + 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x49, 0x5a, 0x45, 0x44, + 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, + 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x04, 0x32, 0xf0, 0x0e, 0x0a, 0x0a, 0x41, + 0x72, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x07, 0x47, 0x65, 0x74, + 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, + 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x61, + 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, + 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x74, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x42, 0x6f, + 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x21, 0x2e, + 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, + 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x22, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, + 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x3a, 0x01, 0x2a, 0x22, + 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x98, 0x01, + 0x0a, 0x1a, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, + 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x29, 0x2e, 0x61, + 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, - 0x12, 0x2a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, - 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, - 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x61, - 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, - 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x1e, 0x3a, 0x01, 0x2a, 0x22, 0x19, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, - 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x12, - 0x7d, 0x0a, 0x10, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, - 0x63, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, - 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, - 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, - 0x2a, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x74, 0x72, 0x65, - 0x65, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x8d, - 0x01, 0x0a, 0x14, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x23, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x61, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, + 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x3a, 0x01, 0x2a, 0x22, 0x18, + 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x9c, 0x01, 0x0a, 0x1b, 0x52, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, + 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, + 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, + 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x3a, 0x01, 0x2a, 0x22, 0x19, 0x2f, 0x76, + 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, + 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x12, 0x7d, 0x0a, 0x10, 0x53, 0x75, 0x62, 0x6d, 0x69, + 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x61, 0x72, + 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, + 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, - 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x3a, 0x01, 0x2a, 0x22, 0x1f, 0x2f, - 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x2f, 0x73, 0x75, - 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x8e, - 0x01, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, - 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x25, 0x2e, 0x61, 0x72, 0x6b, 0x2e, - 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, - 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x26, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, - 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, - 0x3a, 0x01, 0x2a, 0x22, 0x1a, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x73, - 0x75, 0x62, 0x6d, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, - 0x65, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, - 0x6d, 0x12, 0x1d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x12, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0c, 0x12, 0x0a, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x73, 0x30, 0x01, 0x12, 0x56, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x13, - 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, - 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x1d, 0x12, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x70, 0x69, 0x6e, - 0x67, 0x2f, 0x7b, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x69, - 0x0a, 0x0e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, - 0x12, 0x1d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, - 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, - 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x3a, 0x01, 0x2a, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f, - 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x2d, 0x74, 0x78, 0x12, 0x57, 0x0a, 0x08, 0x47, 0x65, 0x74, - 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x17, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, - 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, - 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x7b, 0x74, 0x78, 0x69, - 0x64, 0x7d, 0x12, 0x64, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, - 0x49, 0x64, 0x12, 0x1b, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, - 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, - 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, - 0x2f, 0x69, 0x64, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x5d, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, - 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x18, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x19, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, - 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x2f, 0x7b, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x7d, 0x12, 0x80, 0x01, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, - 0x6d, 0x12, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x30, 0x01, 0x12, 0x73, 0x0a, 0x11, 0x53, 0x65, - 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, - 0x20, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, - 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x21, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x6f, - 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x22, - 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78, 0x6f, 0x2f, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x12, - 0x83, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, - 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, - 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, - 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, - 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, - 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x3a, 0x01, 0x2a, 0x22, 0x15, - 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78, 0x6f, 0x2f, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x2f, 0x64, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x92, 0x01, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x72, - 0x6b, 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x61, 0x72, 0x6b, 0x2d, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x61, 0x72, 0x6b, - 0x2f, 0x61, 0x70, 0x69, 0x2d, 0x73, 0x70, 0x65, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x61, 0x72, 0x6b, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x72, - 0x6b, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x41, 0x58, 0x58, 0xaa, 0x02, 0x06, 0x41, 0x72, 0x6b, 0x2e, - 0x56, 0x31, 0xca, 0x02, 0x06, 0x41, 0x72, 0x6b, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x12, 0x41, 0x72, - 0x6b, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0xea, 0x02, 0x07, 0x41, 0x72, 0x6b, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, 0x2a, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x72, + 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, + 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x8d, 0x01, 0x0a, 0x14, 0x53, 0x75, 0x62, 0x6d, 0x69, + 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, + 0x23, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, + 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, + 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x24, 0x3a, 0x01, 0x2a, 0x22, 0x1f, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, + 0x2f, 0x74, 0x72, 0x65, 0x65, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x8e, 0x01, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, + 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, + 0x73, 0x12, 0x25, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, + 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, + 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x3a, 0x01, 0x2a, 0x22, 0x1a, 0x2f, 0x76, 0x31, + 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x46, 0x6f, 0x72, + 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x65, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x12, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0c, + 0x12, 0x0a, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x30, 0x01, 0x12, 0x56, + 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x13, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, + 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x72, + 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x72, + 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x70, 0x69, 0x6e, 0x67, 0x2f, 0x7b, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x69, 0x0a, 0x0e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, + 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x12, 0x1d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x3a, + 0x01, 0x2a, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x2d, 0x74, + 0x78, 0x12, 0x57, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x17, 0x2e, + 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, + 0x75, 0x6e, 0x64, 0x2f, 0x7b, 0x74, 0x78, 0x69, 0x64, 0x7d, 0x12, 0x64, 0x0a, 0x0c, 0x47, 0x65, + 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x12, 0x1b, 0x2e, 0x61, 0x72, 0x6b, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, + 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x69, 0x64, 0x2f, 0x7b, 0x69, 0x64, 0x7d, + 0x12, 0x5d, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x18, 0x2e, + 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, + 0x76, 0x74, 0x78, 0x6f, 0x73, 0x2f, 0x7b, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x7d, 0x12, + 0x80, 0x01, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x25, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, + 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x30, 0x01, 0x12, 0x73, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, + 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x20, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x61, 0x72, 0x6b, 0x2e, + 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, + 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x22, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78, + 0x6f, 0x2f, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x12, 0x83, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, + 0x12, 0x23, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, + 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x1a, 0x3a, 0x01, 0x2a, 0x22, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78, 0x6f, + 0x2f, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x2f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x92, 0x01, + 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3d, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x6b, 0x2d, 0x6e, 0x65, 0x74, + 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x61, 0x72, 0x6b, 0x2f, 0x61, 0x70, 0x69, 0x2d, 0x73, 0x70, 0x65, + 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x61, + 0x72, 0x6b, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x72, 0x6b, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x41, 0x58, + 0x58, 0xaa, 0x02, 0x06, 0x41, 0x72, 0x6b, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x06, 0x41, 0x72, 0x6b, + 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x12, 0x41, 0x72, 0x6b, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x07, 0x41, 0x72, 0x6b, 0x3a, 0x3a, + 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -4336,7 +4333,6 @@ func file_ark_v1_service_proto_init() { (*GetBoardingAddressResponse_Descriptor_)(nil), (*GetBoardingAddressResponse_Tapscripts)(nil), } - file_ark_v1_service_proto_msgTypes[4].OneofWrappers = []interface{}{} file_ark_v1_service_proto_msgTypes[12].OneofWrappers = []interface{}{} file_ark_v1_service_proto_msgTypes[15].OneofWrappers = []interface{}{ (*GetEventStreamResponse_RoundFinalization)(nil), diff --git a/api-spec/protobuf/gen/ark/v1/service.pb.gw.go b/api-spec/protobuf/gen/ark/v1/service.pb.gw.go index 898e4991a..c26d7897f 100644 --- a/api-spec/protobuf/gen/ark/v1/service.pb.gw.go +++ b/api-spec/protobuf/gen/ark/v1/service.pb.gw.go @@ -10,6 +10,7 @@ package arkv1 import ( "context" + "errors" "io" "net/http" @@ -24,191 +25,183 @@ import ( ) // Suppress "imported and not used" errors -var _ codes.Code -var _ io.Reader -var _ status.Status -var _ = runtime.String -var _ = utilities.NewDoubleArray -var _ = metadata.Join +var ( + _ codes.Code + _ io.Reader + _ status.Status + _ = errors.New + _ = runtime.String + _ = utilities.NewDoubleArray + _ = metadata.Join +) func request_ArkService_GetInfo_0(ctx context.Context, marshaler runtime.Marshaler, client ArkServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetInfoRequest - var metadata runtime.ServerMetadata - + var ( + protoReq GetInfoRequest + metadata runtime.ServerMetadata + ) msg, err := client.GetInfo(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ArkService_GetInfo_0(ctx context.Context, marshaler runtime.Marshaler, server ArkServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetInfoRequest - var metadata runtime.ServerMetadata - + var ( + protoReq GetInfoRequest + metadata runtime.ServerMetadata + ) msg, err := server.GetInfo(ctx, &protoReq) return msg, metadata, err - } func request_ArkService_GetBoardingAddress_0(ctx context.Context, marshaler runtime.Marshaler, client ArkServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetBoardingAddressRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq GetBoardingAddressRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.GetBoardingAddress(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ArkService_GetBoardingAddress_0(ctx context.Context, marshaler runtime.Marshaler, server ArkServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetBoardingAddressRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq GetBoardingAddressRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.GetBoardingAddress(ctx, &protoReq) return msg, metadata, err - } func request_ArkService_RegisterInputsForNextRound_0(ctx context.Context, marshaler runtime.Marshaler, client ArkServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq RegisterInputsForNextRoundRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq RegisterInputsForNextRoundRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.RegisterInputsForNextRound(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ArkService_RegisterInputsForNextRound_0(ctx context.Context, marshaler runtime.Marshaler, server ArkServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq RegisterInputsForNextRoundRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq RegisterInputsForNextRoundRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.RegisterInputsForNextRound(ctx, &protoReq) return msg, metadata, err - } func request_ArkService_RegisterOutputsForNextRound_0(ctx context.Context, marshaler runtime.Marshaler, client ArkServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq RegisterOutputsForNextRoundRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq RegisterOutputsForNextRoundRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.RegisterOutputsForNextRound(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ArkService_RegisterOutputsForNextRound_0(ctx context.Context, marshaler runtime.Marshaler, server ArkServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq RegisterOutputsForNextRoundRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq RegisterOutputsForNextRoundRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.RegisterOutputsForNextRound(ctx, &protoReq) return msg, metadata, err - } func request_ArkService_SubmitTreeNonces_0(ctx context.Context, marshaler runtime.Marshaler, client ArkServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SubmitTreeNoncesRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq SubmitTreeNoncesRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.SubmitTreeNonces(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ArkService_SubmitTreeNonces_0(ctx context.Context, marshaler runtime.Marshaler, server ArkServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SubmitTreeNoncesRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq SubmitTreeNoncesRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.SubmitTreeNonces(ctx, &protoReq) return msg, metadata, err - } func request_ArkService_SubmitTreeSignatures_0(ctx context.Context, marshaler runtime.Marshaler, client ArkServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SubmitTreeSignaturesRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq SubmitTreeSignaturesRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.SubmitTreeSignatures(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ArkService_SubmitTreeSignatures_0(ctx context.Context, marshaler runtime.Marshaler, server ArkServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SubmitTreeSignaturesRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq SubmitTreeSignaturesRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.SubmitTreeSignatures(ctx, &protoReq) return msg, metadata, err - } func request_ArkService_SubmitSignedForfeitTxs_0(ctx context.Context, marshaler runtime.Marshaler, client ArkServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SubmitSignedForfeitTxsRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq SubmitSignedForfeitTxsRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.SubmitSignedForfeitTxs(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ArkService_SubmitSignedForfeitTxs_0(ctx context.Context, marshaler runtime.Marshaler, server ArkServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SubmitSignedForfeitTxsRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq SubmitSignedForfeitTxsRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.SubmitSignedForfeitTxs(ctx, &protoReq) return msg, metadata, err - } func request_ArkService_GetEventStream_0(ctx context.Context, marshaler runtime.Marshaler, client ArkServiceClient, req *http.Request, pathParams map[string]string) (ArkService_GetEventStreamClient, runtime.ServerMetadata, error) { - var protoReq GetEventStreamRequest - var metadata runtime.ServerMetadata - + var ( + protoReq GetEventStreamRequest + metadata runtime.ServerMetadata + ) stream, err := client.GetEventStream(ctx, &protoReq) if err != nil { return nil, metadata, err @@ -219,247 +212,181 @@ func request_ArkService_GetEventStream_0(ctx context.Context, marshaler runtime. } metadata.HeaderMD = header return stream, metadata, nil - } func request_ArkService_Ping_0(ctx context.Context, marshaler runtime.Marshaler, client ArkServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq PingRequest - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq PingRequest + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["request_id"] + val, ok := pathParams["request_id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "request_id") } - protoReq.RequestId, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "request_id", err) } - msg, err := client.Ping(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ArkService_Ping_0(ctx context.Context, marshaler runtime.Marshaler, server ArkServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq PingRequest - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq PingRequest + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["request_id"] + val, ok := pathParams["request_id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "request_id") } - protoReq.RequestId, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "request_id", err) } - msg, err := server.Ping(ctx, &protoReq) return msg, metadata, err - } func request_ArkService_SubmitRedeemTx_0(ctx context.Context, marshaler runtime.Marshaler, client ArkServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SubmitRedeemTxRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq SubmitRedeemTxRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.SubmitRedeemTx(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ArkService_SubmitRedeemTx_0(ctx context.Context, marshaler runtime.Marshaler, server ArkServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SubmitRedeemTxRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq SubmitRedeemTxRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.SubmitRedeemTx(ctx, &protoReq) return msg, metadata, err - } func request_ArkService_GetRound_0(ctx context.Context, marshaler runtime.Marshaler, client ArkServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetRoundRequest - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq GetRoundRequest + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["txid"] + val, ok := pathParams["txid"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "txid") } - protoReq.Txid, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "txid", err) } - msg, err := client.GetRound(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ArkService_GetRound_0(ctx context.Context, marshaler runtime.Marshaler, server ArkServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetRoundRequest - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq GetRoundRequest + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["txid"] + val, ok := pathParams["txid"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "txid") } - protoReq.Txid, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "txid", err) } - msg, err := server.GetRound(ctx, &protoReq) return msg, metadata, err - } func request_ArkService_GetRoundById_0(ctx context.Context, marshaler runtime.Marshaler, client ArkServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetRoundByIdRequest - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq GetRoundByIdRequest + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["id"] + val, ok := pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - msg, err := client.GetRoundById(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ArkService_GetRoundById_0(ctx context.Context, marshaler runtime.Marshaler, server ArkServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetRoundByIdRequest - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq GetRoundByIdRequest + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["id"] + val, ok := pathParams["id"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") } - protoReq.Id, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) } - msg, err := server.GetRoundById(ctx, &protoReq) return msg, metadata, err - } func request_ArkService_ListVtxos_0(ctx context.Context, marshaler runtime.Marshaler, client ArkServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListVtxosRequest - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq ListVtxosRequest + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["address"] + val, ok := pathParams["address"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address") } - protoReq.Address, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err) } - msg, err := client.ListVtxos(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ArkService_ListVtxos_0(ctx context.Context, marshaler runtime.Marshaler, server ArkServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListVtxosRequest - var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err + protoReq ListVtxosRequest + metadata runtime.ServerMetadata + err error ) - - val, ok = pathParams["address"] + val, ok := pathParams["address"] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address") } - protoReq.Address, err = runtime.String(val) if err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err) } - msg, err := server.ListVtxos(ctx, &protoReq) return msg, metadata, err - } func request_ArkService_GetTransactionsStream_0(ctx context.Context, marshaler runtime.Marshaler, client ArkServiceClient, req *http.Request, pathParams map[string]string) (ArkService_GetTransactionsStreamClient, runtime.ServerMetadata, error) { - var protoReq GetTransactionsStreamRequest - var metadata runtime.ServerMetadata - + var ( + protoReq GetTransactionsStreamRequest + metadata runtime.ServerMetadata + ) stream, err := client.GetTransactionsStream(ctx, &protoReq) if err != nil { return nil, metadata, err @@ -470,59 +397,54 @@ func request_ArkService_GetTransactionsStream_0(ctx context.Context, marshaler r } metadata.HeaderMD = header return stream, metadata, nil - } func request_ArkService_SetNostrRecipient_0(ctx context.Context, marshaler runtime.Marshaler, client ArkServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SetNostrRecipientRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq SetNostrRecipientRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.SetNostrRecipient(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ArkService_SetNostrRecipient_0(ctx context.Context, marshaler runtime.Marshaler, server ArkServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SetNostrRecipientRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq SetNostrRecipientRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.SetNostrRecipient(ctx, &protoReq) return msg, metadata, err - } func request_ArkService_DeleteNostrRecipient_0(ctx context.Context, marshaler runtime.Marshaler, client ArkServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq DeleteNostrRecipientRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq DeleteNostrRecipientRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.DeleteNostrRecipient(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_ArkService_DeleteNostrRecipient_0(ctx context.Context, marshaler runtime.Marshaler, server ArkServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq DeleteNostrRecipientRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq DeleteNostrRecipientRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.DeleteNostrRecipient(ctx, &protoReq) return msg, metadata, err - } // RegisterArkServiceHandlerServer registers the http handlers for service ArkService to "mux". @@ -531,16 +453,13 @@ func local_request_ArkService_DeleteNostrRecipient_0(ctx context.Context, marsha // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterArkServiceHandlerFromEndpoint instead. // GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. func RegisterArkServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server ArkServiceServer) error { - - mux.Handle("GET", pattern_ArkService_GetInfo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ArkService_GetInfo_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/GetInfo", runtime.WithHTTPPathPattern("/v1/info")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/GetInfo", runtime.WithHTTPPathPattern("/v1/info")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -552,20 +471,15 @@ func RegisterArkServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_GetInfo_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_ArkService_GetBoardingAddress_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_ArkService_GetBoardingAddress_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/GetBoardingAddress", runtime.WithHTTPPathPattern("/v1/boarding")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/GetBoardingAddress", runtime.WithHTTPPathPattern("/v1/boarding")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -577,20 +491,15 @@ func RegisterArkServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_GetBoardingAddress_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_ArkService_RegisterInputsForNextRound_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_ArkService_RegisterInputsForNextRound_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/RegisterInputsForNextRound", runtime.WithHTTPPathPattern("/v1/round/registerInputs")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/RegisterInputsForNextRound", runtime.WithHTTPPathPattern("/v1/round/registerInputs")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -602,20 +511,15 @@ func RegisterArkServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_RegisterInputsForNextRound_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_ArkService_RegisterOutputsForNextRound_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_ArkService_RegisterOutputsForNextRound_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/RegisterOutputsForNextRound", runtime.WithHTTPPathPattern("/v1/round/registerOutputs")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/RegisterOutputsForNextRound", runtime.WithHTTPPathPattern("/v1/round/registerOutputs")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -627,20 +531,15 @@ func RegisterArkServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_RegisterOutputsForNextRound_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_ArkService_SubmitTreeNonces_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_ArkService_SubmitTreeNonces_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/SubmitTreeNonces", runtime.WithHTTPPathPattern("/v1/round/tree/submitNonces")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/SubmitTreeNonces", runtime.WithHTTPPathPattern("/v1/round/tree/submitNonces")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -652,20 +551,15 @@ func RegisterArkServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_SubmitTreeNonces_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_ArkService_SubmitTreeSignatures_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_ArkService_SubmitTreeSignatures_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/SubmitTreeSignatures", runtime.WithHTTPPathPattern("/v1/round/tree/submitSignatures")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/SubmitTreeSignatures", runtime.WithHTTPPathPattern("/v1/round/tree/submitSignatures")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -677,20 +571,15 @@ func RegisterArkServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_SubmitTreeSignatures_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_ArkService_SubmitSignedForfeitTxs_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_ArkService_SubmitSignedForfeitTxs_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/SubmitSignedForfeitTxs", runtime.WithHTTPPathPattern("/v1/round/submitForfeitTxs")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/SubmitSignedForfeitTxs", runtime.WithHTTPPathPattern("/v1/round/submitForfeitTxs")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -702,27 +591,22 @@ func RegisterArkServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_SubmitSignedForfeitTxs_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - mux.Handle("GET", pattern_ArkService_GetEventStream_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ArkService_GetEventStream_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport") _, outboundMarshaler := runtime.MarshalerForRequest(mux, req) runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return }) - - mux.Handle("GET", pattern_ArkService_Ping_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ArkService_Ping_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/Ping", runtime.WithHTTPPathPattern("/v1/round/ping/{request_id}")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/Ping", runtime.WithHTTPPathPattern("/v1/round/ping/{request_id}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -734,20 +618,15 @@ func RegisterArkServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_Ping_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_ArkService_SubmitRedeemTx_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_ArkService_SubmitRedeemTx_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/SubmitRedeemTx", runtime.WithHTTPPathPattern("/v1/redeem-tx")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/SubmitRedeemTx", runtime.WithHTTPPathPattern("/v1/redeem-tx")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -759,20 +638,15 @@ func RegisterArkServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_SubmitRedeemTx_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_ArkService_GetRound_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ArkService_GetRound_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/GetRound", runtime.WithHTTPPathPattern("/v1/round/{txid}")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/GetRound", runtime.WithHTTPPathPattern("/v1/round/{txid}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -784,20 +658,15 @@ func RegisterArkServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_GetRound_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_ArkService_GetRoundById_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ArkService_GetRoundById_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/GetRoundById", runtime.WithHTTPPathPattern("/v1/round/id/{id}")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/GetRoundById", runtime.WithHTTPPathPattern("/v1/round/id/{id}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -809,20 +678,15 @@ func RegisterArkServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_GetRoundById_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_ArkService_ListVtxos_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ArkService_ListVtxos_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/ListVtxos", runtime.WithHTTPPathPattern("/v1/vtxos/{address}")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/ListVtxos", runtime.WithHTTPPathPattern("/v1/vtxos/{address}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -834,27 +698,22 @@ func RegisterArkServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_ListVtxos_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - mux.Handle("GET", pattern_ArkService_GetTransactionsStream_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ArkService_GetTransactionsStream_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport") _, outboundMarshaler := runtime.MarshalerForRequest(mux, req) runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return }) - - mux.Handle("POST", pattern_ArkService_SetNostrRecipient_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_ArkService_SetNostrRecipient_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/SetNostrRecipient", runtime.WithHTTPPathPattern("/v1/vtxo/nostr")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/SetNostrRecipient", runtime.WithHTTPPathPattern("/v1/vtxo/nostr")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -866,20 +725,15 @@ func RegisterArkServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_SetNostrRecipient_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_ArkService_DeleteNostrRecipient_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_ArkService_DeleteNostrRecipient_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/DeleteNostrRecipient", runtime.WithHTTPPathPattern("/v1/vtxo/nostr/delete")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/DeleteNostrRecipient", runtime.WithHTTPPathPattern("/v1/vtxo/nostr/delete")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -891,9 +745,7 @@ func RegisterArkServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_DeleteNostrRecipient_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) return nil @@ -920,7 +772,6 @@ func RegisterArkServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.Ser } }() }() - return RegisterArkServiceHandler(ctx, mux, conn) } @@ -936,14 +787,11 @@ func RegisterArkServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in // "ArkServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares. func RegisterArkServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client ArkServiceClient) error { - - mux.Handle("GET", pattern_ArkService_GetInfo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ArkService_GetInfo_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/GetInfo", runtime.WithHTTPPathPattern("/v1/info")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/GetInfo", runtime.WithHTTPPathPattern("/v1/info")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -954,18 +802,13 @@ func RegisterArkServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_GetInfo_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_ArkService_GetBoardingAddress_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_ArkService_GetBoardingAddress_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/GetBoardingAddress", runtime.WithHTTPPathPattern("/v1/boarding")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/GetBoardingAddress", runtime.WithHTTPPathPattern("/v1/boarding")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -976,18 +819,13 @@ func RegisterArkServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_GetBoardingAddress_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_ArkService_RegisterInputsForNextRound_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_ArkService_RegisterInputsForNextRound_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/RegisterInputsForNextRound", runtime.WithHTTPPathPattern("/v1/round/registerInputs")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/RegisterInputsForNextRound", runtime.WithHTTPPathPattern("/v1/round/registerInputs")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -998,18 +836,13 @@ func RegisterArkServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_RegisterInputsForNextRound_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_ArkService_RegisterOutputsForNextRound_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_ArkService_RegisterOutputsForNextRound_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/RegisterOutputsForNextRound", runtime.WithHTTPPathPattern("/v1/round/registerOutputs")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/RegisterOutputsForNextRound", runtime.WithHTTPPathPattern("/v1/round/registerOutputs")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -1020,18 +853,13 @@ func RegisterArkServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_RegisterOutputsForNextRound_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_ArkService_SubmitTreeNonces_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_ArkService_SubmitTreeNonces_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/SubmitTreeNonces", runtime.WithHTTPPathPattern("/v1/round/tree/submitNonces")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/SubmitTreeNonces", runtime.WithHTTPPathPattern("/v1/round/tree/submitNonces")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -1042,18 +870,13 @@ func RegisterArkServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_SubmitTreeNonces_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_ArkService_SubmitTreeSignatures_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_ArkService_SubmitTreeSignatures_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/SubmitTreeSignatures", runtime.WithHTTPPathPattern("/v1/round/tree/submitSignatures")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/SubmitTreeSignatures", runtime.WithHTTPPathPattern("/v1/round/tree/submitSignatures")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -1064,18 +887,13 @@ func RegisterArkServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_SubmitTreeSignatures_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_ArkService_SubmitSignedForfeitTxs_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_ArkService_SubmitSignedForfeitTxs_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/SubmitSignedForfeitTxs", runtime.WithHTTPPathPattern("/v1/round/submitForfeitTxs")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/SubmitSignedForfeitTxs", runtime.WithHTTPPathPattern("/v1/round/submitForfeitTxs")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -1086,18 +904,13 @@ func RegisterArkServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_SubmitSignedForfeitTxs_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_ArkService_GetEventStream_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ArkService_GetEventStream_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/GetEventStream", runtime.WithHTTPPathPattern("/v1/events")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/GetEventStream", runtime.WithHTTPPathPattern("/v1/events")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -1108,18 +921,13 @@ func RegisterArkServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_GetEventStream_0(annotatedContext, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_ArkService_Ping_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ArkService_Ping_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/Ping", runtime.WithHTTPPathPattern("/v1/round/ping/{request_id}")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/Ping", runtime.WithHTTPPathPattern("/v1/round/ping/{request_id}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -1130,18 +938,13 @@ func RegisterArkServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_Ping_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_ArkService_SubmitRedeemTx_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_ArkService_SubmitRedeemTx_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/SubmitRedeemTx", runtime.WithHTTPPathPattern("/v1/redeem-tx")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/SubmitRedeemTx", runtime.WithHTTPPathPattern("/v1/redeem-tx")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -1152,18 +955,13 @@ func RegisterArkServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_SubmitRedeemTx_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_ArkService_GetRound_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ArkService_GetRound_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/GetRound", runtime.WithHTTPPathPattern("/v1/round/{txid}")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/GetRound", runtime.WithHTTPPathPattern("/v1/round/{txid}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -1174,18 +972,13 @@ func RegisterArkServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_GetRound_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_ArkService_GetRoundById_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ArkService_GetRoundById_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/GetRoundById", runtime.WithHTTPPathPattern("/v1/round/id/{id}")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/GetRoundById", runtime.WithHTTPPathPattern("/v1/round/id/{id}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -1196,18 +989,13 @@ func RegisterArkServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_GetRoundById_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_ArkService_ListVtxos_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ArkService_ListVtxos_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/ListVtxos", runtime.WithHTTPPathPattern("/v1/vtxos/{address}")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/ListVtxos", runtime.WithHTTPPathPattern("/v1/vtxos/{address}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -1218,18 +1006,13 @@ func RegisterArkServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_ListVtxos_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_ArkService_GetTransactionsStream_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_ArkService_GetTransactionsStream_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/GetTransactionsStream", runtime.WithHTTPPathPattern("/v1/transactions")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/GetTransactionsStream", runtime.WithHTTPPathPattern("/v1/transactions")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -1240,18 +1023,13 @@ func RegisterArkServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_GetTransactionsStream_0(annotatedContext, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_ArkService_SetNostrRecipient_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_ArkService_SetNostrRecipient_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/SetNostrRecipient", runtime.WithHTTPPathPattern("/v1/vtxo/nostr")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/SetNostrRecipient", runtime.WithHTTPPathPattern("/v1/vtxo/nostr")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -1262,18 +1040,13 @@ func RegisterArkServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_SetNostrRecipient_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_ArkService_DeleteNostrRecipient_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_ArkService_DeleteNostrRecipient_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/DeleteNostrRecipient", runtime.WithHTTPPathPattern("/v1/vtxo/nostr/delete")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/DeleteNostrRecipient", runtime.WithHTTPPathPattern("/v1/vtxo/nostr/delete")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -1284,78 +1057,45 @@ func RegisterArkServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_ArkService_DeleteNostrRecipient_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - return nil } var ( - pattern_ArkService_GetInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "info"}, "")) - - pattern_ArkService_GetBoardingAddress_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "boarding"}, "")) - - pattern_ArkService_RegisterInputsForNextRound_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "round", "registerInputs"}, "")) - + pattern_ArkService_GetInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "info"}, "")) + pattern_ArkService_GetBoardingAddress_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "boarding"}, "")) + pattern_ArkService_RegisterInputsForNextRound_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "round", "registerInputs"}, "")) pattern_ArkService_RegisterOutputsForNextRound_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "round", "registerOutputs"}, "")) - - pattern_ArkService_SubmitTreeNonces_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "round", "tree", "submitNonces"}, "")) - - pattern_ArkService_SubmitTreeSignatures_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "round", "tree", "submitSignatures"}, "")) - - pattern_ArkService_SubmitSignedForfeitTxs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "round", "submitForfeitTxs"}, "")) - - pattern_ArkService_GetEventStream_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "events"}, "")) - - pattern_ArkService_Ping_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "round", "ping", "request_id"}, "")) - - pattern_ArkService_SubmitRedeemTx_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "redeem-tx"}, "")) - - pattern_ArkService_GetRound_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "round", "txid"}, "")) - - pattern_ArkService_GetRoundById_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 2}, []string{"v1", "round", "id"}, "")) - - pattern_ArkService_ListVtxos_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "vtxos", "address"}, "")) - - pattern_ArkService_GetTransactionsStream_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "transactions"}, "")) - - pattern_ArkService_SetNostrRecipient_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "vtxo", "nostr"}, "")) - - pattern_ArkService_DeleteNostrRecipient_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "vtxo", "nostr", "delete"}, "")) + pattern_ArkService_SubmitTreeNonces_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "round", "tree", "submitNonces"}, "")) + pattern_ArkService_SubmitTreeSignatures_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "round", "tree", "submitSignatures"}, "")) + pattern_ArkService_SubmitSignedForfeitTxs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "round", "submitForfeitTxs"}, "")) + pattern_ArkService_GetEventStream_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "events"}, "")) + pattern_ArkService_Ping_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "round", "ping", "request_id"}, "")) + pattern_ArkService_SubmitRedeemTx_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "redeem-tx"}, "")) + pattern_ArkService_GetRound_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "round", "txid"}, "")) + pattern_ArkService_GetRoundById_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 2}, []string{"v1", "round", "id"}, "")) + pattern_ArkService_ListVtxos_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "vtxos", "address"}, "")) + pattern_ArkService_GetTransactionsStream_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "transactions"}, "")) + pattern_ArkService_SetNostrRecipient_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "vtxo", "nostr"}, "")) + pattern_ArkService_DeleteNostrRecipient_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "vtxo", "nostr", "delete"}, "")) ) var ( - forward_ArkService_GetInfo_0 = runtime.ForwardResponseMessage - - forward_ArkService_GetBoardingAddress_0 = runtime.ForwardResponseMessage - - forward_ArkService_RegisterInputsForNextRound_0 = runtime.ForwardResponseMessage - + forward_ArkService_GetInfo_0 = runtime.ForwardResponseMessage + forward_ArkService_GetBoardingAddress_0 = runtime.ForwardResponseMessage + forward_ArkService_RegisterInputsForNextRound_0 = runtime.ForwardResponseMessage forward_ArkService_RegisterOutputsForNextRound_0 = runtime.ForwardResponseMessage - - forward_ArkService_SubmitTreeNonces_0 = runtime.ForwardResponseMessage - - forward_ArkService_SubmitTreeSignatures_0 = runtime.ForwardResponseMessage - - forward_ArkService_SubmitSignedForfeitTxs_0 = runtime.ForwardResponseMessage - - forward_ArkService_GetEventStream_0 = runtime.ForwardResponseStream - - forward_ArkService_Ping_0 = runtime.ForwardResponseMessage - - forward_ArkService_SubmitRedeemTx_0 = runtime.ForwardResponseMessage - - forward_ArkService_GetRound_0 = runtime.ForwardResponseMessage - - forward_ArkService_GetRoundById_0 = runtime.ForwardResponseMessage - - forward_ArkService_ListVtxos_0 = runtime.ForwardResponseMessage - - forward_ArkService_GetTransactionsStream_0 = runtime.ForwardResponseStream - - forward_ArkService_SetNostrRecipient_0 = runtime.ForwardResponseMessage - - forward_ArkService_DeleteNostrRecipient_0 = runtime.ForwardResponseMessage + forward_ArkService_SubmitTreeNonces_0 = runtime.ForwardResponseMessage + forward_ArkService_SubmitTreeSignatures_0 = runtime.ForwardResponseMessage + forward_ArkService_SubmitSignedForfeitTxs_0 = runtime.ForwardResponseMessage + forward_ArkService_GetEventStream_0 = runtime.ForwardResponseStream + forward_ArkService_Ping_0 = runtime.ForwardResponseMessage + forward_ArkService_SubmitRedeemTx_0 = runtime.ForwardResponseMessage + forward_ArkService_GetRound_0 = runtime.ForwardResponseMessage + forward_ArkService_GetRoundById_0 = runtime.ForwardResponseMessage + forward_ArkService_ListVtxos_0 = runtime.ForwardResponseMessage + forward_ArkService_GetTransactionsStream_0 = runtime.ForwardResponseStream + forward_ArkService_SetNostrRecipient_0 = runtime.ForwardResponseMessage + forward_ArkService_DeleteNostrRecipient_0 = runtime.ForwardResponseMessage ) diff --git a/api-spec/protobuf/gen/ark/v1/wallet.pb.gw.go b/api-spec/protobuf/gen/ark/v1/wallet.pb.gw.go index 2329357e7..875b3e9c2 100644 --- a/api-spec/protobuf/gen/ark/v1/wallet.pb.gw.go +++ b/api-spec/protobuf/gen/ark/v1/wallet.pb.gw.go @@ -10,6 +10,7 @@ package arkv1 import ( "context" + "errors" "io" "net/http" @@ -24,187 +25,182 @@ import ( ) // Suppress "imported and not used" errors -var _ codes.Code -var _ io.Reader -var _ status.Status -var _ = runtime.String -var _ = utilities.NewDoubleArray -var _ = metadata.Join +var ( + _ codes.Code + _ io.Reader + _ status.Status + _ = errors.New + _ = runtime.String + _ = utilities.NewDoubleArray + _ = metadata.Join +) func request_WalletInitializerService_GenSeed_0(ctx context.Context, marshaler runtime.Marshaler, client WalletInitializerServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GenSeedRequest - var metadata runtime.ServerMetadata - + var ( + protoReq GenSeedRequest + metadata runtime.ServerMetadata + ) msg, err := client.GenSeed(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_WalletInitializerService_GenSeed_0(ctx context.Context, marshaler runtime.Marshaler, server WalletInitializerServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GenSeedRequest - var metadata runtime.ServerMetadata - + var ( + protoReq GenSeedRequest + metadata runtime.ServerMetadata + ) msg, err := server.GenSeed(ctx, &protoReq) return msg, metadata, err - } func request_WalletInitializerService_Create_0(ctx context.Context, marshaler runtime.Marshaler, client WalletInitializerServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq CreateRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq CreateRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.Create(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_WalletInitializerService_Create_0(ctx context.Context, marshaler runtime.Marshaler, server WalletInitializerServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq CreateRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq CreateRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Create(ctx, &protoReq) return msg, metadata, err - } func request_WalletInitializerService_Restore_0(ctx context.Context, marshaler runtime.Marshaler, client WalletInitializerServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq RestoreRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq RestoreRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.Restore(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_WalletInitializerService_Restore_0(ctx context.Context, marshaler runtime.Marshaler, server WalletInitializerServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq RestoreRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq RestoreRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Restore(ctx, &protoReq) return msg, metadata, err - } func request_WalletInitializerService_Unlock_0(ctx context.Context, marshaler runtime.Marshaler, client WalletInitializerServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq UnlockRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq UnlockRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.Unlock(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_WalletInitializerService_Unlock_0(ctx context.Context, marshaler runtime.Marshaler, server WalletInitializerServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq UnlockRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq UnlockRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Unlock(ctx, &protoReq) return msg, metadata, err - } func request_WalletInitializerService_GetStatus_0(ctx context.Context, marshaler runtime.Marshaler, client WalletInitializerServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetStatusRequest - var metadata runtime.ServerMetadata - + var ( + protoReq GetStatusRequest + metadata runtime.ServerMetadata + ) msg, err := client.GetStatus(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_WalletInitializerService_GetStatus_0(ctx context.Context, marshaler runtime.Marshaler, server WalletInitializerServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetStatusRequest - var metadata runtime.ServerMetadata - + var ( + protoReq GetStatusRequest + metadata runtime.ServerMetadata + ) msg, err := server.GetStatus(ctx, &protoReq) return msg, metadata, err - } func request_WalletService_Lock_0(ctx context.Context, marshaler runtime.Marshaler, client WalletServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq LockRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq LockRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.Lock(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_WalletService_Lock_0(ctx context.Context, marshaler runtime.Marshaler, server WalletServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq LockRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq LockRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Lock(ctx, &protoReq) return msg, metadata, err - } func request_WalletService_DeriveAddress_0(ctx context.Context, marshaler runtime.Marshaler, client WalletServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq DeriveAddressRequest - var metadata runtime.ServerMetadata - + var ( + protoReq DeriveAddressRequest + metadata runtime.ServerMetadata + ) msg, err := client.DeriveAddress(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_WalletService_DeriveAddress_0(ctx context.Context, marshaler runtime.Marshaler, server WalletServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq DeriveAddressRequest - var metadata runtime.ServerMetadata - + var ( + protoReq DeriveAddressRequest + metadata runtime.ServerMetadata + ) msg, err := server.DeriveAddress(ctx, &protoReq) return msg, metadata, err - } func request_WalletService_GetBalance_0(ctx context.Context, marshaler runtime.Marshaler, client WalletServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetBalanceRequest - var metadata runtime.ServerMetadata - + var ( + protoReq GetBalanceRequest + metadata runtime.ServerMetadata + ) msg, err := client.GetBalance(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err - } func local_request_WalletService_GetBalance_0(ctx context.Context, marshaler runtime.Marshaler, server WalletServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetBalanceRequest - var metadata runtime.ServerMetadata - + var ( + protoReq GetBalanceRequest + metadata runtime.ServerMetadata + ) msg, err := server.GetBalance(ctx, &protoReq) return msg, metadata, err - } // RegisterWalletInitializerServiceHandlerServer registers the http handlers for service WalletInitializerService to "mux". @@ -213,16 +209,13 @@ func local_request_WalletService_GetBalance_0(ctx context.Context, marshaler run // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterWalletInitializerServiceHandlerFromEndpoint instead. // GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. func RegisterWalletInitializerServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server WalletInitializerServiceServer) error { - - mux.Handle("GET", pattern_WalletInitializerService_GenSeed_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_WalletInitializerService_GenSeed_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.WalletInitializerService/GenSeed", runtime.WithHTTPPathPattern("/v1/admin/wallet/seed")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.WalletInitializerService/GenSeed", runtime.WithHTTPPathPattern("/v1/admin/wallet/seed")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -234,20 +227,15 @@ func RegisterWalletInitializerServiceHandlerServer(ctx context.Context, mux *run runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_WalletInitializerService_GenSeed_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_WalletInitializerService_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_WalletInitializerService_Create_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.WalletInitializerService/Create", runtime.WithHTTPPathPattern("/v1/admin/wallet/create")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.WalletInitializerService/Create", runtime.WithHTTPPathPattern("/v1/admin/wallet/create")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -259,20 +247,15 @@ func RegisterWalletInitializerServiceHandlerServer(ctx context.Context, mux *run runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_WalletInitializerService_Create_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_WalletInitializerService_Restore_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_WalletInitializerService_Restore_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.WalletInitializerService/Restore", runtime.WithHTTPPathPattern("/v1/admin/wallet/restore")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.WalletInitializerService/Restore", runtime.WithHTTPPathPattern("/v1/admin/wallet/restore")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -284,20 +267,15 @@ func RegisterWalletInitializerServiceHandlerServer(ctx context.Context, mux *run runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_WalletInitializerService_Restore_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_WalletInitializerService_Unlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_WalletInitializerService_Unlock_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.WalletInitializerService/Unlock", runtime.WithHTTPPathPattern("/v1/admin/wallet/unlock")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.WalletInitializerService/Unlock", runtime.WithHTTPPathPattern("/v1/admin/wallet/unlock")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -309,20 +287,15 @@ func RegisterWalletInitializerServiceHandlerServer(ctx context.Context, mux *run runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_WalletInitializerService_Unlock_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_WalletInitializerService_GetStatus_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_WalletInitializerService_GetStatus_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.WalletInitializerService/GetStatus", runtime.WithHTTPPathPattern("/v1/admin/wallet/status")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.WalletInitializerService/GetStatus", runtime.WithHTTPPathPattern("/v1/admin/wallet/status")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -334,9 +307,7 @@ func RegisterWalletInitializerServiceHandlerServer(ctx context.Context, mux *run runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_WalletInitializerService_GetStatus_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) return nil @@ -348,16 +319,13 @@ func RegisterWalletInitializerServiceHandlerServer(ctx context.Context, mux *run // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterWalletServiceHandlerFromEndpoint instead. // GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. func RegisterWalletServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server WalletServiceServer) error { - - mux.Handle("POST", pattern_WalletService_Lock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_WalletService_Lock_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.WalletService/Lock", runtime.WithHTTPPathPattern("/v1/admin/wallet/lock")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.WalletService/Lock", runtime.WithHTTPPathPattern("/v1/admin/wallet/lock")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -369,20 +337,15 @@ func RegisterWalletServiceHandlerServer(ctx context.Context, mux *runtime.ServeM runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_WalletService_Lock_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_WalletService_DeriveAddress_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_WalletService_DeriveAddress_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.WalletService/DeriveAddress", runtime.WithHTTPPathPattern("/v1/admin/wallet/address")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.WalletService/DeriveAddress", runtime.WithHTTPPathPattern("/v1/admin/wallet/address")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -394,20 +357,15 @@ func RegisterWalletServiceHandlerServer(ctx context.Context, mux *runtime.ServeM runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_WalletService_DeriveAddress_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_WalletService_GetBalance_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_WalletService_GetBalance_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.WalletService/GetBalance", runtime.WithHTTPPathPattern("/v1/admin/wallet/balance")) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.WalletService/GetBalance", runtime.WithHTTPPathPattern("/v1/admin/wallet/balance")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -419,9 +377,7 @@ func RegisterWalletServiceHandlerServer(ctx context.Context, mux *runtime.ServeM runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_WalletService_GetBalance_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) return nil @@ -448,7 +404,6 @@ func RegisterWalletInitializerServiceHandlerFromEndpoint(ctx context.Context, mu } }() }() - return RegisterWalletInitializerServiceHandler(ctx, mux, conn) } @@ -464,14 +419,11 @@ func RegisterWalletInitializerServiceHandler(ctx context.Context, mux *runtime.S // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in // "WalletInitializerServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares. func RegisterWalletInitializerServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client WalletInitializerServiceClient) error { - - mux.Handle("GET", pattern_WalletInitializerService_GenSeed_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_WalletInitializerService_GenSeed_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.WalletInitializerService/GenSeed", runtime.WithHTTPPathPattern("/v1/admin/wallet/seed")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.WalletInitializerService/GenSeed", runtime.WithHTTPPathPattern("/v1/admin/wallet/seed")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -482,18 +434,13 @@ func RegisterWalletInitializerServiceHandlerClient(ctx context.Context, mux *run runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_WalletInitializerService_GenSeed_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_WalletInitializerService_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_WalletInitializerService_Create_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.WalletInitializerService/Create", runtime.WithHTTPPathPattern("/v1/admin/wallet/create")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.WalletInitializerService/Create", runtime.WithHTTPPathPattern("/v1/admin/wallet/create")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -504,18 +451,13 @@ func RegisterWalletInitializerServiceHandlerClient(ctx context.Context, mux *run runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_WalletInitializerService_Create_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_WalletInitializerService_Restore_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_WalletInitializerService_Restore_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.WalletInitializerService/Restore", runtime.WithHTTPPathPattern("/v1/admin/wallet/restore")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.WalletInitializerService/Restore", runtime.WithHTTPPathPattern("/v1/admin/wallet/restore")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -526,18 +468,13 @@ func RegisterWalletInitializerServiceHandlerClient(ctx context.Context, mux *run runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_WalletInitializerService_Restore_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("POST", pattern_WalletInitializerService_Unlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_WalletInitializerService_Unlock_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.WalletInitializerService/Unlock", runtime.WithHTTPPathPattern("/v1/admin/wallet/unlock")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.WalletInitializerService/Unlock", runtime.WithHTTPPathPattern("/v1/admin/wallet/unlock")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -548,18 +485,13 @@ func RegisterWalletInitializerServiceHandlerClient(ctx context.Context, mux *run runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_WalletInitializerService_Unlock_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_WalletInitializerService_GetStatus_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_WalletInitializerService_GetStatus_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.WalletInitializerService/GetStatus", runtime.WithHTTPPathPattern("/v1/admin/wallet/status")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.WalletInitializerService/GetStatus", runtime.WithHTTPPathPattern("/v1/admin/wallet/status")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -570,35 +502,24 @@ func RegisterWalletInitializerServiceHandlerClient(ctx context.Context, mux *run runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_WalletInitializerService_GetStatus_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - return nil } var ( - pattern_WalletInitializerService_GenSeed_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "admin", "wallet", "seed"}, "")) - - pattern_WalletInitializerService_Create_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "admin", "wallet", "create"}, "")) - - pattern_WalletInitializerService_Restore_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "admin", "wallet", "restore"}, "")) - - pattern_WalletInitializerService_Unlock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "admin", "wallet", "unlock"}, "")) - + pattern_WalletInitializerService_GenSeed_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "admin", "wallet", "seed"}, "")) + pattern_WalletInitializerService_Create_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "admin", "wallet", "create"}, "")) + pattern_WalletInitializerService_Restore_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "admin", "wallet", "restore"}, "")) + pattern_WalletInitializerService_Unlock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "admin", "wallet", "unlock"}, "")) pattern_WalletInitializerService_GetStatus_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "admin", "wallet", "status"}, "")) ) var ( - forward_WalletInitializerService_GenSeed_0 = runtime.ForwardResponseMessage - - forward_WalletInitializerService_Create_0 = runtime.ForwardResponseMessage - - forward_WalletInitializerService_Restore_0 = runtime.ForwardResponseMessage - - forward_WalletInitializerService_Unlock_0 = runtime.ForwardResponseMessage - + forward_WalletInitializerService_GenSeed_0 = runtime.ForwardResponseMessage + forward_WalletInitializerService_Create_0 = runtime.ForwardResponseMessage + forward_WalletInitializerService_Restore_0 = runtime.ForwardResponseMessage + forward_WalletInitializerService_Unlock_0 = runtime.ForwardResponseMessage forward_WalletInitializerService_GetStatus_0 = runtime.ForwardResponseMessage ) @@ -623,7 +544,6 @@ func RegisterWalletServiceHandlerFromEndpoint(ctx context.Context, mux *runtime. } }() }() - return RegisterWalletServiceHandler(ctx, mux, conn) } @@ -639,14 +559,11 @@ func RegisterWalletServiceHandler(ctx context.Context, mux *runtime.ServeMux, co // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in // "WalletServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares. func RegisterWalletServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client WalletServiceClient) error { - - mux.Handle("POST", pattern_WalletService_Lock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_WalletService_Lock_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.WalletService/Lock", runtime.WithHTTPPathPattern("/v1/admin/wallet/lock")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.WalletService/Lock", runtime.WithHTTPPathPattern("/v1/admin/wallet/lock")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -657,18 +574,13 @@ func RegisterWalletServiceHandlerClient(ctx context.Context, mux *runtime.ServeM runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_WalletService_Lock_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_WalletService_DeriveAddress_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_WalletService_DeriveAddress_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.WalletService/DeriveAddress", runtime.WithHTTPPathPattern("/v1/admin/wallet/address")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.WalletService/DeriveAddress", runtime.WithHTTPPathPattern("/v1/admin/wallet/address")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -679,18 +591,13 @@ func RegisterWalletServiceHandlerClient(ctx context.Context, mux *runtime.ServeM runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_WalletService_DeriveAddress_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - - mux.Handle("GET", pattern_WalletService_GetBalance_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodGet, pattern_WalletService_GetBalance_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) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.WalletService/GetBalance", runtime.WithHTTPPathPattern("/v1/admin/wallet/balance")) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.WalletService/GetBalance", runtime.WithHTTPPathPattern("/v1/admin/wallet/balance")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -701,26 +608,19 @@ func RegisterWalletServiceHandlerClient(ctx context.Context, mux *runtime.ServeM runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - forward_WalletService_GetBalance_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - }) - return nil } var ( - pattern_WalletService_Lock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "admin", "wallet", "lock"}, "")) - + pattern_WalletService_Lock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "admin", "wallet", "lock"}, "")) pattern_WalletService_DeriveAddress_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "admin", "wallet", "address"}, "")) - - pattern_WalletService_GetBalance_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "admin", "wallet", "balance"}, "")) + pattern_WalletService_GetBalance_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "admin", "wallet", "balance"}, "")) ) var ( - forward_WalletService_Lock_0 = runtime.ForwardResponseMessage - + forward_WalletService_Lock_0 = runtime.ForwardResponseMessage forward_WalletService_DeriveAddress_0 = runtime.ForwardResponseMessage - - forward_WalletService_GetBalance_0 = runtime.ForwardResponseMessage + forward_WalletService_GetBalance_0 = runtime.ForwardResponseMessage ) diff --git a/common/bitcointree/builder.go b/common/bitcointree/builder.go index d5c895257..f8c2ca307 100644 --- a/common/bitcointree/builder.go +++ b/common/bitcointree/builder.go @@ -7,7 +7,6 @@ import ( "github.com/ark-network/ark/common" "github.com/ark-network/ark/common/tree" "github.com/btcsuite/btcd/btcec/v2/schnorr" - "github.com/btcsuite/btcd/btcec/v2/schnorr/musig2" "github.com/btcsuite/btcd/btcutil/psbt" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" @@ -15,46 +14,40 @@ import ( "github.com/decred/dcrd/dcrec/secp256k1/v4" ) -// CraftSharedOutput returns the taproot script and the amount of the initial root output +// CraftSharedOutput returns the taproot script and the amount of the initial root shared output of a vtxo tree func CraftSharedOutput( - cosigners []*secp256k1.PublicKey, server *secp256k1.PublicKey, receivers []tree.VtxoLeaf, - feeSatsPerNode uint64, roundLifetime common.RelativeLocktime, + receivers []tree.VtxoLeaf, + feeSatsPerNode uint64, + sweepTapTreeRoot []byte, ) ([]byte, int64, error) { - aggregatedKey, _, err := createAggregatedKeyWithSweep( - cosigners, server, roundLifetime, - ) + root, err := createRootNode(receivers, feeSatsPerNode, sweepTapTreeRoot) if err != nil { return nil, 0, err } - root, err := createRootNode(aggregatedKey, cosigners, receivers, feeSatsPerNode) + amount := root.getAmount() + int64(feeSatsPerNode) + + aggregatedKey, err := AggregateKeys(root.getCosigners(), sweepTapTreeRoot) if err != nil { - return nil, 0, err + return nil, 0, fmt.Errorf("failed to aggregate keys: %w", err) } - amount := root.getAmount() + int64(feeSatsPerNode) - scriptPubkey, err := common.P2TRScript(aggregatedKey.FinalKey) if err != nil { - return nil, 0, err + return nil, 0, fmt.Errorf("failed to create script pubkey: %w", err) } - return scriptPubkey, amount, err + return scriptPubkey, amount, nil } -// BuildVtxoTree creates all the tree's transactions +// BuildVtxoTree creates all the tree's transactions and returns the vtxo tree func BuildVtxoTree( - initialInput *wire.OutPoint, cosigners []*secp256k1.PublicKey, server *secp256k1.PublicKey, receivers []tree.VtxoLeaf, - feeSatsPerNode uint64, roundLifetime common.RelativeLocktime, + initialInput *wire.OutPoint, + receivers []tree.VtxoLeaf, + feeSatsPerNode uint64, + sweepTapTreeRoot []byte, ) (tree.VtxoTree, error) { - aggregatedKey, sweepTapLeaf, err := createAggregatedKeyWithSweep( - cosigners, server, roundLifetime, - ) - if err != nil { - return nil, err - } - - root, err := createRootNode(aggregatedKey, cosigners, receivers, feeSatsPerNode) + root, err := createRootNode(receivers, feeSatsPerNode, sweepTapTreeRoot) if err != nil { return nil, err } @@ -71,7 +64,7 @@ func BuildVtxoTree( treeLevel := make([]tree.Node, 0) for i, node := range nodes { - treeNode, err := getTreeNode(node, ins[i], schnorr.SerializePubKey(aggregatedKey.PreTweakedKey), sweepTapLeaf, cosigners) + treeNode, err := getTreeNode(node, ins[i]) if err != nil { return nil, err } @@ -107,18 +100,29 @@ type node interface { getAmount() int64 // returns the input amount of the node = sum of all receivers' amounts + fees getOutputs() ([]*wire.TxOut, error) getChildren() []node + getCosigners() []*secp256k1.PublicKey } type leaf struct { - amount int64 - pubkey *secp256k1.PublicKey + amount int64 + pkScript []byte + cosigners []*secp256k1.PublicKey + signerType tree.SigningType } type branch struct { - aggregatedKey *musig2.AggregateKey - cosigners []*secp256k1.PublicKey - children []node - feeAmount int64 + cosigners []*secp256k1.PublicKey + pkScript []byte + children []node + feeAmount int64 +} + +func (b *branch) getCosigners() []*secp256k1.PublicKey { + return b.cosigners +} + +func (l *leaf) getCosigners() []*secp256k1.PublicKey { + return l.cosigners } func (b *branch) getChildren() []node { @@ -144,31 +148,21 @@ func (l *leaf) getAmount() int64 { } func (l *leaf) getOutputs() ([]*wire.TxOut, error) { - script, err := common.P2TRScript(l.pubkey) - if err != nil { - return nil, err - } - - output := &wire.TxOut{ - Value: l.amount, - PkScript: script, - } - - return []*wire.TxOut{output}, nil + return []*wire.TxOut{ + { + Value: l.amount, + PkScript: l.pkScript, + }, + }, nil } func (b *branch) getOutputs() ([]*wire.TxOut, error) { - sharedOutputScript, err := common.P2TRScript(b.aggregatedKey.FinalKey) - if err != nil { - return nil, err - } - outputs := make([]*wire.TxOut, 0) for _, child := range b.children { outputs = append(outputs, &wire.TxOut{ Value: child.getAmount() + b.feeAmount, - PkScript: sharedOutputScript, + PkScript: b.pkScript, }) } @@ -178,11 +172,8 @@ func (b *branch) getOutputs() ([]*wire.TxOut, error) { func getTreeNode( n node, input *wire.OutPoint, - inputTapInternalKey []byte, - inputSweepTapLeaf *psbt.TaprootTapLeafScript, - cosigners []*secp256k1.PublicKey, ) (tree.Node, error) { - partialTx, err := getTx(n, input, inputTapInternalKey, inputSweepTapLeaf, cosigners) + partialTx, err := getTx(n, input) if err != nil { return tree.Node{}, err } @@ -205,9 +196,6 @@ func getTreeNode( func getTx( n node, input *wire.OutPoint, - inputTapInternalKey []byte, - inputSweepTapLeaf *psbt.TaprootTapLeafScript, - cosigners []*secp256k1.PublicKey, ) (*psbt.Packet, error) { outputs, err := n.getOutputs() if err != nil { @@ -228,10 +216,7 @@ func getTx( return nil, err } - tx.Inputs[0].TaprootInternalKey = inputTapInternalKey - tx.Inputs[0].TaprootLeafScript = []*psbt.TaprootTapLeafScript{inputSweepTapLeaf} - - for _, cosigner := range cosigners { + for _, cosigner := range n.getCosigners() { if err := AddCosignerKey(0, tx, cosigner); err != nil { return nil, err } @@ -241,91 +226,103 @@ func getTx( } func createRootNode( - aggregatedKey *musig2.AggregateKey, - cosigners []*secp256k1.PublicKey, receivers []tree.VtxoLeaf, feeSatsPerNode uint64, + sweepTapTreeRoot []byte, ) (root node, err error) { if len(receivers) == 0 { return nil, fmt.Errorf("no receivers provided") } - nodes := make([]node, 0, len(receivers)) + cosignersALL := make([]*secp256k1.PublicKey, 0) for _, r := range receivers { - pubkeyBytes, err := hex.DecodeString(r.PubKey) - if err != nil { - return nil, err + if r.Type != tree.SignAll { + continue } - pubkey, err := schnorr.ParsePubKey(pubkeyBytes) - if err != nil { - return nil, err + if len(r.SignersPublicKeys) == 0 { + return nil, fmt.Errorf("signers public keys for %s are empty", r.PubKey) } - leafNode := &leaf{ - amount: int64(r.Amount), - pubkey: pubkey, + for _, cosigner := range r.SignersPublicKeys { + pubkeyBytes, err := hex.DecodeString(cosigner) + if err != nil { + return nil, err + } + + pubkey, err := secp256k1.ParsePubKey(pubkeyBytes) + if err != nil { + return nil, fmt.Errorf("failed to parse cosigner pubkey: %w", err) + } + cosignersALL = append(cosignersALL, pubkey) } - nodes = append(nodes, leafNode) } - for len(nodes) > 1 { - nodes, err = createUpperLevel(nodes, aggregatedKey, cosigners, int64(feeSatsPerNode)) + nodes := make([]node, 0, len(receivers)) + for _, r := range receivers { + pubkeyBytes, err := hex.DecodeString(r.PubKey) if err != nil { - return + return nil, fmt.Errorf("failed to decode cosigner pubkey: %w", err) } - } - return nodes[0], nil -} + pubkey, err := schnorr.ParsePubKey(pubkeyBytes) + if err != nil { + return nil, fmt.Errorf("failed to parse vtxo script pubkey: %w", err) + } -func createAggregatedKeyWithSweep( - cosigners []*secp256k1.PublicKey, server *secp256k1.PublicKey, roundLifetime common.RelativeLocktime, -) (*musig2.AggregateKey, *psbt.TaprootTapLeafScript, error) { - sweepClosure := &tree.CSVMultisigClosure{ - MultisigClosure: tree.MultisigClosure{PubKeys: []*secp256k1.PublicKey{server}}, - Locktime: roundLifetime, - } + pkScript, err := common.P2TRScript(pubkey) + if err != nil { + return nil, fmt.Errorf("failed to create script pub key: %w", err) + } - sweepScript, err := sweepClosure.Script() - if err != nil { - return nil, nil, err - } + cosigners := make([]*secp256k1.PublicKey, 0) - sweepLeaf := txscript.NewBaseTapLeaf(sweepScript) + switch r.Type { + case tree.SignBranch: + for _, cosigner := range r.SignersPublicKeys { + pubkeyBytes, err := hex.DecodeString(cosigner) + if err != nil { + return nil, fmt.Errorf("failed to decode cosigner pubkey: %w", err) + } - tapTree := txscript.AssembleTaprootScriptTree(sweepLeaf) - tapTreeRoot := tapTree.RootNode.TapHash() + pubkey, err := secp256k1.ParsePubKey(pubkeyBytes) + if err != nil { + return nil, fmt.Errorf("failed to parse cosigner pubkey: %w", err) + } - aggregatedKey, err := AggregateKeys( - cosigners, tapTreeRoot[:], - ) - if err != nil { - return nil, nil, err - } + cosigners = append(cosigners, pubkey) + } + case tree.SignAll: + cosigners = cosignersALL + } - index := tapTree.LeafProofIndex[sweepLeaf.TapHash()] - proof := tapTree.LeafMerkleProofs[index] + if len(cosigners) == 0 { + return nil, fmt.Errorf("no cosigners for %s", r.PubKey) + } - controlBlock := proof.ToControlBlock(aggregatedKey.PreTweakedKey) - controlBlockBytes, err := controlBlock.ToBytes() - if err != nil { - return nil, nil, err + leafNode := &leaf{ + amount: int64(r.Amount), + pkScript: pkScript, + cosigners: cosigners, + signerType: r.Type, + } + nodes = append(nodes, leafNode) } - tapLeaf := &psbt.TaprootTapLeafScript{ - ControlBlock: controlBlockBytes, - Script: sweepLeaf.Script, - LeafVersion: sweepLeaf.LeafVersion, + for len(nodes) > 1 { + nodes, err = createUpperLevel(nodes, int64(feeSatsPerNode), sweepTapTreeRoot) + if err != nil { + return nil, fmt.Errorf("failed to vtxo tree: %w", err) + } } - return aggregatedKey, tapLeaf, nil + return nodes[0], nil } -func createUpperLevel(nodes []node, aggregatedKey *musig2.AggregateKey, cosigners []*secp256k1.PublicKey, feeAmount int64) ([]node, error) { +func createUpperLevel(nodes []node, feeAmount int64, tapTreeRoot []byte) ([]node, error) { if len(nodes)%2 != 0 { last := nodes[len(nodes)-1] - pairs, err := createUpperLevel(nodes[:len(nodes)-1], aggregatedKey, cosigners, feeAmount) + pairs, err := createUpperLevel(nodes[:len(nodes)-1], feeAmount, tapTreeRoot) if err != nil { return nil, err } @@ -337,11 +334,24 @@ func createUpperLevel(nodes []node, aggregatedKey *musig2.AggregateKey, cosigner for i := 0; i < len(nodes); i += 2 { left := nodes[i] right := nodes[i+1] + + cosigners := append(left.getCosigners(), right.getCosigners()...) + + aggregatedKey, err := AggregateKeys(cosigners, tapTreeRoot) + if err != nil { + return nil, err + } + + pkScript, err := common.P2TRScript(aggregatedKey.FinalKey) + if err != nil { + return nil, err + } + branchNode := &branch{ - aggregatedKey: aggregatedKey, - cosigners: cosigners, - feeAmount: feeAmount, - children: []node{left, right}, + pkScript: pkScript, + cosigners: cosigners, + feeAmount: feeAmount, + children: []node{left, right}, } pairs = append(pairs, branchNode) diff --git a/common/bitcointree/musig2.go b/common/bitcointree/musig2.go index 927e430fc..fe535d421 100644 --- a/common/bitcointree/musig2.go +++ b/common/bitcointree/musig2.go @@ -3,10 +3,13 @@ package bitcointree import ( "bytes" "encoding/binary" + "encoding/hex" "errors" "fmt" "io" + "runtime" "strings" + "sync" "github.com/ark-network/ark/common" "github.com/ark-network/ark/common/tree" @@ -20,8 +23,7 @@ import ( ) var ( - ErrMissingVtxoTree = errors.New("missing vtxo tree") - ErrMissingAggregateKey = errors.New("missing aggregate key") + ErrMissingVtxoTree = errors.New("missing vtxo tree") ) type Musig2Nonce struct { @@ -51,16 +53,16 @@ type TreeNonces [][]*Musig2Nonce // public nonces type TreePartialSigs [][]*musig2.PartialSignature type SignerSession interface { - GetNonces() (TreeNonces, error) // generate tree nonces for this session - SetKeys([]*btcec.PublicKey) error // set the cosigner public keys for this session - SetAggregatedNonces(TreeNonces) error // set the aggregated nonces - Sign() (TreePartialSigs, error) // sign the tree + GetPublicKey() string + GetNonces() (TreeNonces, error) // generate tree nonces for this session + SetAggregatedNonces(TreeNonces) // set the aggregated nonces + Sign() (TreePartialSigs, error) // sign the tree } type CoordinatorSession interface { - AddNonce(*btcec.PublicKey, TreeNonces) error + AddNonce(*btcec.PublicKey, TreeNonces) + AddSig(*btcec.PublicKey, TreePartialSigs) AggregateNonces() (TreeNonces, error) - AddSig(*btcec.PublicKey, TreePartialSigs) error // SignTree combines the signatures and add them to the tree's psbts SignTree() (tree.VtxoTree, error) } @@ -97,6 +99,20 @@ func AggregateKeys( pubkeys []*btcec.PublicKey, scriptRoot []byte, ) (*musig2.AggregateKey, error) { + if len(pubkeys) == 0 { + return nil, errors.New("no pubkeys") + } + + for _, pubkey := range pubkeys { + if pubkey == nil { + return nil, errors.New("nil pubkey") + } + } + + if scriptRoot == nil { + return nil, errors.New("nil script root") + } + key, _, _, err := musig2.AggregateKeys(pubkeys, true, musig2.WithTaprootKeyTweak(scriptRoot), ) @@ -109,55 +125,66 @@ func AggregateKeys( func ValidateTreeSigs( scriptRoot []byte, - finalAggregatedKey *btcec.PublicKey, roundSharedOutputAmount int64, vtxoTree tree.VtxoTree, ) error { - prevoutFetcherFactory, err := prevOutFetcherFactory(finalAggregatedKey, vtxoTree, roundSharedOutputAmount) + prevoutFetcherFactory, err := prevOutFetcherFactory(vtxoTree, roundSharedOutputAmount, scriptRoot) if err != nil { return err } - for _, level := range vtxoTree { - for _, node := range level { - partialTx, err := psbt.NewFromRawBytes(strings.NewReader(node.Tx), true) - if err != nil { - return err - } + return workPoolMatrix(vtxoTree, func(_, _ int, node tree.Node) error { + partialTx, err := psbt.NewFromRawBytes(strings.NewReader(node.Tx), true) + if err != nil { + return fmt.Errorf("failed to parse tx: %w", err) + } - sig := partialTx.Inputs[0].TaprootKeySpendSig - if len(sig) == 0 { - return errors.New("unsigned tree input") - } + sig := partialTx.Inputs[0].TaprootKeySpendSig + if len(sig) == 0 { + return errors.New("unsigned tree input") + } - schnorrSig, err := schnorr.ParseSignature(sig) - if err != nil { - return err - } + schnorrSig, err := schnorr.ParseSignature(sig) + if err != nil { + return fmt.Errorf("failed to parse signature: %w", err) + } - prevoutFetcher, err := prevoutFetcherFactory(partialTx) - if err != nil { - return err - } + prevoutFetcher, err := prevoutFetcherFactory(partialTx) + if err != nil { + return fmt.Errorf("failed to get prevout fetcher: %w", err) + } - message, err := txscript.CalcTaprootSignatureHash( - txscript.NewTxSigHashes(partialTx.UnsignedTx, prevoutFetcher), - txscript.SigHashDefault, - partialTx.UnsignedTx, - 0, - prevoutFetcher, - ) - if err != nil { - return err - } + message, err := txscript.CalcTaprootSignatureHash( + txscript.NewTxSigHashes(partialTx.UnsignedTx, prevoutFetcher), + txscript.SigHashDefault, + partialTx.UnsignedTx, + 0, + prevoutFetcher, + ) + if err != nil { + return fmt.Errorf("failed to calculate sighash: %w", err) + } - if !schnorrSig.Verify(message, finalAggregatedKey) { - return errors.New("invalid signature") - } + keys, err := GetCosignerKeys(partialTx.Inputs[0]) + if err != nil { + return fmt.Errorf("failed to get cosigner keys: %w", err) } - } - return nil + if len(keys) == 0 { + return fmt.Errorf("no keys for txid %s", partialTx.UnsignedTx.TxHash().String()) + } + + aggregateKey, err := AggregateKeys(keys, scriptRoot) + if err != nil { + return fmt.Errorf("failed to aggregate keys: %w", err) + } + + if !schnorrSig.Verify(message, aggregateKey.FinalKey) { + return fmt.Errorf("invalid signature for txid %s", partialTx.UnsignedTx.TxHash().String()) + } + + return nil + }) } func NewTreeSignerSession( @@ -165,46 +192,88 @@ func NewTreeSignerSession( roundSharedOutputAmount int64, vtxoTree tree.VtxoTree, scriptRoot []byte, -) SignerSession { - return &treeSignerSession{ - secretKey: signer, - tree: vtxoTree, - scriptRoot: scriptRoot, - roundSharedOutputAmount: roundSharedOutputAmount, +) (SignerSession, error) { + prevOutFetcherFactory, err := prevOutFetcherFactory(vtxoTree, roundSharedOutputAmount, scriptRoot) + if err != nil { + return nil, err + } + + txs, err := vtxoTreeToTx(vtxoTree) + if err != nil { + return nil, err } + + return &treeSignerSession{ + secretKey: signer, + txs: txs, + scriptRoot: scriptRoot, + prevoutFetcherFactory: prevOutFetcherFactory, + }, nil } type treeSignerSession struct { - secretKey *btcec.PrivateKey - tree tree.VtxoTree - myNonces [][]*musig2.Nonces - keys []*btcec.PublicKey - aggregateNonces TreeNonces - scriptRoot []byte - roundSharedOutputAmount int64 - prevoutFetcherFactory func(*psbt.Packet) (txscript.PrevOutputFetcher, error) + secretKey *btcec.PrivateKey + txs [][]*psbt.Packet + myNonces [][]*musig2.Nonces + aggregateNonces TreeNonces + scriptRoot []byte + prevoutFetcherFactory func(*psbt.Packet) (txscript.PrevOutputFetcher, error) +} + +func (t *treeSignerSession) GetPublicKey() string { + return hex.EncodeToString(t.secretKey.PubKey().SerializeCompressed()) } func (t *treeSignerSession) generateNonces() error { - if t.tree == nil { + if len(t.txs) == 0 { return ErrMissingVtxoTree } - myNonces := make([][]*musig2.Nonces, 0) + signerPubKey := t.secretKey.PubKey() + serializedSignerPubKey := schnorr.SerializePubKey(signerPubKey) - for _, level := range t.tree { - levelNonces := make([]*musig2.Nonces, 0) - for range level { - nonce, err := musig2.GenNonces( - musig2.WithPublicKey(t.secretKey.PubKey()), - ) - if err != nil { - return err + // Pre-allocate the result matrix + myNonces := make([][]*musig2.Nonces, len(t.txs)) + for i := range myNonces { + myNonces[i] = make([]*musig2.Nonces, len(t.txs[i])) + } + + err := workPoolMatrix(t.txs, func(i, j int, partialTx *psbt.Packet) error { + keys, err := GetCosignerKeys(partialTx.Inputs[0]) + if err != nil { + return err + } + + if len(keys) == 0 { + return fmt.Errorf("no keys for txid %s", partialTx.UnsignedTx.TxHash().String()) + } + + mustSign := false + for _, key := range keys { + if bytes.Equal(schnorr.SerializePubKey(key), serializedSignerPubKey) { + mustSign = true + break } + } + + if !mustSign { + myNonces[i][j] = nil + return nil + } - levelNonces = append(levelNonces, nonce) + nonce, err := musig2.GenNonces( + musig2.WithPublicKey(signerPubKey), + ) + if err != nil { + return err } - myNonces = append(myNonces, levelNonces) + + myNonces[i][j] = nonce + return nil + }) + + if err != nil { + return err } t.myNonces = myNonces @@ -212,7 +281,7 @@ func (t *treeSignerSession) generateNonces() error { } func (t *treeSignerSession) GetNonces() (TreeNonces, error) { - if t.tree == nil { + if len(t.txs) == 0 { return nil, ErrMissingVtxoTree } @@ -227,6 +296,11 @@ func (t *treeSignerSession) GetNonces() (TreeNonces, error) { for _, level := range t.myNonces { levelNonces := make([]*Musig2Nonce, 0) for _, nonce := range level { + if nonce == nil { + levelNonces = append(levelNonces, nil) + continue + } + levelNonces = append(levelNonces, &Musig2Nonce{nonce.PubNonce}) } nonces = append(nonces, levelNonces) @@ -235,75 +309,72 @@ func (t *treeSignerSession) GetNonces() (TreeNonces, error) { return nonces, nil } -func (t *treeSignerSession) SetKeys(keys []*btcec.PublicKey) error { - if t.keys != nil { - return errors.New("keys already set") - } - - aggregateKey, err := AggregateKeys(keys, t.scriptRoot) - if err != nil { - return err - } - - factory, err := prevOutFetcherFactory(aggregateKey.FinalKey, t.tree, t.roundSharedOutputAmount) - if err != nil { - return err - } - - t.prevoutFetcherFactory = factory - t.keys = keys - - return nil -} - -func (t *treeSignerSession) SetAggregatedNonces(nonces TreeNonces) error { - if t.aggregateNonces != nil { - return errors.New("nonces already set") - } - +func (t *treeSignerSession) SetAggregatedNonces(nonces TreeNonces) { t.aggregateNonces = nonces - return nil } func (t *treeSignerSession) Sign() (TreePartialSigs, error) { - if t.tree == nil { + if len(t.txs) == 0 { return nil, ErrMissingVtxoTree } - if t.keys == nil { - return nil, ErrMissingAggregateKey - } - if t.aggregateNonces == nil { return nil, errors.New("nonces not set") } - sigs := make(TreePartialSigs, 0) + sigs := make(TreePartialSigs, len(t.txs)) + for i := range sigs { + sigs[i] = make([]*musig2.PartialSignature, len(t.txs[i])) + } - for i, level := range t.tree { - levelSigs := make([]*musig2.PartialSignature, 0) + signerPubKey := schnorr.SerializePubKey(t.secretKey.PubKey()) - for j, node := range level { - partialTx, err := psbt.NewFromRawBytes(strings.NewReader(node.Tx), true) - if err != nil { - return nil, err - } - // sign the node - sig, err := t.signPartial(partialTx, i, j, t.secretKey) - if err != nil { - return nil, err + if err := workPoolMatrix(t.txs, func(i, j int, partialTx *psbt.Packet) error { + keys, err := GetCosignerKeys(partialTx.Inputs[0]) + if err != nil { + return fmt.Errorf("failed to get cosigner keys: %w", err) + } + + if len(keys) == 0 { + return fmt.Errorf("no keys for txid %s", partialTx.UnsignedTx.TxHash().String()) + } + + // Check if the signer's key is in the list of keys + mustSign := false + for _, key := range keys { + if bytes.Equal(schnorr.SerializePubKey(key), signerPubKey) { + mustSign = true + break } + } - levelSigs = append(levelSigs, sig) + // Skip signing if not required + if !mustSign { + sigs[i][j] = nil + return nil } - sigs = append(sigs, levelSigs) + sig, err := t.signPartial(partialTx, i, j, t.secretKey, keys) + if err != nil { + return fmt.Errorf("failed to sign partial tx: %w", err) + } + + sigs[i][j] = sig + return nil + }); err != nil { + return nil, err } return sigs, nil } -func (t *treeSignerSession) signPartial(partialTx *psbt.Packet, posx int, posy int, seckey *btcec.PrivateKey) (*musig2.PartialSignature, error) { +func (t *treeSignerSession) signPartial( + partialTx *psbt.Packet, + posx int, + posy int, + seckey *btcec.PrivateKey, + keys []*btcec.PublicKey, +) (*musig2.PartialSignature, error) { prevoutFetcher, err := t.prevoutFetcherFactory(partialTx) if err != nil { return nil, err @@ -324,76 +395,51 @@ func (t *treeSignerSession) signPartial(partialTx *psbt.Packet, posx int, posy i } return musig2.Sign( - myNonce.SecNonce, seckey, aggregatedNonce.PubNonce, t.keys, [32]byte(message), - musig2.WithSortedKeys(), musig2.WithTaprootSignTweak(t.scriptRoot), + myNonce.SecNonce, seckey, aggregatedNonce.PubNonce, keys, [32]byte(message), + musig2.WithSortedKeys(), musig2.WithTaprootSignTweak(t.scriptRoot), musig2.WithFastSign(), ) } type treeCoordinatorSession struct { scriptRoot []byte - tree tree.VtxoTree - keys []*btcec.PublicKey - nonces []TreeNonces - sigs []TreePartialSigs + nonces map[string]TreeNonces // xonly pubkey -> nonces + sigs map[string]TreePartialSigs // xonly pubkey -> sigs prevoutFetcherFactory func(*psbt.Packet) (txscript.PrevOutputFetcher, error) + txs [][]*psbt.Packet + vtxoTree tree.VtxoTree } func NewTreeCoordinatorSession( roundSharedOutputAmount int64, vtxoTree tree.VtxoTree, scriptRoot []byte, - keys []*btcec.PublicKey, ) (CoordinatorSession, error) { - aggregateKey, err := AggregateKeys(keys, scriptRoot) + prevoutFetcherFactory, err := prevOutFetcherFactory(vtxoTree, roundSharedOutputAmount, scriptRoot) if err != nil { return nil, err } - prevoutFetcherFactory, err := prevOutFetcherFactory(aggregateKey.FinalKey, vtxoTree, roundSharedOutputAmount) + txs, err := vtxoTreeToTx(vtxoTree) if err != nil { return nil, err } - nbOfKeys := len(keys) - return &treeCoordinatorSession{ scriptRoot: scriptRoot, - tree: vtxoTree, - keys: keys, - nonces: make([]TreeNonces, nbOfKeys), - sigs: make([]TreePartialSigs, nbOfKeys), + txs: txs, + nonces: make(map[string]TreeNonces), + sigs: make(map[string]TreePartialSigs), prevoutFetcherFactory: prevoutFetcherFactory, + vtxoTree: vtxoTree, }, nil } -func (t *treeCoordinatorSession) getPubkeyIndex(pubkey *btcec.PublicKey) int { - for i, key := range t.keys { - if key.IsEqual(pubkey) { - return i - } - } - - return -1 -} - -func (t *treeCoordinatorSession) AddNonce(pubkey *btcec.PublicKey, nonce TreeNonces) error { - index := t.getPubkeyIndex(pubkey) - if index == -1 { - return errors.New("public key not found") - } - - t.nonces[index] = nonce - return nil +func (t *treeCoordinatorSession) AddNonce(pubkey *btcec.PublicKey, nonce TreeNonces) { + t.nonces[hex.EncodeToString(schnorr.SerializePubKey(pubkey))] = nonce } -func (t *treeCoordinatorSession) AddSig(pubkey *btcec.PublicKey, sig TreePartialSigs) error { - index := t.getPubkeyIndex(pubkey) - if index == -1 { - return errors.New("public key not found") - } - - t.sigs[index] = sig - return nil +func (t *treeCoordinatorSession) AddSig(pubkey *btcec.PublicKey, sig TreePartialSigs) { + t.sigs[hex.EncodeToString(schnorr.SerializePubKey(pubkey))] = sig } func (t *treeCoordinatorSession) AggregateNonces() (TreeNonces, error) { @@ -403,122 +449,154 @@ func (t *treeCoordinatorSession) AggregateNonces() (TreeNonces, error) { } } - aggregatedNonces := make(TreeNonces, 0) + aggregatedNonces := make(TreeNonces, len(t.txs)) + for i := range aggregatedNonces { + aggregatedNonces[i] = make([]*Musig2Nonce, len(t.txs[i])) + } - for i, level := range t.tree { - levelNonces := make([]*Musig2Nonce, 0) - for j := range level { - nonces := make([][66]byte, 0) - for _, n := range t.nonces { - nonces = append(nonces, n[i][j].PubNonce) + err := workPoolMatrix(t.txs, func(i, j int, partialTx *psbt.Packet) error { + keys, err := GetCosignerKeys(partialTx.Inputs[0]) + if err != nil { + return fmt.Errorf("failed to get cosigner keys: %w", err) + } + + if len(keys) == 0 { + return fmt.Errorf("no keys for txid %s", partialTx.UnsignedTx.TxHash().String()) + } + + nonces := make([][66]byte, 0, len(keys)) + + for _, key := range keys { + keyStr := hex.EncodeToString(schnorr.SerializePubKey(key)) + nonceMatrix, ok := t.nonces[keyStr] + if !ok { + return fmt.Errorf("nonces not set for cosigner key %x", key.SerializeCompressed()) } - aggregatedNonce, err := musig2.AggregateNonces(nonces) - if err != nil { - return nil, err + nonce := nonceMatrix[i][j] + if nonce == nil { + return fmt.Errorf("missing nonce for cosigner key %x", key.SerializeCompressed()) } - levelNonces = append(levelNonces, &Musig2Nonce{aggregatedNonce}) + nonces = append(nonces, nonce.PubNonce) } - aggregatedNonces = append(aggregatedNonces, levelNonces) + aggregatedNonce, err := musig2.AggregateNonces(nonces) + if err != nil { + return fmt.Errorf("failed to aggregate nonces: %w", err) + } + + aggregatedNonces[i][j] = &Musig2Nonce{aggregatedNonce} + return nil + }) + + if err != nil { + return nil, err } return aggregatedNonces, nil } -// SignTree implements CoordinatorSession. func (t *treeCoordinatorSession) SignTree() (tree.VtxoTree, error) { - var missingSigs int - for _, sig := range t.sigs { - if sig == nil { - missingSigs++ - } + signedTree := make(tree.VtxoTree, len(t.txs)) + for i := range signedTree { + signedTree[i] = make([]tree.Node, len(t.txs[i])) } - if missingSigs > 0 { - return nil, fmt.Errorf("missing %d signature(s)", missingSigs) - } + if err := workPoolMatrix(t.txs, func(i, j int, partialTx *psbt.Packet) error { + keys, err := GetCosignerKeys(partialTx.Inputs[0]) + if err != nil { + return err + } - aggregatedKey, err := AggregateKeys(t.keys, t.scriptRoot) - if err != nil { - return nil, err - } + if len(keys) == 0 { + return fmt.Errorf("no keys for txid %s", partialTx.UnsignedTx.TxHash().String()) + } - for i, level := range t.tree { - for j, node := range level { - partialTx, err := psbt.NewFromRawBytes(strings.NewReader(node.Tx), true) - if err != nil { - return nil, err - } + var combinedNonce *secp256k1.PublicKey + sigs := make([]*musig2.PartialSignature, 0, len(keys)) - var combinedNonce *secp256k1.PublicKey - sigs := make([]*musig2.PartialSignature, 0) - for _, sig := range t.sigs { - s := sig[i][j] - if s.R != nil { - combinedNonce = s.R - } - sigs = append(sigs, s) + for _, key := range keys { + sigMatrix, ok := t.sigs[hex.EncodeToString(schnorr.SerializePubKey(key))] + if !ok { + return fmt.Errorf("sigs not set for cosigner key %x", key.SerializeCompressed()) } - if combinedNonce == nil { - return nil, errors.New("missing combined nonce") + s := sigMatrix[i][j] + if s == nil { + return fmt.Errorf("missing signature for cosigner key %x", key.SerializeCompressed()) } - prevoutFetcher, err := t.prevoutFetcherFactory(partialTx) - if err != nil { - return nil, err + if s.R != nil { + combinedNonce = s.R } + sigs = append(sigs, s) + } - message, err := txscript.CalcTaprootSignatureHash( - txscript.NewTxSigHashes(partialTx.UnsignedTx, prevoutFetcher), - txscript.SigHashDefault, - partialTx.UnsignedTx, - 0, - prevoutFetcher, - ) - - combinedSig := musig2.CombineSigs( - combinedNonce, sigs, - musig2.WithTaprootTweakedCombine([32]byte(message), t.keys, t.scriptRoot, true), - ) - if err != nil { - return nil, err - } + if combinedNonce == nil { + return fmt.Errorf("missing combined nonce for txid %s", partialTx.UnsignedTx.TxHash().String()) + } - if !combinedSig.Verify(message, aggregatedKey.FinalKey) { - return nil, errors.New("invalid signature") - } + prevoutFetcher, err := t.prevoutFetcherFactory(partialTx) + if err != nil { + return err + } - partialTx.Inputs[0].TaprootKeySpendSig = combinedSig.Serialize() + message, err := txscript.CalcTaprootSignatureHash( + txscript.NewTxSigHashes(partialTx.UnsignedTx, prevoutFetcher), + txscript.SigHashDefault, + partialTx.UnsignedTx, + 0, + prevoutFetcher, + ) + if err != nil { + return err + } - encodedSignedTx, err := partialTx.B64Encode() - if err != nil { - return nil, err - } + combinedSig := musig2.CombineSigs( + combinedNonce, sigs, + musig2.WithTaprootTweakedCombine([32]byte(message), keys, t.scriptRoot, true), + ) - node.Tx = encodedSignedTx - t.tree[i][j] = node + aggregatedKey, err := AggregateKeys(keys, t.scriptRoot) + if err != nil { + return err + } + + if !combinedSig.Verify(message, aggregatedKey.FinalKey) { + return fmt.Errorf("invalid signature for cosigner key %x, txid %s", keys[0].SerializeCompressed(), partialTx.UnsignedTx.TxHash().String()) + } + + partialTx.Inputs[0].TaprootKeySpendSig = combinedSig.Serialize() + + encodedSignedTx, err := partialTx.B64Encode() + if err != nil { + return err } + + signedTree[i][j] = tree.Node{ + Txid: t.vtxoTree[i][j].Txid, + Tx: encodedSignedTx, + ParentTxid: t.vtxoTree[i][j].ParentTxid, + Leaf: t.vtxoTree[i][j].Leaf, + } + + return nil + }); err != nil { + return nil, err } - return t.tree, nil + return signedTree, nil } func prevOutFetcherFactory( - finalAggregatedKey *btcec.PublicKey, vtxoTree tree.VtxoTree, roundSharedOutputAmount int64, + scriptRoot []byte, ) ( func(partial *psbt.Packet) (txscript.PrevOutputFetcher, error), error, ) { - pkscript, err := common.P2TRScript(finalAggregatedKey) - if err != nil { - return nil, err - } - rootNode, err := vtxoTree.Root() if err != nil { return nil, err @@ -528,6 +606,25 @@ func prevOutFetcherFactory( parentOutpoint := partial.UnsignedTx.TxIn[0].PreviousOutPoint parentTxID := parentOutpoint.Hash.String() if rootNode.ParentTxid == parentTxID { + keys, err := GetCosignerKeys(partial.Inputs[0]) + if err != nil { + return nil, err + } + + if len(keys) == 0 { + return nil, fmt.Errorf("no keys for txid %s", partial.UnsignedTx.TxHash().String()) + } + + aggregateKey, err := AggregateKeys(keys, scriptRoot) + if err != nil { + return nil, err + } + + pkscript, err := common.P2TRScript(aggregateKey.FinalKey) + if err != nil { + return nil, err + } + return &treePrevOutFetcher{ prevout: &wire.TxOut{ Value: roundSharedOutputAmount, @@ -555,13 +652,8 @@ func prevOutFetcherFactory( return nil, err } - parentValue := parentTx.UnsignedTx.TxOut[parentOutpoint.Index].Value - return &treePrevOutFetcher{ - prevout: &wire.TxOut{ - Value: parentValue, - PkScript: pkscript, - }, + prevout: parentTx.UnsignedTx.TxOut[parentOutpoint.Index], }, nil }, nil } @@ -641,3 +733,93 @@ func decodeMatrix[T readable](factory func() T, data io.Reader) ([][]T, error) { return matrix, nil } + +func vtxoTreeToTx(vtxoTree tree.VtxoTree) ([][]*psbt.Packet, error) { + txs := make([][]*psbt.Packet, 0) + + for _, level := range vtxoTree { + levelTxs := make([]*psbt.Packet, 0) + for _, node := range level { + ptx, err := psbt.NewFromRawBytes(strings.NewReader(node.Tx), true) + if err != nil { + return nil, err + } + + levelTxs = append(levelTxs, ptx) + } + + txs = append(txs, levelTxs) + } + + return txs, nil +} + +// workPool is a generic worker pool that processes items concurrently +func workPool[T any](items []T, workers int, processItem func(item T) error) error { + errChan := make(chan error, 1) + workChan := make(chan T) + + var wg sync.WaitGroup + wg.Add(workers) + + // launch workers + for w := 0; w < workers; w++ { + go func() { + defer wg.Done() + for item := range workChan { + if err := processItem(item); err != nil { + select { + case errChan <- err: + default: + } + return + } + } + }() + } + + // distribute tasks + go func() { + for _, item := range items { + select { + case err := <-errChan: + close(workChan) + errChan <- err + return + default: + workChan <- item + } + } + close(workChan) + }() + + // wait for all workers to finish + wg.Wait() + + select { + case err := <-errChan: + return err + default: + return nil + } +} + +// workPoolMatrix is a specialized version of workPool for processing 2D matrices +func workPoolMatrix[T any](matrix [][]T, processItem func(i, j int, item T) error) error { + type workItem struct { + i, j int + item T + } + + // for each item in the matrix, create a work task + items := make([]workItem, 0, len(matrix)*len(matrix[0])) + for i, row := range matrix { + for j, item := range row { + items = append(items, workItem{i: i, j: j, item: item}) + } + } + + return workPool(items, runtime.NumCPU(), func(item workItem) error { + return processItem(item.i, item.j, item.item) + }) +} diff --git a/common/bitcointree/musig2_test.go b/common/bitcointree/musig2_test.go index be040b3e3..7f60f6814 100644 --- a/common/bitcointree/musig2_test.go +++ b/common/bitcointree/musig2_test.go @@ -1,14 +1,15 @@ package bitcointree_test import ( + "encoding/hex" "encoding/json" + "fmt" "os" "testing" "github.com/ark-network/ark/common" "github.com/ark-network/ark/common/bitcointree" "github.com/ark-network/ark/common/tree" - "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" @@ -26,110 +27,106 @@ var lifetime = common.RelativeLocktime{Type: common.LocktimeTypeBlock, Value: 14 var testTxid, _ = chainhash.NewHashFromStr("49f8664acc899be91902f8ade781b7eeb9cbe22bdd9efbc36e56195de21bcd12") func TestRoundTripSignTree(t *testing.T) { + t.Parallel() fixtures := parseFixtures(t) - for _, f := range fixtures.Valid { - // Generate 20 cosigners - cosigners := make([]*secp256k1.PrivateKey, 20) - cosignerPubkeys := make([]*btcec.PublicKey, 20) - for i := 0; i < 20; i++ { - prvkey, err := secp256k1.GeneratePrivateKey() + for i, f := range fixtures.Valid { + t.Run(fmt.Sprintf("test %d", i), func(t *testing.T) { + server, err := secp256k1.GeneratePrivateKey() require.NoError(t, err) - cosigners[i] = prvkey - cosignerPubkeys[i] = prvkey.PubKey() - } - - server, err := secp256k1.GeneratePrivateKey() - require.NoError(t, err) - - _, sharedOutputAmount, err := bitcointree.CraftSharedOutput( - cosignerPubkeys, - server.PubKey(), - castReceivers(f.Receivers), - minRelayFee, - lifetime, - ) - require.NoError(t, err) - - vtxoTree, err := bitcointree.BuildVtxoTree( - &wire.OutPoint{ - Hash: *testTxid, - Index: 0, - }, - cosignerPubkeys, - server.PubKey(), - castReceivers(f.Receivers), - minRelayFee, - lifetime, - ) - require.NoError(t, err) - - sweepClosure := &tree.CSVMultisigClosure{ - MultisigClosure: tree.MultisigClosure{PubKeys: []*secp256k1.PublicKey{server.PubKey()}}, - Locktime: lifetime, - } - - sweepScript, err := sweepClosure.Script() - require.NoError(t, err) - - sweepTapLeaf := txscript.NewBaseTapLeaf(sweepScript) - sweepTapTree := txscript.AssembleTaprootScriptTree(sweepTapLeaf) - root := sweepTapTree.RootNode.TapHash() - - serverCoordinator, err := bitcointree.NewTreeCoordinatorSession( - sharedOutputAmount, - vtxoTree, - root.CloneBytes(), - cosignerPubkeys, - ) - require.NoError(t, err) - - // Create signer sessions for all cosigners - signerSessions := make([]bitcointree.SignerSession, 20) - for i, cosigner := range cosigners { - signerSessions[i] = bitcointree.NewTreeSignerSession(cosigner, sharedOutputAmount, vtxoTree, root.CloneBytes()) - } - - // Get nonces from all signers - for i, session := range signerSessions { - nonces, err := session.GetNonces() + + sweepScript, err := (&tree.CSVMultisigClosure{ + MultisigClosure: tree.MultisigClosure{PubKeys: []*secp256k1.PublicKey{server.PubKey()}}, + Locktime: lifetime, + }).Script() require.NoError(t, err) - err = serverCoordinator.AddNonce(cosignerPubkeys[i], nonces) + + sweepTapLeaf := txscript.NewBaseTapLeaf(sweepScript) + sweepRoot := sweepTapLeaf.TapHash() + + receivers := make([]tree.VtxoLeaf, 0, len(f.Receivers)) + + privKeys := make([]*secp256k1.PrivateKey, 0, len(receivers)) + for i, r := range castReceivers(f.Receivers) { + receiver := r + prvkey, err := secp256k1.GeneratePrivateKey() + require.NoError(t, err) + privKeys = append(privKeys, prvkey) + + receiver.SignersPublicKeys = []string{ + hex.EncodeToString(prvkey.PubKey().SerializeCompressed()), + } + if i%2 == 0 { + receiver.Type = tree.SignAll + } else { + receiver.Type = tree.SignBranch + } + receivers = append(receivers, receiver) + } + + _, sharedOutputAmount, err := bitcointree.CraftSharedOutput( + receivers, + minRelayFee, + sweepRoot[:], + ) require.NoError(t, err) - } - aggregatedNonce, err := serverCoordinator.AggregateNonces() - require.NoError(t, err) + vtxoTree, err := bitcointree.BuildVtxoTree( + &wire.OutPoint{ + Hash: *testTxid, + Index: 0, + }, + receivers, + minRelayFee, + sweepRoot[:], + ) + require.NoError(t, err) - // Set keys and aggregated nonces for all signers - for _, session := range signerSessions { - err = session.SetKeys(cosignerPubkeys) + serverCoordinator, err := bitcointree.NewTreeCoordinatorSession( + sharedOutputAmount, + vtxoTree, + sweepRoot[:], + ) require.NoError(t, err) - err = session.SetAggregatedNonces(aggregatedNonce) + + // Create signer sessions for all cosigners + signerSessions := make([]bitcointree.SignerSession, len(receivers)) + for i, prvkey := range privKeys { + signerSessions[i], err = bitcointree.NewTreeSignerSession(prvkey, sharedOutputAmount, vtxoTree, sweepRoot[:]) + require.NoError(t, err) + } + + // Get nonces from all signers + for i, session := range signerSessions { + nonces, err := session.GetNonces() + require.NoError(t, err) + serverCoordinator.AddNonce(privKeys[i].PubKey(), nonces) + } + + aggregatedNonce, err := serverCoordinator.AggregateNonces() require.NoError(t, err) - } - // Get signatures from all signers - for i, session := range signerSessions { - sig, err := session.Sign() + // Set keys and aggregated nonces for all signers + for _, session := range signerSessions { + session.SetAggregatedNonces(aggregatedNonce) + } + + // Get signatures from all signers + for i, session := range signerSessions { + sig, err := session.Sign() + require.NoError(t, err) + serverCoordinator.AddSig(privKeys[i].PubKey(), sig) + } + + signedTree, err := serverCoordinator.SignTree() require.NoError(t, err) - err = serverCoordinator.AddSig(cosignerPubkeys[i], sig) + + err = bitcointree.ValidateTreeSigs( + sweepRoot[:], + sharedOutputAmount, + signedTree, + ) require.NoError(t, err) - } - - signedTree, err := serverCoordinator.SignTree() - require.NoError(t, err) - - // verify the tree - aggregatedKey, err := bitcointree.AggregateKeys(cosignerPubkeys, root.CloneBytes()) - require.NoError(t, err) - - err = bitcointree.ValidateTreeSigs( - root.CloneBytes(), - aggregatedKey.FinalKey, - sharedOutputAmount, - signedTree, - ) - require.NoError(t, err) + }) } } diff --git a/common/tree/type.go b/common/tree/type.go index 68d90c2ce..1ab753a60 100644 --- a/common/tree/type.go +++ b/common/tree/type.go @@ -4,9 +4,20 @@ import ( "github.com/vulpemventures/go-elements/psetv2" ) +type SigningType uint8 + +const ( + // SignAll makes the signer sign all the branches + SignAll SigningType = iota + // SignBranch makes the signer sign only its own branch + SignBranch +) + type TreeFactory func(outpoint psetv2.InputArgs) (VtxoTree, error) type VtxoLeaf struct { - PubKey string - Amount uint64 + PubKey string + Amount uint64 + Type SigningType + SignersPublicKeys []string } diff --git a/pkg/client-sdk/ark_sdk.go b/pkg/client-sdk/ark_sdk.go index 07b26780e..0b6fa45e5 100644 --- a/pkg/client-sdk/ark_sdk.go +++ b/pkg/client-sdk/ark_sdk.go @@ -7,6 +7,8 @@ import ( "github.com/ark-network/ark/pkg/client-sdk/types" ) +type Option func(options interface{}) error + type ArkClient interface { GetConfigData(ctx context.Context) (*types.Config, error) Init(ctx context.Context, args InitArgs) error @@ -23,13 +25,14 @@ type ArkClient interface { UnilateralRedeem(ctx context.Context) error CollaborativeRedeem( ctx context.Context, addr string, amount uint64, withExpiryCoinselect bool, + opts ...Option, ) (string, error) - Settle(ctx context.Context) (string, error) + Settle(ctx context.Context, opts ...Option) (string, error) ListVtxos(ctx context.Context) (spendable, spent []client.Vtxo, err error) Dump(ctx context.Context) (seed string, err error) GetTransactionHistory(ctx context.Context) ([]types.Transaction, error) GetTransactionEventChannel() chan types.TransactionEvent - RedeemNotes(ctx context.Context, notes []string) (string, error) + RedeemNotes(ctx context.Context, notes []string, opts ...Option) (string, error) SetNostrNotificationRecipient(ctx context.Context, nostrRecipient string) error SignTransaction(ctx context.Context, tx string) (string, error) Stop() error diff --git a/pkg/client-sdk/client/client.go b/pkg/client-sdk/client/client.go index 93573cd64..27bc67c6b 100644 --- a/pkg/client-sdk/client/client.go +++ b/pkg/client-sdk/client/client.go @@ -25,10 +25,10 @@ type RoundEvent interface { type TransportClient interface { GetInfo(ctx context.Context) (*Info, error) RegisterInputsForNextRound( - ctx context.Context, inputs []Input, ephemeralKey string, + ctx context.Context, inputs []Input, signerPubKeys []string, signingType tree.SigningType, ) (string, error) RegisterNotesForNextRound( - ctx context.Context, notes []string, ephemeralKey string, + ctx context.Context, notes []string, signerPubKeys []string, signingType tree.SigningType, ) (string, error) RegisterOutputsForNextRound( ctx context.Context, requestID string, outputs []Output, @@ -191,10 +191,9 @@ type RoundFailedEvent struct { func (e RoundFailedEvent) isRoundEvent() {} type RoundSigningStartedEvent struct { - ID string - UnsignedTree tree.VtxoTree - CosignersPubKeys []*secp256k1.PublicKey - UnsignedRoundTx string + ID string + UnsignedTree tree.VtxoTree + UnsignedRoundTx string } func (e RoundSigningStartedEvent) isRoundEvent() {} diff --git a/pkg/client-sdk/client/grpc/client.go b/pkg/client-sdk/client/grpc/client.go index 2ce588591..c9005e035 100644 --- a/pkg/client-sdk/client/grpc/client.go +++ b/pkg/client-sdk/client/grpc/client.go @@ -85,13 +85,14 @@ func (a *grpcClient) GetBoardingAddress( } func (a *grpcClient) RegisterInputsForNextRound( - ctx context.Context, inputs []client.Input, ephemeralPubkey string, + ctx context.Context, inputs []client.Input, signerPubKeys []string, signingType tree.SigningType, ) (string, error) { req := &arkv1.RegisterInputsForNextRoundRequest{ Inputs: ins(inputs).toProto(), } - if len(ephemeralPubkey) > 0 { - req.EphemeralPubkey = &ephemeralPubkey + if len(signerPubKeys) > 0 { + req.SignerPubkeys = signerPubKeys + req.SigningType = uint32(signingType) } resp, err := a.svc.RegisterInputsForNextRound(ctx, req) @@ -102,13 +103,14 @@ func (a *grpcClient) RegisterInputsForNextRound( } func (a *grpcClient) RegisterNotesForNextRound( - ctx context.Context, notes []string, ephemeralKey string, + ctx context.Context, notes []string, signerPubKeys []string, signingType tree.SigningType, ) (string, error) { req := &arkv1.RegisterInputsForNextRoundRequest{ Notes: notes, } - if len(ephemeralKey) > 0 { - req.EphemeralPubkey = &ephemeralKey + if len(signerPubKeys) > 0 { + req.SignerPubkeys = signerPubKeys + req.SigningType = uint32(signingType) } resp, err := a.svc.RegisterInputsForNextRound(ctx, req) if err != nil { diff --git a/pkg/client-sdk/client/grpc/types.go b/pkg/client-sdk/client/grpc/types.go index 49e955298..ab4d6a6e8 100644 --- a/pkg/client-sdk/client/grpc/types.go +++ b/pkg/client-sdk/client/grpc/types.go @@ -10,7 +10,6 @@ import ( "github.com/ark-network/ark/common/bitcointree" "github.com/ark-network/ark/common/tree" "github.com/ark-network/ark/pkg/client-sdk/client" - "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/lightningnetwork/lnd/lnwallet/chainfee" ) @@ -72,24 +71,10 @@ func (e event) toRoundEvent() (client.RoundEvent, error) { } if ee := e.GetRoundSigning(); ee != nil { - pubkeys := make([]*secp256k1.PublicKey, 0, len(ee.GetCosignersPubkeys())) - for _, pubkey := range ee.GetCosignersPubkeys() { - p, err := hex.DecodeString(pubkey) - if err != nil { - return nil, err - } - pk, err := secp256k1.ParsePubKey(p) - if err != nil { - return nil, err - } - pubkeys = append(pubkeys, pk) - } - return client.RoundSigningStartedEvent{ - ID: ee.GetId(), - UnsignedTree: treeFromProto{ee.GetUnsignedVtxoTree()}.parse(), - CosignersPubKeys: pubkeys, - UnsignedRoundTx: ee.GetUnsignedRoundTx(), + ID: ee.GetId(), + UnsignedTree: treeFromProto{ee.GetUnsignedVtxoTree()}.parse(), + UnsignedRoundTx: ee.GetUnsignedRoundTx(), }, nil } diff --git a/pkg/client-sdk/client/rest/client.go b/pkg/client-sdk/client/rest/client.go index 656e2e2be..fff3853cc 100644 --- a/pkg/client-sdk/client/rest/client.go +++ b/pkg/client-sdk/client/rest/client.go @@ -21,7 +21,6 @@ import ( "github.com/ark-network/ark/pkg/client-sdk/client/rest/service/arkservice/ark_service" "github.com/ark-network/ark/pkg/client-sdk/client/rest/service/models" "github.com/ark-network/ark/pkg/client-sdk/internal/utils" - "github.com/decred/dcrd/dcrec/secp256k1/v4" httptransport "github.com/go-openapi/runtime/client" "github.com/go-openapi/strfmt" "github.com/lightningnetwork/lnd/lnwallet/chainfee" @@ -108,7 +107,7 @@ func (a *restClient) GetBoardingAddress( } func (a *restClient) RegisterInputsForNextRound( - ctx context.Context, inputs []client.Input, ephemeralPubkey string, + ctx context.Context, inputs []client.Input, signerPubKeys []string, signingType tree.SigningType, ) (string, error) { ins := make([]*models.V1Input, 0, len(inputs)) for _, i := range inputs { @@ -125,8 +124,9 @@ func (a *restClient) RegisterInputsForNextRound( body := &models.V1RegisterInputsForNextRoundRequest{ Inputs: ins, } - if len(ephemeralPubkey) > 0 { - body.EphemeralPubkey = ephemeralPubkey + if len(signerPubKeys) > 0 { + body.SignerPubkeys = signerPubKeys + body.SigningType = int64(signingType) } resp, err := a.svc.ArkServiceRegisterInputsForNextRound( @@ -140,13 +140,14 @@ func (a *restClient) RegisterInputsForNextRound( } func (a *restClient) RegisterNotesForNextRound( - ctx context.Context, notes []string, ephemeralKey string, + ctx context.Context, notes []string, signerPubKeys []string, signingType tree.SigningType, ) (string, error) { body := &models.V1RegisterInputsForNextRoundRequest{ Notes: notes, } - if len(ephemeralKey) > 0 { - body.EphemeralPubkey = ephemeralKey + if len(signerPubKeys) > 0 { + body.SignerPubkeys = signerPubKeys + body.SigningType = int64(signingType) } resp, err := a.svc.ArkServiceRegisterInputsForNextRound( ark_service.NewArkServiceRegisterInputsForNextRoundParams().WithBody(body), @@ -338,26 +339,10 @@ func (c *restClient) GetEventStream( } case resp.Result.RoundSigning != nil: e := resp.Result.RoundSigning - pubkeys := make([]*secp256k1.PublicKey, 0, len(e.CosignersPubkeys)) - for _, pubkey := range e.CosignersPubkeys { - p, err := hex.DecodeString(pubkey) - if err != nil { - _err = err - break - } - pk, err := secp256k1.ParsePubKey(p) - if err != nil { - _err = err - break - } - pubkeys = append(pubkeys, pk) - } - event = client.RoundSigningStartedEvent{ - ID: e.ID, - UnsignedTree: treeFromProto{e.UnsignedVtxoTree}.parse(), - CosignersPubKeys: pubkeys, - UnsignedRoundTx: e.UnsignedRoundTx, + ID: e.ID, + UnsignedTree: treeFromProto{e.UnsignedVtxoTree}.parse(), + UnsignedRoundTx: e.UnsignedRoundTx, } case resp.Result.RoundSigningNoncesGenerated != nil: e := resp.Result.RoundSigningNoncesGenerated diff --git a/pkg/client-sdk/client/rest/service/models/v1_register_inputs_for_next_round_request.go b/pkg/client-sdk/client/rest/service/models/v1_register_inputs_for_next_round_request.go index 00b5200a6..afb534394 100644 --- a/pkg/client-sdk/client/rest/service/models/v1_register_inputs_for_next_round_request.go +++ b/pkg/client-sdk/client/rest/service/models/v1_register_inputs_for_next_round_request.go @@ -19,14 +19,17 @@ import ( // swagger:model v1RegisterInputsForNextRoundRequest type V1RegisterInputsForNextRoundRequest struct { - // ephemeral pubkey - EphemeralPubkey string `json:"ephemeralPubkey,omitempty"` - // inputs Inputs []*V1Input `json:"inputs"` // notes Notes []string `json:"notes"` + + // signer pubkeys + SignerPubkeys []string `json:"signerPubkeys"` + + // signing type + SigningType int64 `json:"signingType,omitempty"` } // Validate validates this v1 register inputs for next round request diff --git a/pkg/client-sdk/client/rest/service/models/v1_round_signing_event.go b/pkg/client-sdk/client/rest/service/models/v1_round_signing_event.go index 3fb052fae..cde59f8aa 100644 --- a/pkg/client-sdk/client/rest/service/models/v1_round_signing_event.go +++ b/pkg/client-sdk/client/rest/service/models/v1_round_signing_event.go @@ -18,9 +18,6 @@ import ( // swagger:model v1RoundSigningEvent type V1RoundSigningEvent struct { - // cosigners pubkeys - CosignersPubkeys []string `json:"cosignersPubkeys"` - // id ID string `json:"id,omitempty"` diff --git a/pkg/client-sdk/covenant_client.go b/pkg/client-sdk/covenant_client.go index ec2893dfc..8d24f00f4 100644 --- a/pkg/client-sdk/covenant_client.go +++ b/pkg/client-sdk/covenant_client.go @@ -211,7 +211,7 @@ func (a *covenantArkClient) InitWithWallet(ctx context.Context, args InitWithWal return nil } -func (a *covenantArkClient) RedeemNotes(ctx context.Context, notes []string) (string, error) { +func (a *covenantArkClient) RedeemNotes(_ context.Context, _ []string, _ ...Option) (string, error) { return "", fmt.Errorf("not implemented") } @@ -492,6 +492,7 @@ func (a *covenantArkClient) UnilateralRedeem(ctx context.Context) error { func (a *covenantArkClient) CollaborativeRedeem( ctx context.Context, addr string, amount uint64, withExpiryCoinselect bool, + opts ...Option, ) (string, error) { if a.wallet.IsLocked() { return "", fmt.Errorf("wallet is locked") @@ -585,7 +586,7 @@ func (a *covenantArkClient) CollaborativeRedeem( }) } - requestID, err := a.client.RegisterInputsForNextRound(ctx, inputs, "") + requestID, err := a.client.RegisterInputsForNextRound(ctx, inputs, nil, 0) if err != nil { return "", err } @@ -604,6 +605,7 @@ func (a *covenantArkClient) CollaborativeRedeem( func (a *covenantArkClient) Settle( ctx context.Context, + _ ...Option, // no options for covenant ) (string, error) { return a.sendOffchain(ctx, false, nil) } @@ -1012,7 +1014,7 @@ func (a *covenantArkClient) sendOffchain( }) } - requestID, err := a.client.RegisterInputsForNextRound(ctx, inputs, "") + requestID, err := a.client.RegisterInputsForNextRound(ctx, inputs, nil, 0) if err != nil { return "", err } diff --git a/pkg/client-sdk/covenantless_client.go b/pkg/client-sdk/covenantless_client.go index d60049084..1bf0ef9af 100644 --- a/pkg/client-sdk/covenantless_client.go +++ b/pkg/client-sdk/covenantless_client.go @@ -34,6 +34,42 @@ import ( log "github.com/sirupsen/logrus" ) +// SettleOptions are only available for covenantless clients +// it allows to customize the vtxo signing process +type SettleOptions struct { + CustomSignerPrivKeys []*secp256k1.PrivateKey + SigningType *tree.SigningType +} + +// WithSignAll sets the signing type to ALL instead of the default BRANCH +func WithSignAll(o interface{}) error { + opts, ok := o.(*SettleOptions) + if !ok { + return fmt.Errorf("invalid options type") + } + + t := tree.SignAll + opts.SigningType = &t + return nil +} + +// WithCustomTreeSigner allows to use a set of custom signer for the vtxo tree signing process +func WithCustomTreeSigner(privKeys []*secp256k1.PrivateKey) Option { + return func(o interface{}) error { + opts, ok := o.(*SettleOptions) + if !ok { + return fmt.Errorf("invalid options type") + } + + if len(privKeys) == 0 { + return fmt.Errorf("no private keys provided") + } + + opts.CustomSignerPrivKeys = privKeys + return nil + } +} + type bitcoinReceiver struct { to string amount uint64 @@ -830,9 +866,16 @@ func (a *covenantlessArkClient) SendOffChain( return signedRedeemTx, nil } -func (a *covenantlessArkClient) RedeemNotes(ctx context.Context, notes []string) (string, error) { +func (a *covenantlessArkClient) RedeemNotes(ctx context.Context, notes []string, opts ...Option) (string, error) { amount := uint64(0) + options := &SettleOptions{} + for _, opt := range opts { + if err := opt(options); err != nil { + return "", err + } + } + for _, vStr := range notes { v, err := note.NewFromString(vStr) if err != nil { @@ -849,13 +892,13 @@ func (a *covenantlessArkClient) RedeemNotes(ctx context.Context, notes []string) return "", fmt.Errorf("no funds detected") } - roundEphemeralKey, err := secp256k1.GeneratePrivateKey() + signerPrivKeys, signerPubKeys, signingType, err := handleOptions(options) if err != nil { return "", err } requestID, err := a.client.RegisterNotesForNextRound( - ctx, notes, hex.EncodeToString(roundEphemeralKey.PubKey().SerializeCompressed()), + ctx, notes, signerPubKeys, signingType, ) if err != nil { return "", err @@ -877,7 +920,7 @@ func (a *covenantlessArkClient) RedeemNotes(ctx context.Context, notes []string) log.Infof("payout registered with id: %s", requestID) roundTxID, err := a.handleRoundStream( - ctx, requestID, nil, nil, receiversOutput, roundEphemeralKey, + ctx, requestID, nil, nil, receiversOutput, signerPrivKeys, ) if err != nil { return "", err @@ -948,7 +991,15 @@ func (a *covenantlessArkClient) UnilateralRedeem(ctx context.Context) error { func (a *covenantlessArkClient) CollaborativeRedeem( ctx context.Context, addr string, amount uint64, withExpiryCoinselect bool, + opts ...Option, ) (string, error) { + options := &SettleOptions{} + for _, opt := range opts { + if err := opt(options); err != nil { + return "", err + } + } + if a.wallet.IsLocked() { return "", fmt.Errorf("wallet is locked") } @@ -1037,7 +1088,7 @@ func (a *covenantlessArkClient) CollaborativeRedeem( }) } - roundEphemeralKey, err := secp256k1.GeneratePrivateKey() + signerPrivKeys, signerPubKeys, signingType, err := handleOptions(options) if err != nil { return "", err } @@ -1045,7 +1096,8 @@ func (a *covenantlessArkClient) CollaborativeRedeem( requestID, err := a.client.RegisterInputsForNextRound( ctx, inputs, - hex.EncodeToString(roundEphemeralKey.PubKey().SerializeCompressed()), + signerPubKeys, + signingType, ) if err != nil { return "", err @@ -1056,7 +1108,7 @@ func (a *covenantlessArkClient) CollaborativeRedeem( } roundTxID, err := a.handleRoundStream( - ctx, requestID, selectedCoins, selectedBoardingCoins, receivers, roundEphemeralKey, + ctx, requestID, selectedCoins, selectedBoardingCoins, receivers, signerPrivKeys, ) if err != nil { return "", err @@ -1065,8 +1117,8 @@ func (a *covenantlessArkClient) CollaborativeRedeem( return roundTxID, nil } -func (a *covenantlessArkClient) Settle(ctx context.Context) (string, error) { - return a.sendOffchain(ctx, false, nil) +func (a *covenantlessArkClient) Settle(ctx context.Context, opts ...Option) (string, error) { + return a.sendOffchain(ctx, false, nil, opts...) } func (a *covenantlessArkClient) GetTransactionHistory( @@ -1344,7 +1396,16 @@ func (a *covenantlessArkClient) sendOnchain( func (a *covenantlessArkClient) sendOffchain( ctx context.Context, withExpiryCoinselect bool, receivers []Receiver, + settleOpts ...Option, ) (string, error) { + + options := &SettleOptions{} + for _, opt := range settleOpts { + if err := opt(options); err != nil { + return "", err + } + } + if a.wallet.IsLocked() { return "", fmt.Errorf("wallet is locked") } @@ -1477,13 +1538,13 @@ func (a *covenantlessArkClient) sendOffchain( }) } - roundEphemeralKey, err := secp256k1.GeneratePrivateKey() + signerPrivKeys, signerPubKeys, signingType, err := handleOptions(options) if err != nil { return "", err } requestID, err := a.client.RegisterInputsForNextRound( - ctx, inputs, hex.EncodeToString(roundEphemeralKey.PubKey().SerializeCompressed()), + ctx, inputs, signerPubKeys, signingType, ) if err != nil { return "", err @@ -1498,7 +1559,7 @@ func (a *covenantlessArkClient) sendOffchain( log.Infof("registered inputs and outputs with request id: %s", requestID) roundTxID, err := a.handleRoundStream( - ctx, requestID, selectedCoins, selectedBoardingCoins, outputs, roundEphemeralKey, + ctx, requestID, selectedCoins, selectedBoardingCoins, outputs, signerPrivKeys, ) if err != nil { return "", err @@ -1585,7 +1646,7 @@ func (a *covenantlessArkClient) handleRoundStream( vtxosToSign []client.TapscriptsVtxo, boardingUtxos []types.Utxo, receivers []client.Output, - roundEphemeralKey *secp256k1.PrivateKey, + signerPrivKeys []*secp256k1.PrivateKey, ) (string, error) { round, err := a.client.GetRound(ctx, "") if err != nil { @@ -1607,7 +1668,7 @@ func (a *covenantlessArkClient) handleRoundStream( close() }() - var signerSession bitcointree.SignerSession + var signerSessions []bitcointree.SignerSession const ( start = iota @@ -1644,8 +1705,8 @@ func (a *covenantlessArkClient) handleRoundStream( continue } log.Info("a round signing started") - signerSession, err = a.handleRoundSigningStarted( - ctx, roundEphemeralKey, event.(client.RoundSigningStartedEvent), + signerSessions, err = a.handleRoundSigningStarted( + ctx, signerPrivKeys, event.(client.RoundSigningStartedEvent), ) if err != nil { return "", err @@ -1659,7 +1720,7 @@ func (a *covenantlessArkClient) handleRoundStream( pingStop() log.Info("round combined nonces generated") if err := a.handleRoundSigningNoncesGenerated( - ctx, event.(client.RoundSigningNoncesGeneratedEvent), roundEphemeralKey, signerSession, + ctx, event.(client.RoundSigningNoncesGeneratedEvent), signerSessions, ); err != nil { return "", err } @@ -1699,8 +1760,8 @@ func (a *covenantlessArkClient) handleRoundStream( } func (a *covenantlessArkClient) handleRoundSigningStarted( - ctx context.Context, ephemeralKey *secp256k1.PrivateKey, event client.RoundSigningStartedEvent, -) (signerSession bitcointree.SignerSession, err error) { + ctx context.Context, signerPrivKeys []*secp256k1.PrivateKey, event client.RoundSigningStartedEvent, +) ([]bitcointree.SignerSession, error) { sweepClosure := tree.CSVMultisigClosure{ MultisigClosure: tree.MultisigClosure{PubKeys: []*secp256k1.PublicKey{a.ServerPubKey}}, Locktime: a.RoundLifetime, @@ -1708,12 +1769,12 @@ func (a *covenantlessArkClient) handleRoundSigningStarted( script, err := sweepClosure.Script() if err != nil { - return + return nil, err } roundTx, err := psbt.NewFromRawBytes(strings.NewReader(event.UnsignedRoundTx), true) if err != nil { - return + return nil, err } sharedOutput := roundTx.UnsignedTx.TxOut[0] @@ -1723,52 +1784,60 @@ func (a *covenantlessArkClient) handleRoundSigningStarted( sweepTapTree := txscript.AssembleTaprootScriptTree(sweepTapLeaf) root := sweepTapTree.RootNode.TapHash() - signerSession = bitcointree.NewTreeSignerSession( - ephemeralKey, sharedOutputValue, event.UnsignedTree, root.CloneBytes(), - ) + signerSessions := make([]bitcointree.SignerSession, 0, len(signerPrivKeys)) - if err = signerSession.SetKeys(event.CosignersPubKeys); err != nil { - return - } + for _, privKey := range signerPrivKeys { + var session bitcointree.SignerSession + session, err = bitcointree.NewTreeSignerSession( + privKey, sharedOutputValue, event.UnsignedTree, root.CloneBytes(), + ) + if err != nil { + return nil, err + } - nonces, err := signerSession.GetNonces() - if err != nil { - return - } + signerSessions = append(signerSessions, session) - myPubkey := hex.EncodeToString(ephemeralKey.PubKey().SerializeCompressed()) + nonces, err := session.GetNonces() + if err != nil { + return nil, err + } - err = a.arkClient.client.SubmitTreeNonces(ctx, event.ID, myPubkey, nonces) + myPubkey := hex.EncodeToString(privKey.PubKey().SerializeCompressed()) - return + err = a.arkClient.client.SubmitTreeNonces(ctx, event.ID, myPubkey, nonces) + if err != nil { + return nil, err + } + } + + return signerSessions, nil } func (a *covenantlessArkClient) handleRoundSigningNoncesGenerated( ctx context.Context, event client.RoundSigningNoncesGeneratedEvent, - ephemeralKey *secp256k1.PrivateKey, - signerSession bitcointree.SignerSession, + signerSessions []bitcointree.SignerSession, ) error { - if signerSession == nil { + if len(signerSessions) <= 0 { return fmt.Errorf("tree signer session not set") } - if err := signerSession.SetAggregatedNonces(event.Nonces); err != nil { - return err - } + for _, session := range signerSessions { + session.SetAggregatedNonces(event.Nonces) - sigs, err := signerSession.Sign() - if err != nil { - return err - } + sigs, err := session.Sign() + if err != nil { + return err + } - if err := a.arkClient.client.SubmitTreeSignatures( - ctx, - event.ID, - hex.EncodeToString(ephemeralKey.PubKey().SerializeCompressed()), - sigs, - ); err != nil { - return err + if err := a.arkClient.client.SubmitTreeSignatures( + ctx, + event.ID, + session.GetPublicKey(), + sigs, + ); err != nil { + return err + } } return nil @@ -2702,3 +2771,33 @@ func buildRedeemTx( return bitcointree.BuildRedeemTx(ins, outs) } + +func handleOptions(options *SettleOptions) ([]*secp256k1.PrivateKey, []string, tree.SigningType, error) { + signerPrivKeys := make([]*secp256k1.PrivateKey, 0) + signerPubKeys := make([]string, 0) + if len(options.CustomSignerPrivKeys) > 0 { + for _, privKey := range options.CustomSignerPrivKeys { + signerPrivKeys = append(signerPrivKeys, privKey) + signerPubKeys = append(signerPubKeys, hex.EncodeToString(privKey.PubKey().SerializeCompressed())) + } + } + + var signingType tree.SigningType + if options.SigningType != nil { + signingType = *options.SigningType + } else { + signingType = tree.SignBranch + } + + // if no custom signer priv keys are provided, we generate a new ephemeral key + if len(signerPubKeys) == 0 { + ephemeralKey, err := secp256k1.GeneratePrivateKey() + if err != nil { + return nil, nil, tree.SignBranch, err + } + signerPrivKeys = append(signerPrivKeys, ephemeralKey) + signerPubKeys = append(signerPubKeys, hex.EncodeToString(ephemeralKey.PubKey().SerializeCompressed())) + } + + return signerPrivKeys, signerPubKeys, signingType, nil +} diff --git a/server/internal/core/application/covenant.go b/server/internal/core/application/covenant.go index 4d40e4301..7b8956d03 100644 --- a/server/internal/core/application/covenant.go +++ b/server/internal/core/application/covenant.go @@ -188,11 +188,11 @@ func (s *covenantService) GetBoardingAddress(ctx context.Context, userPubkey *se return addr, scripts, nil } -func (s *covenantService) SpendNotes(_ context.Context, _ []note.Note) (string, error) { +func (s *covenantService) SpendNotes(_ context.Context, _ []note.Note, _ []string, _ domain.SigningType) (string, error) { return "", fmt.Errorf("unimplemented") } -func (s *covenantService) SpendVtxos(ctx context.Context, inputs []ports.Input) (string, error) { +func (s *covenantService) SpendVtxos(ctx context.Context, inputs []ports.Input, _ []string, _ domain.SigningType) (string, error) { vtxosInputs := make([]domain.Vtxo, 0) boardingInputs := make([]ports.BoardingInput, 0) @@ -473,16 +473,6 @@ func (s *covenantService) GetInfo(ctx context.Context) (*ServiceInfo, error) { }, nil } -func (s *covenantService) RegisterCosignerPubkey(ctx context.Context, requestID string, _ string) error { - // if the user sends an ephemeral pubkey, something is going wrong client-side - // we should delete the associated tx request - if err := s.txRequests.delete(requestID); err != nil { - log.WithError(err).Warnf("failed to delete tx request %s", requestID) - } - - return ErrTreeSigningNotRequired -} - func (s *covenantService) RegisterCosignerNonces(context.Context, string, *secp256k1.PublicKey, string) error { return ErrTreeSigningNotRequired } @@ -567,7 +557,7 @@ func (s *covenantService) startFinalization() { if num > txRequestsThreshold { num = txRequestsThreshold } - requests, boardingInputs, _, _ := s.txRequests.pop(num) + requests, boardingInputs, _ := s.txRequests.pop(num) if _, err := round.RegisterTxRequests(requests); err != nil { round.Fail(fmt.Errorf("failed to register tx requests: %s", err)) log.WithError(err).Warn("failed to register tx requests") diff --git a/server/internal/core/application/covenantless.go b/server/internal/core/application/covenantless.go index 4172022f9..caffc0bd5 100644 --- a/server/internal/core/application/covenantless.go +++ b/server/internal/core/application/covenantless.go @@ -53,10 +53,13 @@ type covenantlessService struct { transactionEventsCh chan TransactionEvent // cached data for the current round - lastEvent domain.RoundEvent currentRoundLock sync.Mutex currentRound *domain.Round treeSigningSessions map[string]*musigSigningSession + + // TODO derive this from wallet + serverSigningKey *secp256k1.PrivateKey + serverSigningPubKey *secp256k1.PublicKey } func NewCovenantlessService( @@ -89,6 +92,11 @@ func NewCovenantlessService( } } + serverSigningKey, err := secp256k1.GeneratePrivateKey() + if err != nil { + return nil, fmt.Errorf("failed to generate ephemeral key: %s", err) + } + svc := &covenantlessService{ network: network, pubkey: pubkey, @@ -108,6 +116,8 @@ func NewCovenantlessService( treeSigningSessions: make(map[string]*musigSigningSession), boardingExitDelay: boardingExitDelay, nostrDefaultRelays: nostrDefaultRelays, + serverSigningKey: serverSigningKey, + serverSigningPubKey: serverSigningKey.PubKey(), } repoManager.RegisterEventsHandler( @@ -496,7 +506,7 @@ func (s *covenantlessService) GetBoardingAddress( return } -func (s *covenantlessService) SpendNotes(ctx context.Context, notes []note.Note) (string, error) { +func (s *covenantlessService) SpendNotes(ctx context.Context, notes []note.Note, signerPubkeys []string, signingType domain.SigningType) (string, error) { notesRepo := s.repoManager.Notes() for _, note := range notes { @@ -528,6 +538,12 @@ func (s *covenantlessService) SpendNotes(ctx context.Context, notes []note.Note) return "", fmt.Errorf("failed to create tx request: %s", err) } + // add the server pubkey as a signer + signerPubkeys = append(signerPubkeys, hex.EncodeToString(s.serverSigningPubKey.SerializeCompressed())) + + request.AddSignerPubKeys(signerPubkeys) + request.AddSigningType(signingType) + if err := s.txRequests.pushWithNotes(*request, notes); err != nil { return "", fmt.Errorf("failed to push tx requests: %s", err) } @@ -535,7 +551,7 @@ func (s *covenantlessService) SpendNotes(ctx context.Context, notes []note.Note) return request.Id, nil } -func (s *covenantlessService) SpendVtxos(ctx context.Context, inputs []ports.Input) (string, error) { +func (s *covenantlessService) SpendVtxos(ctx context.Context, inputs []ports.Input, signerPubkeys []string, signingType domain.SigningType) (string, error) { vtxosInputs := make([]domain.Vtxo, 0) boardingInputs := make([]ports.BoardingInput, 0) @@ -635,6 +651,16 @@ func (s *covenantlessService) SpendVtxos(ctx context.Context, inputs []ports.Inp if err != nil { return "", err } + + if len(signerPubkeys) <= 0 { + return "", fmt.Errorf("signer pubkeys are required") + } + + signerPubkeys = append(signerPubkeys, hex.EncodeToString(s.serverSigningPubKey.SerializeCompressed())) + + request.AddSignerPubKeys(signerPubkeys) + request.AddSigningType(signingType) + if err := s.txRequests.push(*request, boardingInputs); err != nil { return "", err } @@ -849,20 +875,6 @@ func calcNextMarketHour(marketHourStartTime, marketHourEndTime time.Time, period } } -func (s *covenantlessService) RegisterCosignerPubkey(ctx context.Context, requestID string, pubkey string) error { - pubkeyBytes, err := hex.DecodeString(pubkey) - if err != nil { - return fmt.Errorf("failed to decode hex pubkey: %s", err) - } - - ephemeralPubkey, err := secp256k1.ParsePubKey(pubkeyBytes) - if err != nil { - return fmt.Errorf("failed to parse pubkey: %s", err) - } - - return s.txRequests.pushEphemeralKey(requestID, ephemeralPubkey) -} - func (s *covenantlessService) RegisterCosignerNonces( ctx context.Context, roundID string, pubkey *secp256k1.PublicKey, encodedNonces string, ) error { @@ -1035,14 +1047,7 @@ func (s *covenantlessService) startFinalization() { if num > txRequestsThreshold { num = txRequestsThreshold } - requests, boardingInputs, cosigners, redeeemedNotes := s.txRequests.pop(num) - if len(requests) > len(cosigners) { - err := fmt.Errorf("missing ephemeral key for tx requests") - round.Fail(fmt.Errorf("round aborted: %s", err)) - log.WithError(err).Debugf("round %s aborted", round.Id) - return - } - + requests, boardingInputs, redeeemedNotes := s.txRequests.pop(num) notes = redeeemedNotes if _, err := round.RegisterTxRequests(requests); err != nil { @@ -1058,17 +1063,8 @@ func (s *covenantlessService) startFinalization() { return } - ephemeralKey, err := secp256k1.GeneratePrivateKey() - if err != nil { - round.Fail(fmt.Errorf("failed to generate ephemeral key: %s", err)) - log.WithError(err).Warn("failed to generate ephemeral key") - return - } - - cosigners = append(cosigners, ephemeralKey.PubKey()) - unsignedRoundTx, vtxoTree, connectorAddress, connectors, err := s.builder.BuildRoundTx( - s.pubkey, requests, boardingInputs, connectorAddresses, cosigners..., + s.pubkey, requests, boardingInputs, connectorAddresses, ) if err != nil { round.Fail(fmt.Errorf("failed to create round tx: %s", err)) @@ -1080,16 +1076,24 @@ func (s *covenantlessService) startFinalization() { s.forfeitTxs.init(connectors, requests) if len(vtxoTree) > 0 { - log.Debugf("signing vtxo tree for round %s", round.Id) - signingSession := newMusigSigningSession(len(cosigners)) + uniqueSignerPubkeys := make(map[string]struct{}) + for _, request := range requests { + for _, pubkey := range request.SignerPubKeys { + uniqueSignerPubkeys[pubkey] = struct{}{} + } + } + + nbOfCosigners := len(uniqueSignerPubkeys) + + signingSession := newMusigSigningSession(nbOfCosigners) s.treeSigningSessions[round.Id] = signingSession log.Debugf("signing session created for round %s", round.Id) s.currentRound.UnsignedTx = unsignedRoundTx // send back the unsigned tree & all cosigners pubkeys - s.propagateRoundSigningStartedEvent(vtxoTree, cosigners) + s.propagateRoundSigningStartedEvent(vtxoTree) sweepClosure := tree.CSVMultisigClosure{ MultisigClosure: tree.MultisigClosure{PubKeys: []*secp256k1.PublicKey{s.pubkey}}, @@ -1114,16 +1118,21 @@ func (s *covenantlessService) startFinalization() { sweepTapTree := txscript.AssembleTaprootScriptTree(sweepLeaf) root := sweepTapTree.RootNode.TapHash() - coordinator, err := bitcointree.NewTreeCoordinatorSession(sharedOutputAmount, vtxoTree, root.CloneBytes(), cosigners) + coordinator, err := bitcointree.NewTreeCoordinatorSession(sharedOutputAmount, vtxoTree, root.CloneBytes()) if err != nil { round.Fail(fmt.Errorf("failed to create tree coordinator: %s", err)) log.WithError(err).Warn("failed to create tree coordinator") return } - serverSignerSession := bitcointree.NewTreeSignerSession( - ephemeralKey, sharedOutputAmount, vtxoTree, root.CloneBytes(), + serverSignerSession, err := bitcointree.NewTreeSignerSession( + s.serverSigningKey, sharedOutputAmount, vtxoTree, root.CloneBytes(), ) + if err != nil { + round.Fail(fmt.Errorf("failed to create tree signer session: %s", err)) + log.WithError(err).Warn("failed to create tree signer session") + return + } nonces, err := serverSignerSession.GetNonces() if err != nil { @@ -1132,11 +1141,7 @@ func (s *covenantlessService) startFinalization() { return } - if err := coordinator.AddNonce(ephemeralKey.PubKey(), nonces); err != nil { - round.Fail(fmt.Errorf("failed to add nonce: %s", err)) - log.WithError(err).Warn("failed to add nonce") - return - } + coordinator.AddNonce(s.serverSigningPubKey, nonces) noncesTimer := time.NewTimer(thirdOfRemainingDuration) @@ -1148,11 +1153,7 @@ func (s *covenantlessService) startFinalization() { case <-signingSession.nonceDoneC: noncesTimer.Stop() for pubkey, nonce := range signingSession.nonces { - if err := coordinator.AddNonce(pubkey, nonce); err != nil { - round.Fail(fmt.Errorf("failed to add nonce: %s", err)) - log.WithError(err).Warn("failed to add nonce") - return - } + coordinator.AddNonce(pubkey, nonce) } } @@ -1167,19 +1168,10 @@ func (s *covenantlessService) startFinalization() { log.Debugf("nonces aggregated for round %s", round.Id) + // send the combined nonces to the clients s.propagateRoundSigningNoncesGeneratedEvent(aggragatedNonces) - if err := serverSignerSession.SetKeys(cosigners); err != nil { - round.Fail(fmt.Errorf("failed to set keys: %s", err)) - log.WithError(err).Warn("failed to set keys") - return - } - - if err := serverSignerSession.SetAggregatedNonces(aggragatedNonces); err != nil { - round.Fail(fmt.Errorf("failed to set aggregated nonces: %s", err)) - log.WithError(err).Warn("failed to set aggregated nonces") - return - } + serverSignerSession.SetAggregatedNonces(aggragatedNonces) // sign the tree as server serverTreeSigs, err := serverSignerSession.Sign() @@ -1188,12 +1180,7 @@ func (s *covenantlessService) startFinalization() { log.WithError(err).Warn("failed to sign tree") return } - - if err := coordinator.AddSig(ephemeralKey.PubKey(), serverTreeSigs); err != nil { - round.Fail(fmt.Errorf("failed to add signature: %s", err)) - log.WithError(err).Warn("failed to add signature") - return - } + coordinator.AddSig(s.serverSigningPubKey, serverTreeSigs) log.Debugf("tree signed by us for round %s", round.Id) @@ -1209,11 +1196,7 @@ func (s *covenantlessService) startFinalization() { case <-signingSession.sigDoneC: signaturesTimer.Stop() for pubkey, sig := range signingSession.signatures { - if err := coordinator.AddSig(pubkey, sig); err != nil { - round.Fail(fmt.Errorf("failed to add signature: %s", err)) - log.WithError(err).Warn("failed to add signature") - return - } + coordinator.AddSig(pubkey, sig) } } @@ -1242,17 +1225,13 @@ func (s *covenantlessService) startFinalization() { log.Debugf("started finalization stage for round: %s", round.Id) } -func (s *covenantlessService) propagateRoundSigningStartedEvent( - unsignedVtxoTree tree.VtxoTree, cosigners []*secp256k1.PublicKey, -) { +func (s *covenantlessService) propagateRoundSigningStartedEvent(unsignedVtxoTree tree.VtxoTree) { ev := RoundSigningStarted{ Id: s.currentRound.Id, UnsignedVtxoTree: unsignedVtxoTree, - Cosigners: cosigners, UnsignedRoundTx: s.currentRound.UnsignedTx, } - s.lastEvent = ev s.eventsCh <- ev } @@ -1262,7 +1241,6 @@ func (s *covenantlessService) propagateRoundSigningNoncesGeneratedEvent(combined Nonces: combinedNonces, } - s.lastEvent = ev s.eventsCh <- ev } @@ -1576,10 +1554,8 @@ func (s *covenantlessService) propagateEvents(round *domain.Round) { RoundTx: e.RoundTx, MinRelayFeeRate: int64(s.wallet.MinRelayFeeRate(context.Background())), } - s.lastEvent = ev s.eventsCh <- ev case domain.RoundFinalized, domain.RoundFailed: - s.lastEvent = e s.eventsCh <- e } } diff --git a/server/internal/core/application/covenantless_event.go b/server/internal/core/application/covenantless_event.go index 41cad10ec..76a18ed01 100644 --- a/server/internal/core/application/covenantless_event.go +++ b/server/internal/core/application/covenantless_event.go @@ -11,14 +11,12 @@ import ( "github.com/ark-network/ark/common/bitcointree" "github.com/ark-network/ark/common/tree" - "github.com/decred/dcrd/dcrec/secp256k1/v4" ) // signer should react to this event by generating a musig2 nonce for each transaction in the tree type RoundSigningStarted struct { Id string UnsignedVtxoTree tree.VtxoTree - Cosigners []*secp256k1.PublicKey UnsignedRoundTx string } diff --git a/server/internal/core/application/types.go b/server/internal/core/application/types.go index 37ffcbd89..a5750197b 100644 --- a/server/internal/core/application/types.go +++ b/server/internal/core/application/types.go @@ -17,8 +17,8 @@ var ( type Service interface { Start() error Stop() - SpendNotes(ctx context.Context, notes []note.Note) (string, error) - SpendVtxos(ctx context.Context, inputs []ports.Input) (string, error) + SpendNotes(ctx context.Context, notes []note.Note, signerPubkeys []string, signingType domain.SigningType) (string, error) + SpendVtxos(ctx context.Context, inputs []ports.Input, signerPubkeys []string, signingType domain.SigningType) (string, error) ClaimVtxos(ctx context.Context, creds string, receivers []domain.Receiver) error SignVtxos(ctx context.Context, forfeitTxs []string) error SignRoundTx(ctx context.Context, roundTx string) error @@ -36,7 +36,6 @@ type Service interface { ctx context.Context, userPubkey *secp256k1.PublicKey, ) (address string, scripts []string, err error) // Tree signing methods - RegisterCosignerPubkey(ctx context.Context, requestID string, ephemeralPubkey string) error RegisterCosignerNonces( ctx context.Context, roundID string, pubkey *secp256k1.PublicKey, nonces string, diff --git a/server/internal/core/application/utils.go b/server/internal/core/application/utils.go index 4d3db2ce6..4fabd5322 100644 --- a/server/internal/core/application/utils.go +++ b/server/internal/core/application/utils.go @@ -12,7 +12,6 @@ import ( "github.com/ark-network/ark/common/tree" "github.com/ark-network/ark/server/internal/core/domain" "github.com/ark-network/ark/server/internal/core/ports" - "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/nbd-wtf/go-nostr" "github.com/nbd-wtf/go-nostr/nip19" ) @@ -26,15 +25,14 @@ type timedTxRequest struct { } type txRequestsQueue struct { - lock *sync.RWMutex - requests map[string]*timedTxRequest - ephemeralKeys map[string]*secp256k1.PublicKey + lock *sync.RWMutex + requests map[string]*timedTxRequest } func newTxRequestsQueue() *txRequestsQueue { requestsById := make(map[string]*timedTxRequest) lock := &sync.RWMutex{} - return &txRequestsQueue{lock, requestsById, make(map[string]*secp256k1.PublicKey)} + return &txRequestsQueue{lock, requestsById} } func (m *txRequestsQueue) len() int64 { @@ -50,18 +48,6 @@ func (m *txRequestsQueue) len() int64 { return count } -func (m *txRequestsQueue) delete(id string) error { - m.lock.Lock() - defer m.lock.Unlock() - - if _, ok := m.requests[id]; !ok { - return errTxRequestNotFound{id} - } - - delete(m.requests, id) - return nil -} - func (m *txRequestsQueue) pushWithNotes(request domain.TxRequest, notes []note.Note) error { m.lock.Lock() defer m.lock.Unlock() @@ -119,19 +105,7 @@ func (m *txRequestsQueue) push( return nil } -func (m *txRequestsQueue) pushEphemeralKey(requestID string, pubkey *secp256k1.PublicKey) error { - m.lock.Lock() - defer m.lock.Unlock() - - if _, ok := m.requests[requestID]; !ok { - return fmt.Errorf("tx request %s not found, cannot register signing ephemeral public key", requestID) - } - - m.ephemeralKeys[requestID] = pubkey - return nil -} - -func (m *txRequestsQueue) pop(num int64) ([]domain.TxRequest, []ports.BoardingInput, []*secp256k1.PublicKey, []note.Note) { +func (m *txRequestsQueue) pop(num int64) ([]domain.TxRequest, []ports.BoardingInput, []note.Note) { m.lock.Lock() defer m.lock.Unlock() @@ -157,19 +131,14 @@ func (m *txRequestsQueue) pop(num int64) ([]domain.TxRequest, []ports.BoardingIn requests := make([]domain.TxRequest, 0, num) boardingInputs := make([]ports.BoardingInput, 0) - cosigners := make([]*secp256k1.PublicKey, 0, num) notes := make([]note.Note, 0) for _, p := range requestsByTime[:num] { boardingInputs = append(boardingInputs, p.boardingInputs...) requests = append(requests, p.TxRequest) - if pubkey, ok := m.ephemeralKeys[p.TxRequest.Id]; ok { - cosigners = append(cosigners, pubkey) - delete(m.ephemeralKeys, p.TxRequest.Id) - } notes = append(notes, p.notes...) delete(m.requests, p.Id) } - return requests, boardingInputs, cosigners, notes + return requests, boardingInputs, notes } func (m *txRequestsQueue) update(request domain.TxRequest) error { @@ -233,9 +202,11 @@ func (m *txRequestsQueue) view(id string) (*domain.TxRequest, bool) { } return &domain.TxRequest{ - Id: request.Id, - Inputs: request.Inputs, - Receivers: request.Receivers, + Id: request.Id, + Inputs: request.Inputs, + Receivers: request.Receivers, + SignerPubKeys: request.SignerPubKeys, + SigningType: request.SigningType, }, true } diff --git a/server/internal/core/domain/payment.go b/server/internal/core/domain/payment.go index a694e22fa..85653596e 100644 --- a/server/internal/core/domain/payment.go +++ b/server/internal/core/domain/payment.go @@ -11,10 +11,19 @@ import ( "github.com/google/uuid" ) +type SigningType uint8 + +const ( + SignAll SigningType = iota + SignBranch +) + type TxRequest struct { - Id string - Inputs []Vtxo - Receivers []Receiver + Id string + Inputs []Vtxo + Receivers []Receiver + SignerPubKeys []string // pubkeys signing the shared output + SigningType SigningType } func NewTxRequest(inputs []Vtxo) (*TxRequest, error) { @@ -28,6 +37,14 @@ func NewTxRequest(inputs []Vtxo) (*TxRequest, error) { return request, nil } +func (r *TxRequest) AddSignerPubKeys(pubkeys []string) { + r.SignerPubKeys = append(r.SignerPubKeys, pubkeys...) +} + +func (r *TxRequest) AddSigningType(signingType SigningType) { + r.SigningType = signingType +} + func (r *TxRequest) AddReceivers(receivers []Receiver) (err error) { if r.Receivers == nil { r.Receivers = make([]Receiver, 0) diff --git a/server/internal/core/ports/tx_builder.go b/server/internal/core/ports/tx_builder.go index 61210cbea..6ce2d07ef 100644 --- a/server/internal/core/ports/tx_builder.go +++ b/server/internal/core/ports/tx_builder.go @@ -36,7 +36,6 @@ type TxBuilder interface { BuildRoundTx( serverPubkey *secp256k1.PublicKey, txRequests []domain.TxRequest, boardingInputs []BoardingInput, connectorAddresses []string, - cosigners ...*secp256k1.PublicKey, ) ( roundTx string, vtxoTree tree.VtxoTree, diff --git a/server/internal/infrastructure/tx-builder/covenant/builder.go b/server/internal/infrastructure/tx-builder/covenant/builder.go index 4104658fd..64a4d4444 100644 --- a/server/internal/infrastructure/tx-builder/covenant/builder.go +++ b/server/internal/infrastructure/tx-builder/covenant/builder.go @@ -366,7 +366,6 @@ func (b *txBuilder) BuildRoundTx( requests []domain.TxRequest, boardingInputs []ports.BoardingInput, connectorAddresses []string, - _ ...*secp256k1.PublicKey, // cosigners are not used in the covenant ) (roundTx string, vtxoTree tree.VtxoTree, nextConnectorAddress string, connectors []string, err error) { // The creation of the tree and the round tx are tightly coupled: // - building the tree requires knowing the shared outpoint (txid:vout) diff --git a/server/internal/infrastructure/tx-builder/covenantless/builder.go b/server/internal/infrastructure/tx-builder/covenantless/builder.go index 226d8c4a1..5e164551b 100644 --- a/server/internal/infrastructure/tx-builder/covenantless/builder.go +++ b/server/internal/infrastructure/tx-builder/covenantless/builder.go @@ -32,7 +32,9 @@ type txBuilder struct { } func NewTxBuilder( - wallet ports.WalletService, net common.Network, roundLifetime, boardingExitDelay common.RelativeLocktime, + wallet ports.WalletService, + net common.Network, + roundLifetime, boardingExitDelay common.RelativeLocktime, ) ports.TxBuilder { return &txBuilder{wallet, net, roundLifetime, boardingExitDelay} } @@ -552,13 +554,14 @@ func (b *txBuilder) BuildRoundTx( requests []domain.TxRequest, boardingInputs []ports.BoardingInput, connectorAddresses []string, - cosigners ...*secp256k1.PublicKey, ) (roundTx string, vtxoTree tree.VtxoTree, nextConnectorAddress string, connectors []string, err error) { var sharedOutputScript []byte var sharedOutputAmount int64 - if len(cosigners) == 0 { - return "", nil, "", nil, fmt.Errorf("missing cosigners") + for _, request := range requests { + if len(request.SignerPubKeys) == 0 { + return "", nil, "", nil, fmt.Errorf("missing signer pubkeys for request ID %s", request.Id) + } } receivers, err := getOutputVtxosLeaves(requests) @@ -571,9 +574,23 @@ func (b *txBuilder) BuildRoundTx( return } + var sweepScript []byte + sweepScript, err = (&tree.CSVMultisigClosure{ + MultisigClosure: tree.MultisigClosure{ + PubKeys: []*secp256k1.PublicKey{serverPubkey}, + }, + Locktime: b.roundLifetime, + }).Script() + if err != nil { + return + } + + tree := txscript.AssembleTaprootScriptTree(txscript.NewBaseTapLeaf(sweepScript)) + root := tree.RootNode.TapHash() + if !isOnchainOnly(requests) { sharedOutputScript, sharedOutputAmount, err = bitcointree.CraftSharedOutput( - cosigners, serverPubkey, receivers, feeAmount, b.roundLifetime, + receivers, feeAmount, root[:], ) if err != nil { return @@ -605,7 +622,7 @@ func (b *txBuilder) BuildRoundTx( } vtxoTree, err = bitcointree.BuildVtxoTree( - initialOutpoint, cosigners, serverPubkey, receivers, feeAmount, b.roundLifetime, + initialOutpoint, receivers, feeAmount, root[:], ) if err != nil { return "", nil, "", nil, err diff --git a/server/internal/infrastructure/tx-builder/covenantless/builder_test.go b/server/internal/infrastructure/tx-builder/covenantless/builder_test.go index 1d7ecc988..ccc43a7ab 100644 --- a/server/internal/infrastructure/tx-builder/covenantless/builder_test.go +++ b/server/internal/infrastructure/tx-builder/covenantless/builder_test.go @@ -12,6 +12,7 @@ import ( "github.com/ark-network/ark/server/internal/core/domain" "github.com/ark-network/ark/server/internal/core/ports" txbuilder "github.com/ark-network/ark/server/internal/infrastructure/tx-builder/covenantless" + "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -68,16 +69,23 @@ func TestBuildRoundTx(t *testing.T) { if len(fixtures.Valid) > 0 { t.Run("valid", func(t *testing.T) { for _, f := range fixtures.Valid { - cosigners := make([]*secp256k1.PublicKey, 0) - for range f.Requests { + requests := make([]domain.TxRequest, 0) + + for _, request := range f.Requests { randKey, err := secp256k1.GeneratePrivateKey() require.NoError(t, err) - cosigners = append(cosigners, randKey.PubKey()) + requests = append(requests, domain.TxRequest{ + Id: request.Id, + SignerPubKeys: []string{ + hex.EncodeToString(schnorr.SerializePubKey(randKey.PubKey())), + }, + SigningType: 0, + }) } roundTx, vtxoTree, connAddr, _, err := builder.BuildRoundTx( - pubkey, f.Requests, []ports.BoardingInput{}, []string{}, cosigners..., + pubkey, f.Requests, []ports.BoardingInput{}, []string{}, ) require.NoError(t, err) require.NotEmpty(t, roundTx) diff --git a/server/internal/infrastructure/tx-builder/covenantless/utils.go b/server/internal/infrastructure/tx-builder/covenantless/utils.go index 4a31d8f80..7741518aa 100644 --- a/server/internal/infrastructure/tx-builder/covenantless/utils.go +++ b/server/internal/infrastructure/tx-builder/covenantless/utils.go @@ -46,8 +46,10 @@ func getOutputVtxosLeaves( for _, receiver := range request.Receivers { if !receiver.IsOnchain() { leaves = append(leaves, tree.VtxoLeaf{ - PubKey: receiver.PubKey, - Amount: receiver.Amount, + PubKey: receiver.PubKey, + Amount: receiver.Amount, + Type: tree.SigningType(request.SigningType), + SignersPublicKeys: request.SignerPubKeys, }) } } diff --git a/server/internal/interface/grpc/handlers/arkservice.go b/server/internal/interface/grpc/handlers/arkservice.go index 3e3ec135a..115f8a282 100644 --- a/server/internal/interface/grpc/handlers/arkservice.go +++ b/server/internal/interface/grpc/handlers/arkservice.go @@ -131,7 +131,7 @@ func (h *handler) RegisterInputsForNextRound( if err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } - requestID, err = h.svc.SpendVtxos(ctx, inputs) + requestID, err = h.svc.SpendVtxos(ctx, inputs, req.GetSignerPubkeys(), domain.SigningType(req.GetSigningType())) if err != nil { return nil, err } @@ -142,19 +142,12 @@ func (h *handler) RegisterInputsForNextRound( if err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } - requestID, err = h.svc.SpendNotes(ctx, notes) + requestID, err = h.svc.SpendNotes(ctx, notes, req.GetSignerPubkeys(), domain.SigningType(req.GetSigningType())) if err != nil { return nil, err } } - pubkey := req.GetEphemeralPubkey() - if len(pubkey) > 0 { - if err := h.svc.RegisterCosignerPubkey(ctx, requestID, pubkey); err != nil { - return nil, err - } - } - return &arkv1.RegisterInputsForNextRoundResponse{ RequestId: requestID, }, nil @@ -519,17 +512,10 @@ func (h *handler) listenToEvents() { }, } case application.RoundSigningStarted: - cosignersKeys := make([]string, 0, len(e.Cosigners)) - for _, key := range e.Cosigners { - keyStr := hex.EncodeToString(key.SerializeCompressed()) - cosignersKeys = append(cosignersKeys, keyStr) - } - ev = &arkv1.GetEventStreamResponse{ Event: &arkv1.GetEventStreamResponse_RoundSigning{ RoundSigning: &arkv1.RoundSigningEvent{ Id: e.Id, - CosignersPubkeys: cosignersKeys, UnsignedVtxoTree: vtxoTree(e.UnsignedVtxoTree).toProto(), UnsignedRoundTx: e.UnsignedRoundTx, }, From 200ab95d8bf37da67f9bac7cdbd558591705b0e0 Mon Sep 17 00:00:00 2001 From: louisinger Date: Wed, 15 Jan 2025 16:34:50 +0100 Subject: [PATCH 02/21] fix: sweeper and tests --- common/bitcointree/builder.go | 11 ++- common/bitcointree/musig2_test.go | 1 + common/bitcointree/psbt.go | 21 +++++ common/bitcointree/validation.go | 88 +++++++------------ common/locktime.go | 16 ++++ .../redemption/covenantless_redeem.go | 53 +++-------- .../internal/core/application/covenantless.go | 3 + .../tx-builder/covenantless/builder.go | 81 ++++++++++++++--- .../tx-builder/covenantless/builder_test.go | 23 ++++- 9 files changed, 180 insertions(+), 117 deletions(-) diff --git a/common/bitcointree/builder.go b/common/bitcointree/builder.go index f8c2ca307..39893457a 100644 --- a/common/bitcointree/builder.go +++ b/common/bitcointree/builder.go @@ -46,6 +46,7 @@ func BuildVtxoTree( receivers []tree.VtxoLeaf, feeSatsPerNode uint64, sweepTapTreeRoot []byte, + lifetime common.RelativeLocktime, ) (tree.VtxoTree, error) { root, err := createRootNode(receivers, feeSatsPerNode, sweepTapTreeRoot) if err != nil { @@ -64,7 +65,7 @@ func BuildVtxoTree( treeLevel := make([]tree.Node, 0) for i, node := range nodes { - treeNode, err := getTreeNode(node, ins[i]) + treeNode, err := getTreeNode(node, ins[i], lifetime) if err != nil { return nil, err } @@ -172,8 +173,9 @@ func (b *branch) getOutputs() ([]*wire.TxOut, error) { func getTreeNode( n node, input *wire.OutPoint, + lifetime common.RelativeLocktime, ) (tree.Node, error) { - partialTx, err := getTx(n, input) + partialTx, err := getTx(n, input, lifetime) if err != nil { return tree.Node{}, err } @@ -196,6 +198,7 @@ func getTreeNode( func getTx( n node, input *wire.OutPoint, + lifetime common.RelativeLocktime, ) (*psbt.Packet, error) { outputs, err := n.getOutputs() if err != nil { @@ -222,6 +225,10 @@ func getTx( } } + if err := AddLifetime(0, tx, lifetime); err != nil { + return nil, err + } + return tx, nil } diff --git a/common/bitcointree/musig2_test.go b/common/bitcointree/musig2_test.go index 7f60f6814..83347fcd4 100644 --- a/common/bitcointree/musig2_test.go +++ b/common/bitcointree/musig2_test.go @@ -78,6 +78,7 @@ func TestRoundTripSignTree(t *testing.T) { receivers, minRelayFee, sweepRoot[:], + lifetime, ) require.NoError(t, err) diff --git a/common/bitcointree/psbt.go b/common/bitcointree/psbt.go index eae26c23a..07842c10b 100644 --- a/common/bitcointree/psbt.go +++ b/common/bitcointree/psbt.go @@ -3,6 +3,7 @@ package bitcointree import ( "bytes" + "github.com/ark-network/ark/common" "github.com/ark-network/ark/common/tree" "github.com/btcsuite/btcd/btcutil/psbt" "github.com/btcsuite/btcd/wire" @@ -12,6 +13,7 @@ import ( var ( COSIGNER_PSBT_KEY_PREFIX = []byte("cosigner") CONDITION_WITNESS_KEY_PREFIX = []byte(tree.ConditionWitnessKey) + LIFETIME_PSBT_KEY = []byte("lifetime") ) func AddConditionWitness(inIndex int, ptx *psbt.Packet, witness wire.TxWitness) error { @@ -39,6 +41,25 @@ func GetConditionWitness(in psbt.PInput) (wire.TxWitness, error) { return wire.TxWitness{}, nil } +func AddLifetime(inIndex int, ptx *psbt.Packet, lifetime common.RelativeLocktime) error { + ptx.Inputs[inIndex].Unknowns = append(ptx.Inputs[inIndex].Unknowns, &psbt.Unknown{ + Value: lifetime.Bytes(), + Key: LIFETIME_PSBT_KEY, + }) + + return nil +} + +func GetLifetime(in psbt.PInput) (*common.RelativeLocktime, error) { + for _, u := range in.Unknowns { + if bytes.Contains(u.Key, LIFETIME_PSBT_KEY) { + return common.NewRelativeLocktimeFromBytes(u.Value) + } + } + + return nil, nil +} + func AddCosignerKey(inIndex int, ptx *psbt.Packet, key *secp256k1.PublicKey) error { currentCosigners, err := GetCosignerKeys(ptx.Inputs[inIndex]) if err != nil { diff --git a/common/bitcointree/validation.go b/common/bitcointree/validation.go index 9f1068aab..39d270a2f 100644 --- a/common/bitcointree/validation.go +++ b/common/bitcointree/validation.go @@ -15,36 +15,32 @@ import ( ) var ( - ErrInvalidRoundTx = fmt.Errorf("invalid round transaction") - ErrInvalidRoundTxOutputs = fmt.Errorf("invalid number of outputs in round transaction") - ErrEmptyTree = fmt.Errorf("empty vtxo tree") - ErrInvalidRootLevel = fmt.Errorf("root level must have only one node") - ErrNoLeaves = fmt.Errorf("no leaves in the tree") - ErrNodeTxEmpty = fmt.Errorf("node transaction is empty") - ErrNodeTxidEmpty = fmt.Errorf("node txid is empty") - ErrNodeParentTxidEmpty = fmt.Errorf("node parent txid is empty") - ErrNodeTxidDifferent = fmt.Errorf("node txid differs from node transaction") - ErrNumberOfInputs = fmt.Errorf("node transaction should have only one input") - ErrNumberOfOutputs = fmt.Errorf("node transaction should have only three or two outputs") - ErrParentTxidInput = fmt.Errorf("parent txid should be the input of the node transaction") - ErrNumberOfChildren = fmt.Errorf("node branch transaction should have two children") - ErrLeafChildren = fmt.Errorf("leaf node should have max 1 child") - ErrInvalidChildTxid = fmt.Errorf("invalid child txid") - ErrNumberOfTapscripts = fmt.Errorf("input should have 1 tapscript leaf") - ErrInternalKey = fmt.Errorf("invalid taproot internal key") - ErrInvalidTaprootScript = fmt.Errorf("invalid taproot script") - ErrInvalidControlBlock = fmt.Errorf("invalid control block") - ErrInvalidTaprootScriptLen = fmt.Errorf("invalid taproot script length (expected 32 bytes)") - ErrInvalidLeafTaprootScript = fmt.Errorf("invalid leaf taproot script") - ErrInvalidAmount = fmt.Errorf("children amount is different from parent amount") - ErrInvalidSweepSequence = fmt.Errorf("invalid sweep sequence") - ErrInvalidServer = fmt.Errorf("invalid server") - ErrMissingFeeOutput = fmt.Errorf("missing fee output") - ErrInvalidLeftOutput = fmt.Errorf("invalid left output") - ErrInvalidRightOutput = fmt.Errorf("invalid right output") - ErrMissingSweepTapscript = fmt.Errorf("missing sweep tapscript") - ErrInvalidLeaf = fmt.Errorf("leaf node shouldn't have children") - ErrWrongRoundTxid = fmt.Errorf("the input of the tree root is not the round tx's shared output") + ErrInvalidRoundTx = fmt.Errorf("invalid round transaction") + ErrInvalidRoundTxOutputs = fmt.Errorf("invalid number of outputs in round transaction") + ErrEmptyTree = fmt.Errorf("empty vtxo tree") + ErrInvalidRootLevel = fmt.Errorf("root level must have only one node") + ErrNoLeaves = fmt.Errorf("no leaves in the tree") + ErrNodeTxEmpty = fmt.Errorf("node transaction is empty") + ErrNodeTxidEmpty = fmt.Errorf("node txid is empty") + ErrNodeParentTxidEmpty = fmt.Errorf("node parent txid is empty") + ErrNodeTxidDifferent = fmt.Errorf("node txid differs from node transaction") + ErrNumberOfInputs = fmt.Errorf("node transaction should have only one input") + ErrNumberOfOutputs = fmt.Errorf("node transaction should have only three or two outputs") + ErrParentTxidInput = fmt.Errorf("parent txid should be the input of the node transaction") + ErrNumberOfChildren = fmt.Errorf("node branch transaction should have two children") + ErrLeafChildren = fmt.Errorf("leaf node should have max 1 child") + ErrInvalidChildTxid = fmt.Errorf("invalid child txid") + ErrInternalKey = fmt.Errorf("invalid taproot internal key") + ErrInvalidTaprootScript = fmt.Errorf("invalid taproot script") + ErrInvalidAmount = fmt.Errorf("children amount is different from parent amount") + ErrInvalidSweepSequence = fmt.Errorf("invalid sweep sequence") + ErrInvalidServer = fmt.Errorf("invalid server") + ErrMissingFeeOutput = fmt.Errorf("missing fee output") + ErrInvalidLeftOutput = fmt.Errorf("invalid left output") + ErrInvalidRightOutput = fmt.Errorf("invalid right output") + ErrMissingSweepTapscript = fmt.Errorf("missing sweep tapscript") + ErrInvalidLeaf = fmt.Errorf("leaf node shouldn't have children") + ErrWrongRoundTxid = fmt.Errorf("the input of the tree root is not the round tx's shared output") ) // 0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0 @@ -178,11 +174,6 @@ func validateNodeTransaction(node tree.Node, tree tree.VtxoTree, tapTreeRoot []b return ErrNumberOfInputs } - input := decodedPsbt.Inputs[0] - if len(input.TaprootLeafScript) != 1 { - return ErrNumberOfTapscripts - } - prevTxid := decodedPsbt.UnsignedTx.TxIn[0].PreviousOutPoint.Hash.String() if prevTxid != node.ParentTxid { return ErrParentTxidInput @@ -206,38 +197,21 @@ func validateNodeTransaction(node tree.Node, tree tree.VtxoTree, tapTreeRoot []b return ErrInvalidTaprootScript } - inputData := decodedPsbt.Inputs[0] - - inputTapInternalKey, err := schnorr.ParsePubKey(inputData.TaprootInternalKey) - if err != nil { - return fmt.Errorf("invalid internal key: %w", err) - } - cosigners, err := GetCosignerKeys(decodedPsbt.Inputs[0]) if err != nil { return fmt.Errorf("unable to get cosigners keys: %w", err) } - aggregatedKey, err := AggregateKeys(cosigners, tapTreeRoot) - if err != nil { - return fmt.Errorf("unable to aggregate keys: %w", err) - } - - if !bytes.Equal(inputData.TaprootInternalKey, schnorr.SerializePubKey(aggregatedKey.PreTweakedKey)) { - return ErrInternalKey + if len(cosigners) == 0 { + return ErrInvalidTaprootScript } - inputTapLeaf := inputData.TaprootLeafScript[0] - - ctrlBlock, err := txscript.ParseControlBlock(inputTapLeaf.ControlBlock) + aggregatedKey, err := AggregateKeys(cosigners, tapTreeRoot) if err != nil { - return ErrInvalidControlBlock + return fmt.Errorf("unable to aggregate keys: %w", err) } - rootHash := ctrlBlock.RootHash(inputTapLeaf.Script) - tapKey := txscript.ComputeTaprootOutputKey(inputTapInternalKey, rootHash) - - if !bytes.Equal(schnorr.SerializePubKey(tapKey), schnorr.SerializePubKey(aggregatedKey.FinalKey)) { + if !bytes.Equal(schnorr.SerializePubKey(aggregatedKey.FinalKey), previousScriptKey) { return ErrInvalidTaprootScript } diff --git a/common/locktime.go b/common/locktime.go index 7d260e8c4..1cc36c6cb 100644 --- a/common/locktime.go +++ b/common/locktime.go @@ -1,6 +1,7 @@ package common import ( + "encoding/binary" "fmt" "github.com/btcsuite/btcd/blockchain" @@ -44,6 +45,14 @@ type RelativeLocktime struct { Value uint32 } +func NewRelativeLocktimeFromBytes(b []byte) (*RelativeLocktime, error) { + if len(b) != 5 { + return nil, fmt.Errorf("invalid locktime bytes length, expected 5, got %d", len(b)) + } + + return &RelativeLocktime{Type: RelativeLocktimeType(b[0]), Value: binary.BigEndian.Uint32(b[1:])}, nil +} + func (l RelativeLocktime) Seconds() int64 { if l.Type == LocktimeTypeBlock { return int64(l.Value) * SECONDS_PER_BLOCK @@ -69,6 +78,13 @@ func (l RelativeLocktime) LessThan(other RelativeLocktime) bool { return l.Compare(other) < 0 } +func (l RelativeLocktime) Bytes() []byte { + b := make([]byte, 5) + b[0] = byte(l.Type) + binary.BigEndian.PutUint32(b[1:], l.Value) + return b +} + func BIP68Sequence(locktime RelativeLocktime) (uint32, error) { value := locktime.Value isSeconds := locktime.Type == LocktimeTypeSecond diff --git a/pkg/client-sdk/redemption/covenantless_redeem.go b/pkg/client-sdk/redemption/covenantless_redeem.go index bc07be1b7..6e1599284 100644 --- a/pkg/client-sdk/redemption/covenantless_redeem.go +++ b/pkg/client-sdk/redemption/covenantless_redeem.go @@ -7,12 +7,11 @@ import ( "strings" "time" - "github.com/ark-network/ark/common" + "github.com/ark-network/ark/common/bitcointree" "github.com/ark-network/ark/common/tree" "github.com/ark-network/ark/pkg/client-sdk/client" "github.com/ark-network/ark/pkg/client-sdk/explorer" "github.com/btcsuite/btcd/btcutil/psbt" - "github.com/btcsuite/btcd/txscript" ) type CovenantlessRedeemBranch struct { @@ -26,16 +25,23 @@ func NewCovenantlessRedeemBranch( explorer explorer.Explorer, vtxoTree tree.VtxoTree, vtxo client.Vtxo, ) (*CovenantlessRedeemBranch, error) { - _, locktime, err := findCovenantlessSweepClosure(vtxoTree) + root, err := vtxoTree.Root() + if err != nil { + return nil, err + } + + ptxRoot, err := psbt.NewFromRawBytes(strings.NewReader(root.Tx), true) if err != nil { return nil, err } - lifetime, err := time.ParseDuration(fmt.Sprintf("%ds", locktime.Seconds())) + lifetime, err := bitcointree.GetLifetime(ptxRoot.Inputs[0]) if err != nil { return nil, err } + lifetimeDuration := time.Duration(lifetime.Seconds()) * time.Second + nodes, err := vtxoTree.Branch(vtxo.Txid) if err != nil { return nil, err @@ -53,7 +59,7 @@ func NewCovenantlessRedeemBranch( return &CovenantlessRedeemBranch{ vtxo: vtxo, branch: branch, - lifetime: lifetime, + lifetime: lifetimeDuration, explorer: explorer, }, nil } @@ -154,40 +160,3 @@ func (r *CovenantlessRedeemBranch) OffchainPath() ([]*psbt.Packet, error) { return offchainPath, nil } - -func findCovenantlessSweepClosure( - vtxoTree tree.VtxoTree, -) (*txscript.TapLeaf, *common.RelativeLocktime, error) { - root, err := vtxoTree.Root() - if err != nil { - return nil, nil, err - } - - // find the sweep closure - tx, err := psbt.NewFromRawBytes(strings.NewReader(root.Tx), true) - if err != nil { - return nil, nil, err - } - - var locktime *common.RelativeLocktime - var sweepClosure *txscript.TapLeaf - for _, tapLeaf := range tx.Inputs[0].TaprootLeafScript { - closure := &tree.CSVMultisigClosure{} - valid, err := closure.Decode(tapLeaf.Script) - if err != nil { - continue - } - - if valid && (locktime == nil || closure.Locktime.LessThan(*locktime)) { - locktime = &closure.Locktime - leaf := txscript.NewBaseTapLeaf(tapLeaf.Script) - sweepClosure = &leaf - } - } - - if sweepClosure == nil { - return nil, nil, fmt.Errorf("sweep closure not found") - } - - return sweepClosure, locktime, nil -} diff --git a/server/internal/core/application/covenantless.go b/server/internal/core/application/covenantless.go index caffc0bd5..14b17220a 100644 --- a/server/internal/core/application/covenantless.go +++ b/server/internal/core/application/covenantless.go @@ -1004,6 +1004,7 @@ func (s *covenantlessService) startRound() { } func (s *covenantlessService) startFinalization() { + log.Debugf("started finalization stage for round: %s", s.currentRound.Id) ctx := context.Background() round := s.currentRound @@ -1063,6 +1064,7 @@ func (s *covenantlessService) startFinalization() { return } + log.Debugf("building round tx for round %s", round.Id) unsignedRoundTx, vtxoTree, connectorAddress, connectors, err := s.builder.BuildRoundTx( s.pubkey, requests, boardingInputs, connectorAddresses, ) @@ -1274,6 +1276,7 @@ func (s *covenantlessService) finalizeRound(notes []note.Note) { boardingInputs := make([]domain.VtxoKey, 0) roundTx, err := psbt.NewFromRawBytes(strings.NewReader(round.UnsignedTx), true) if err != nil { + log.Debugf("failed to parse round tx: %s", round.UnsignedTx) changes = round.Fail(fmt.Errorf("failed to parse round tx: %s", err)) log.WithError(err).Warn("failed to parse round tx") return diff --git a/server/internal/infrastructure/tx-builder/covenantless/builder.go b/server/internal/infrastructure/tx-builder/covenantless/builder.go index 5e164551b..cced2c7f7 100644 --- a/server/internal/infrastructure/tx-builder/covenantless/builder.go +++ b/server/internal/infrastructure/tx-builder/covenantless/builder.go @@ -622,7 +622,7 @@ func (b *txBuilder) BuildRoundTx( } vtxoTree, err = bitcointree.BuildVtxoTree( - initialOutpoint, receivers, feeAmount, root[:], + initialOutpoint, receivers, feeAmount, root[:], b.roundLifetime, ) if err != nil { return "", nil, "", nil, err @@ -678,7 +678,7 @@ func (b *txBuilder) GetSweepInput(node tree.Node) (lifetime *common.RelativeLock txid := input.PreviousOutPoint.Hash index := input.PreviousOutPoint.Index - sweepLeaf, internalKey, lifetime, err := extractSweepLeaf(partialTx.Inputs[0]) + sweepLeaf, internalKey, lifetime, err := b.extractSweepLeaf(partialTx.Inputs[0]) if err != nil { return nil, nil, err } @@ -1277,27 +1277,84 @@ func castToOutpoints(inputs []ports.TxInput) []ports.TxOutpoint { return outpoints } -func extractSweepLeaf(input psbt.PInput) (sweepLeaf *psbt.TaprootTapLeafScript, internalKey *secp256k1.PublicKey, lifetime *common.RelativeLocktime, err error) { - for _, leaf := range input.TaprootLeafScript { - closure := &tree.CSVMultisigClosure{} - valid, err := closure.Decode(leaf.Script) +func (b *txBuilder) extractSweepLeaf(input psbt.PInput) (sweepLeaf *psbt.TaprootTapLeafScript, internalKey *secp256k1.PublicKey, lifetime *common.RelativeLocktime, err error) { + // this if case is here to handle previous version of the tree + if len(input.TaprootLeafScript) > 0 { + for _, leaf := range input.TaprootLeafScript { + closure := &tree.CSVMultisigClosure{} + valid, err := closure.Decode(leaf.Script) + if err != nil { + return nil, nil, nil, err + } + + if valid && (lifetime == nil || closure.Locktime.LessThan(*lifetime)) { + sweepLeaf = leaf + lifetime = &closure.Locktime + } + } + + internalKey, err = schnorr.ParsePubKey(input.TaprootInternalKey) if err != nil { return nil, nil, nil, err } - if valid && (lifetime == nil || closure.Locktime.LessThan(*lifetime)) { - sweepLeaf = leaf - lifetime = &closure.Locktime + if sweepLeaf == nil { + return nil, nil, nil, fmt.Errorf("sweep leaf not found") } + return sweepLeaf, internalKey, lifetime, nil + } + + serverPubKey, err := b.wallet.GetPubkey(context.Background()) + if err != nil { + return nil, nil, nil, err + } + + cosignerPubKeys, err := bitcointree.GetCosignerKeys(input) + if err != nil { + return nil, nil, nil, err + } + + if len(cosignerPubKeys) == 0 { + return nil, nil, nil, fmt.Errorf("no cosigner pubkeys found") + } + + lifetime, err = bitcointree.GetLifetime(input) + if err != nil { + return nil, nil, nil, err + } + + sweepClosure := &tree.CSVMultisigClosure{ + Locktime: *lifetime, + MultisigClosure: tree.MultisigClosure{ + PubKeys: []*secp256k1.PublicKey{serverPubKey}, + }, + } + + sweepScript, err := sweepClosure.Script() + if err != nil { + return nil, nil, nil, err + } + + sweepTapTree := txscript.AssembleTaprootScriptTree(txscript.NewBaseTapLeaf(sweepScript)) + sweepRoot := sweepTapTree.RootNode.TapHash() + + aggregatedKey, err := bitcointree.AggregateKeys(cosignerPubKeys, sweepRoot[:]) + if err != nil { + return nil, nil, nil, err } + internalKey = aggregatedKey.PreTweakedKey - internalKey, err = schnorr.ParsePubKey(input.TaprootInternalKey) + sweepLeafMerkleProof := sweepTapTree.LeafMerkleProofs[0] + sweepLeafControlBlock := sweepLeafMerkleProof.ToControlBlock(internalKey) + sweepLeafControlBlockBytes, err := sweepLeafControlBlock.ToBytes() if err != nil { return nil, nil, nil, err } - if sweepLeaf == nil { - return nil, nil, nil, fmt.Errorf("sweep leaf not found") + sweepLeaf = &psbt.TaprootTapLeafScript{ + Script: sweepScript, + ControlBlock: sweepLeafControlBlockBytes, + LeafVersion: txscript.BaseLeafVersion, } return sweepLeaf, internalKey, lifetime, nil diff --git a/server/internal/infrastructure/tx-builder/covenantless/builder_test.go b/server/internal/infrastructure/tx-builder/covenantless/builder_test.go index ccc43a7ab..c7bf0afd8 100644 --- a/server/internal/infrastructure/tx-builder/covenantless/builder_test.go +++ b/server/internal/infrastructure/tx-builder/covenantless/builder_test.go @@ -12,7 +12,6 @@ import ( "github.com/ark-network/ark/server/internal/core/domain" "github.com/ark-network/ark/server/internal/core/ports" txbuilder "github.com/ark-network/ark/server/internal/infrastructure/tx-builder/covenantless" - "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -78,14 +77,16 @@ func TestBuildRoundTx(t *testing.T) { requests = append(requests, domain.TxRequest{ Id: request.Id, SignerPubKeys: []string{ - hex.EncodeToString(schnorr.SerializePubKey(randKey.PubKey())), + hex.EncodeToString(randKey.PubKey().SerializeCompressed()), }, SigningType: 0, + Inputs: request.Inputs, + Receivers: request.Receivers, }) } roundTx, vtxoTree, connAddr, _, err := builder.BuildRoundTx( - pubkey, f.Requests, []ports.BoardingInput{}, []string{}, + pubkey, requests, []ports.BoardingInput{}, []string{}, ) require.NoError(t, err) require.NotEmpty(t, roundTx) @@ -105,8 +106,22 @@ func TestBuildRoundTx(t *testing.T) { if len(fixtures.Invalid) > 0 { t.Run("invalid", func(t *testing.T) { for _, f := range fixtures.Invalid { + requests := make([]domain.TxRequest, 0) + + for _, request := range f.Requests { + requests = append(requests, domain.TxRequest{ + Id: request.Id, + SignerPubKeys: []string{ + hex.EncodeToString(pubkey.SerializeCompressed()), + }, + SigningType: 0, + Inputs: request.Inputs, + Receivers: request.Receivers, + }) + } + roundTx, vtxoTree, connAddr, _, err := builder.BuildRoundTx( - pubkey, f.Requests, []ports.BoardingInput{}, []string{}, + pubkey, requests, []ports.BoardingInput{}, []string{}, ) require.EqualError(t, err, f.ExpectedErr) require.Empty(t, roundTx) From 749c38530b6f3f818442423cb84473db8b296be4 Mon Sep 17 00:00:00 2001 From: louisinger Date: Thu, 16 Jan 2025 17:49:24 +0100 Subject: [PATCH 03/21] improve common/musig2.go --- common/bitcointree/musig2.go | 222 +++++++++++++----------- common/bitcointree/musig2_test.go | 184 +++++++++++--------- common/bitcointree/psbt.go | 17 +- common/bitcointree/testdata/musig2.json | 85 --------- 4 files changed, 232 insertions(+), 276 deletions(-) delete mode 100644 common/bitcointree/testdata/musig2.json diff --git a/common/bitcointree/musig2.go b/common/bitcointree/musig2.go index fe535d421..65c9cc09c 100644 --- a/common/bitcointree/musig2.go +++ b/common/bitcointree/musig2.go @@ -49,24 +49,9 @@ func (n *Musig2Nonce) Decode(r io.Reader) error { return nil } -type TreeNonces [][]*Musig2Nonce // public nonces +type TreeNonces [][]*Musig2Nonce // public nonces only type TreePartialSigs [][]*musig2.PartialSignature -type SignerSession interface { - GetPublicKey() string - GetNonces() (TreeNonces, error) // generate tree nonces for this session - SetAggregatedNonces(TreeNonces) // set the aggregated nonces - Sign() (TreePartialSigs, error) // sign the tree -} - -type CoordinatorSession interface { - AddNonce(*btcec.PublicKey, TreeNonces) - AddSig(*btcec.PublicKey, TreePartialSigs) - AggregateNonces() (TreeNonces, error) - // SignTree combines the signatures and add them to the tree's psbts - SignTree() (tree.VtxoTree, error) -} - func (n TreeNonces) Encode(w io.Writer) error { matrix, err := encodeMatrix(n) if err != nil { @@ -95,6 +80,22 @@ func DecodeSignatures(r io.Reader) (TreePartialSigs, error) { return decodeMatrix(func() *musig2.PartialSignature { return new(musig2.PartialSignature) }, r) } +type SignerSession interface { + GetPublicKey() string + GetNonces() (TreeNonces, error) // generate tree nonces for this session + SetAggregatedNonces(TreeNonces) // set the aggregated nonces + Sign() (TreePartialSigs, error) // sign the tree +} + +type CoordinatorSession interface { + AddNonce(*btcec.PublicKey, TreeNonces) + AddSig(*btcec.PublicKey, TreePartialSigs) + AggregateNonces() (TreeNonces, error) + // SignTree combines the signatures and add them to the tree's psbts + SignTree() (tree.VtxoTree, error) +} + +// AggregateKeys is a wrapper around musig2.AggregateKeys using the given scriptRoot as taproot tweak func AggregateKeys( pubkeys []*btcec.PublicKey, scriptRoot []byte, @@ -123,6 +124,8 @@ func AggregateKeys( return key, nil } +// ValidateTreeSigs iterates over the tree matrix and verify the TaprootKeySpendSig +// the public key is rebuilt from the keys set in the unknown field of the psbt func ValidateTreeSigs( scriptRoot []byte, roundSharedOutputAmount int64, @@ -224,62 +227,8 @@ func (t *treeSignerSession) GetPublicKey() string { return hex.EncodeToString(t.secretKey.PubKey().SerializeCompressed()) } -func (t *treeSignerSession) generateNonces() error { - if len(t.txs) == 0 { - return ErrMissingVtxoTree - } - - signerPubKey := t.secretKey.PubKey() - serializedSignerPubKey := schnorr.SerializePubKey(signerPubKey) - - // Pre-allocate the result matrix - myNonces := make([][]*musig2.Nonces, len(t.txs)) - for i := range myNonces { - myNonces[i] = make([]*musig2.Nonces, len(t.txs[i])) - } - - err := workPoolMatrix(t.txs, func(i, j int, partialTx *psbt.Packet) error { - keys, err := GetCosignerKeys(partialTx.Inputs[0]) - if err != nil { - return err - } - - if len(keys) == 0 { - return fmt.Errorf("no keys for txid %s", partialTx.UnsignedTx.TxHash().String()) - } - - mustSign := false - for _, key := range keys { - if bytes.Equal(schnorr.SerializePubKey(key), serializedSignerPubKey) { - mustSign = true - break - } - } - - if !mustSign { - myNonces[i][j] = nil - return nil - } - - nonce, err := musig2.GenNonces( - musig2.WithPublicKey(signerPubKey), - ) - if err != nil { - return err - } - - myNonces[i][j] = nonce - return nil - }) - - if err != nil { - return err - } - - t.myNonces = myNonces - return nil -} - +// GetNonces returns only the public musig2 nonces for each transaction +// where the signer's key is in the list of cosigners func (t *treeSignerSession) GetNonces() (TreeNonces, error) { if len(t.txs) == 0 { return nil, ErrMissingVtxoTree @@ -313,6 +262,7 @@ func (t *treeSignerSession) SetAggregatedNonces(nonces TreeNonces) { t.aggregateNonces = nonces } +// Sign generates the musig2 partial signatures for each transaction where the signer's key is in the list of keys func (t *treeSignerSession) Sign() (TreePartialSigs, error) { if len(t.txs) == 0 { return nil, ErrMissingVtxoTree @@ -322,39 +272,27 @@ func (t *treeSignerSession) Sign() (TreePartialSigs, error) { return nil, errors.New("nonces not set") } - sigs := make(TreePartialSigs, len(t.txs)) - for i := range sigs { - sigs[i] = make([]*musig2.PartialSignature, len(t.txs[i])) + sigs := make(TreePartialSigs, 0, len(t.txs)) + for i := range t.txs { + sigs = append(sigs, make([]*musig2.PartialSignature, len(t.txs[i]))) } signerPubKey := schnorr.SerializePubKey(t.secretKey.PubKey()) if err := workPoolMatrix(t.txs, func(i, j int, partialTx *psbt.Packet) error { - keys, err := GetCosignerKeys(partialTx.Inputs[0]) + mustSign, keys, err := getCosignersPublicKeys(signerPubKey, partialTx) if err != nil { - return fmt.Errorf("failed to get cosigner keys: %w", err) - } - - if len(keys) == 0 { - return fmt.Errorf("no keys for txid %s", partialTx.UnsignedTx.TxHash().String()) - } - - // Check if the signer's key is in the list of keys - mustSign := false - for _, key := range keys { - if bytes.Equal(schnorr.SerializePubKey(key), signerPubKey) { - mustSign = true - break - } + return err } - // Skip signing if not required + // if the signer's key is not in the list of keys, skip signing if !mustSign { sigs[i][j] = nil return nil } - sig, err := t.signPartial(partialTx, i, j, t.secretKey, keys) + // craft musig2 partial signature + sig, err := t.signPartial(partialTx, i, j, keys) if err != nil { return fmt.Errorf("failed to sign partial tx: %w", err) } @@ -368,11 +306,56 @@ func (t *treeSignerSession) Sign() (TreePartialSigs, error) { return sigs, nil } +// generateNonces iterates over the tree matrix and generates musig2 private and public nonces for each transaction +func (t *treeSignerSession) generateNonces() error { + if len(t.txs) == 0 { + return ErrMissingVtxoTree + } + + signerPubKey := t.secretKey.PubKey() + serializedSignerPubKey := schnorr.SerializePubKey(signerPubKey) + + myNonces := make([][]*musig2.Nonces, 0, len(t.txs)) + for i := range t.txs { + myNonces = append(myNonces, make([]*musig2.Nonces, len(t.txs[i]))) + } + + err := workPoolMatrix(t.txs, func(i, j int, partialTx *psbt.Packet) error { + mustGenerateNonce, _, err := getCosignersPublicKeys(serializedSignerPubKey, partialTx) + if err != nil { + return err + } + + // if the signer's key is not in the list of keys, skip generating nonces + if !mustGenerateNonce { + myNonces[i][j] = nil + return nil + } + + // generate musig2 nonces + nonce, err := musig2.GenNonces( + musig2.WithPublicKey(signerPubKey), + ) + if err != nil { + return err + } + + myNonces[i][j] = nonce + return nil + }) + + if err != nil { + return err + } + + t.myNonces = myNonces + return nil +} + +// signPartial signs the given transaction at the position (posx, posy) func (t *treeSignerSession) signPartial( partialTx *psbt.Packet, - posx int, - posy int, - seckey *btcec.PrivateKey, + posx int, posy int, keys []*btcec.PublicKey, ) (*musig2.PartialSignature, error) { prevoutFetcher, err := t.prevoutFetcherFactory(partialTx) @@ -395,7 +378,7 @@ func (t *treeSignerSession) signPartial( } return musig2.Sign( - myNonce.SecNonce, seckey, aggregatedNonce.PubNonce, keys, [32]byte(message), + myNonce.SecNonce, t.secretKey, aggregatedNonce.PubNonce, keys, [32]byte(message), musig2.WithSortedKeys(), musig2.WithTaprootSignTweak(t.scriptRoot), musig2.WithFastSign(), ) } @@ -442,6 +425,8 @@ func (t *treeCoordinatorSession) AddSig(pubkey *btcec.PublicKey, sig TreePartial t.sigs[hex.EncodeToString(schnorr.SerializePubKey(pubkey))] = sig } +// AggregateNonces aggregates the musig2 nonces for each transaction in the tree +// it returns an error if any of the nonces are not set func (t *treeCoordinatorSession) AggregateNonces() (TreeNonces, error) { for _, nonce := range t.nonces { if nonce == nil { @@ -449,9 +434,9 @@ func (t *treeCoordinatorSession) AggregateNonces() (TreeNonces, error) { } } - aggregatedNonces := make(TreeNonces, len(t.txs)) - for i := range aggregatedNonces { - aggregatedNonces[i] = make([]*Musig2Nonce, len(t.txs[i])) + aggregatedNonces := make(TreeNonces, 0, len(t.txs)) + for i := range t.txs { + aggregatedNonces = append(aggregatedNonces, make([]*Musig2Nonce, len(t.txs[i]))) } err := workPoolMatrix(t.txs, func(i, j int, partialTx *psbt.Packet) error { @@ -481,6 +466,14 @@ func (t *treeCoordinatorSession) AggregateNonces() (TreeNonces, error) { nonces = append(nonces, nonce.PubNonce) } + if len(nonces) == 0 { + return fmt.Errorf("missing nonces for txid %s", partialTx.UnsignedTx.TxHash().String()) + } + + if len(nonces) != len(keys) { + return fmt.Errorf("wrong number of nonces for txid %s, expected %d got %d", partialTx.UnsignedTx.TxHash().String(), len(keys), len(nonces)) + } + aggregatedNonce, err := musig2.AggregateNonces(nonces) if err != nil { return fmt.Errorf("failed to aggregate nonces: %w", err) @@ -497,10 +490,12 @@ func (t *treeCoordinatorSession) AggregateNonces() (TreeNonces, error) { return aggregatedNonces, nil } +// SignTree combines the signatures and add them to the tree's psbts +// it returns the vtxo tree with the signed transactions set as TaprootKeySpendSig func (t *treeCoordinatorSession) SignTree() (tree.VtxoTree, error) { - signedTree := make(tree.VtxoTree, len(t.txs)) - for i := range signedTree { - signedTree[i] = make([]tree.Node, len(t.txs[i])) + signedTree := make(tree.VtxoTree, 0, len(t.txs)) + for i := range t.txs { + signedTree = append(signedTree, make([]tree.Node, len(t.txs[i]))) } if err := workPoolMatrix(t.txs, func(i, j int, partialTx *psbt.Packet) error { @@ -553,6 +548,14 @@ func (t *treeCoordinatorSession) SignTree() (tree.VtxoTree, error) { return err } + if len(sigs) == 0 { + return fmt.Errorf("missing signatures for txid %s", partialTx.UnsignedTx.TxHash().String()) + } + + if len(sigs) != len(keys) { + return fmt.Errorf("wrong number of signatures for txid %s, expected %d got %d", partialTx.UnsignedTx.TxHash().String(), len(keys), len(sigs)) + } + combinedSig := musig2.CombineSigs( combinedNonce, sigs, musig2.WithTaprootTweakedCombine([32]byte(message), keys, t.scriptRoot, true), @@ -823,3 +826,18 @@ func workPoolMatrix[T any](matrix [][]T, processItem func(i, j int, item T) erro return processItem(item.i, item.j, item.item) }) } + +// getCosignersPublicKeys extract the set of cosigners public keys from the tx and check if the signer's key is in the set +func getCosignersPublicKeys(signerPubKey []byte, tx *psbt.Packet) (bool, []*secp256k1.PublicKey, error) { + keys, err := GetCosignerKeys(tx.Inputs[0]) + if err != nil { + return false, nil, err + } + + for _, key := range keys { + if bytes.Equal(schnorr.SerializePubKey(key), signerPubKey) { + return true, keys, nil + } + } + return false, nil, nil +} diff --git a/common/bitcointree/musig2_test.go b/common/bitcointree/musig2_test.go index 83347fcd4..d1f70598e 100644 --- a/common/bitcointree/musig2_test.go +++ b/common/bitcointree/musig2_test.go @@ -2,14 +2,13 @@ package bitcointree_test import ( "encoding/hex" - "encoding/json" "fmt" - "os" "testing" "github.com/ark-network/ark/common" "github.com/ark-network/ark/common/bitcointree" "github.com/ark-network/ark/common/tree" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" @@ -22,49 +21,25 @@ const ( exitDelay = 512 ) -var lifetime = common.RelativeLocktime{Type: common.LocktimeTypeBlock, Value: 144} - -var testTxid, _ = chainhash.NewHashFromStr("49f8664acc899be91902f8ade781b7eeb9cbe22bdd9efbc36e56195de21bcd12") +var ( + lifetime = common.RelativeLocktime{Type: common.LocktimeTypeBlock, Value: 144} + testTxid, _ = chainhash.NewHashFromStr("49f8664acc899be91902f8ade781b7eeb9cbe22bdd9efbc36e56195de21bcd12") + serverPrivKey, _ = secp256k1.GeneratePrivateKey() + sweepScript, _ = (&tree.CSVMultisigClosure{ + MultisigClosure: tree.MultisigClosure{PubKeys: []*secp256k1.PublicKey{serverPrivKey.PubKey()}}, + Locktime: lifetime, + }).Script() + sweepRoot = txscript.NewBaseTapLeaf(sweepScript).TapHash() + receiverCounts = []int{1, 2, 20, 128} +) -func TestRoundTripSignTree(t *testing.T) { +func TestBuildAndSignVtxoTree(t *testing.T) { t.Parallel() - fixtures := parseFixtures(t) - for i, f := range fixtures.Valid { - t.Run(fmt.Sprintf("test %d", i), func(t *testing.T) { - server, err := secp256k1.GeneratePrivateKey() - require.NoError(t, err) - - sweepScript, err := (&tree.CSVMultisigClosure{ - MultisigClosure: tree.MultisigClosure{PubKeys: []*secp256k1.PublicKey{server.PubKey()}}, - Locktime: lifetime, - }).Script() - require.NoError(t, err) - - sweepTapLeaf := txscript.NewBaseTapLeaf(sweepScript) - sweepRoot := sweepTapLeaf.TapHash() - - receivers := make([]tree.VtxoLeaf, 0, len(f.Receivers)) - - privKeys := make([]*secp256k1.PrivateKey, 0, len(receivers)) - for i, r := range castReceivers(f.Receivers) { - receiver := r - prvkey, err := secp256k1.GeneratePrivateKey() - require.NoError(t, err) - privKeys = append(privKeys, prvkey) - - receiver.SignersPublicKeys = []string{ - hex.EncodeToString(prvkey.PubKey().SerializeCompressed()), - } - if i%2 == 0 { - receiver.Type = tree.SignAll - } else { - receiver.Type = tree.SignBranch - } - receivers = append(receivers, receiver) - } + for _, tc := range generateTestCases(t) { + t.Run(tc.name, func(t *testing.T) { _, sharedOutputAmount, err := bitcointree.CraftSharedOutput( - receivers, + tc.receivers, minRelayFee, sweepRoot[:], ) @@ -75,7 +50,7 @@ func TestRoundTripSignTree(t *testing.T) { Hash: *testTxid, Index: 0, }, - receivers, + tc.receivers, minRelayFee, sweepRoot[:], lifetime, @@ -89,38 +64,46 @@ func TestRoundTripSignTree(t *testing.T) { ) require.NoError(t, err) - // Create signer sessions for all cosigners - signerSessions := make([]bitcointree.SignerSession, len(receivers)) - for i, prvkey := range privKeys { - signerSessions[i], err = bitcointree.NewTreeSignerSession(prvkey, sharedOutputAmount, vtxoTree, sweepRoot[:]) + // Cceate signer sessions for each receivers + signerSessions := make(map[*btcec.PublicKey]bitcointree.SignerSession) + for _, prvkey := range tc.privKeys { + session, err := bitcointree.NewTreeSignerSession(prvkey, sharedOutputAmount, vtxoTree, sweepRoot[:]) require.NoError(t, err) + signerSessions[prvkey.PubKey()] = session } - // Get nonces from all signers - for i, session := range signerSessions { + // ddd server's signer session + serverSession, err := bitcointree.NewTreeSignerSession(serverPrivKey, sharedOutputAmount, vtxoTree, sweepRoot[:]) + require.NoError(t, err) + signerSessions[serverPrivKey.PubKey()] = serverSession + + // generate nonces from all signers + for pubkey, session := range signerSessions { nonces, err := session.GetNonces() require.NoError(t, err) - serverCoordinator.AddNonce(privKeys[i].PubKey(), nonces) + serverCoordinator.AddNonce(pubkey, nonces) } aggregatedNonce, err := serverCoordinator.AggregateNonces() require.NoError(t, err) - // Set keys and aggregated nonces for all signers + // set the aggregated nonces for all signers sessions for _, session := range signerSessions { session.SetAggregatedNonces(aggregatedNonce) } - // Get signatures from all signers - for i, session := range signerSessions { + // get signatures from all signers sessions + for pubkey, session := range signerSessions { sig, err := session.Sign() require.NoError(t, err) - serverCoordinator.AddSig(privKeys[i].PubKey(), sig) + serverCoordinator.AddSig(pubkey, sig) } + // aggregate signatures signedTree, err := serverCoordinator.SignTree() require.NoError(t, err) + // validate signatures err = bitcointree.ValidateTreeSigs( sweepRoot[:], sharedOutputAmount, @@ -131,40 +114,81 @@ func TestRoundTripSignTree(t *testing.T) { } } -type receiverFixture struct { - Amount int64 `json:"amount"` - Pubkey string `json:"pubkey"` +type testCase struct { + name string + receivers []tree.VtxoLeaf + privKeys []*secp256k1.PrivateKey } -func castReceivers(receivers []receiverFixture) []tree.VtxoLeaf { - receiversOut := make([]tree.VtxoLeaf, 0, len(receivers)) - for _, r := range receivers { - receiversOut = append(receiversOut, tree.VtxoLeaf{ - PubKey: r.Pubkey, - Amount: uint64(r.Amount), +func generateReceiversFixture(count int) ([]tree.VtxoLeaf, []*secp256k1.PrivateKey, error) { + receivers := make([]tree.VtxoLeaf, 0, count) + privKeys := make([]*secp256k1.PrivateKey, 0, count) + for i := 0; i < count; i++ { + prvkey, err := secp256k1.GeneratePrivateKey() + if err != nil { + return nil, nil, err + } + receivers = append(receivers, tree.VtxoLeaf{ + PubKey: "0000000000000000000000000000000000000000000000000000000000000002", + Amount: uint64((i + 1) * 1000), + SignersPublicKeys: []string{ + hex.EncodeToString(prvkey.PubKey().SerializeCompressed()), + hex.EncodeToString(serverPrivKey.PubKey().SerializeCompressed()), + }, }) + privKeys = append(privKeys, prvkey) } - return receiversOut + return receivers, privKeys, nil } -type fixture struct { - Valid []struct { - Receivers []receiverFixture `json:"receivers"` - } `json:"valid"` +func withSigningType(signingType tree.SigningType, receivers []tree.VtxoLeaf) []tree.VtxoLeaf { + newReceivers := make([]tree.VtxoLeaf, 0, len(receivers)) + for _, receiver := range receivers { + newReceivers = append(newReceivers, tree.VtxoLeaf{ + PubKey: receiver.PubKey, + Amount: receiver.Amount, + SignersPublicKeys: receiver.SignersPublicKeys, + Type: signingType, + }) + } + return newReceivers } -func parseFixtures(t *testing.T) fixture { - file, err := os.ReadFile("testdata/musig2.json") - require.NoError(t, err) - v := map[string]interface{}{} - err = json.Unmarshal(file, &v) - require.NoError(t, err) - - vv := v["treeSignature"].(map[string]interface{}) - file, _ = json.Marshal(vv) - var fixtures fixture - err = json.Unmarshal(file, &fixtures) - require.NoError(t, err) +func withMixedSigningTypes(receivers []tree.VtxoLeaf) []tree.VtxoLeaf { + first := withSigningType(tree.SignAll, receivers[:len(receivers)/2]) + second := withSigningType(tree.SignBranch, receivers[len(receivers)/2:]) + return append(first, second...) +} - return fixtures +func generateTestCases(t *testing.T) []testCase { + testCases := make([]testCase, 0) + for _, count := range receiverCounts { + receivers, privKeys, err := generateReceiversFixture(count) + require.NoError(t, err) + // add mixed types test case if count is between 2 and 32 + if count > 1 && count < 32 { + testCases = append(testCases, testCase{ + name: fmt.Sprintf("%d receivers Mixed Signing Types", len(receivers)), + receivers: withMixedSigningTypes(receivers), + privKeys: privKeys, + }) + } + + // add SignAll test case if count is less than 32 + if count < 32 { + testCases = append(testCases, testCase{ + name: fmt.Sprintf("%d receivers SignAll", len(receivers)), + receivers: withSigningType(tree.SignAll, receivers), + privKeys: privKeys, + }) + } + + // always add SignBranch test case + testCases = append(testCases, testCase{ + name: fmt.Sprintf("%d receivers SignBranch", len(receivers)), + receivers: withSigningType(tree.SignBranch, receivers), + privKeys: privKeys, + }) + } + return testCases } diff --git a/common/bitcointree/psbt.go b/common/bitcointree/psbt.go index 07842c10b..90db3ab27 100644 --- a/common/bitcointree/psbt.go +++ b/common/bitcointree/psbt.go @@ -2,6 +2,7 @@ package bitcointree import ( "bytes" + "encoding/binary" "github.com/ark-network/ark/common" "github.com/ark-network/ark/common/tree" @@ -79,8 +80,7 @@ func AddCosignerKey(inIndex int, ptx *psbt.Packet, key *secp256k1.PublicKey) err func GetCosignerKeys(in psbt.PInput) ([]*secp256k1.PublicKey, error) { var keys []*secp256k1.PublicKey for _, u := range in.Unknowns { - cosignerIndex := parsePrefixedCosignerKey(u.Key) - if cosignerIndex == -1 { + if !parsePrefixedCosignerKey(u.Key) { continue } @@ -96,13 +96,12 @@ func GetCosignerKeys(in psbt.PInput) ([]*secp256k1.PublicKey, error) { } func cosignerPrefixedKey(index int) []byte { - return append(COSIGNER_PSBT_KEY_PREFIX, byte(index)) -} + indexBytes := make([]byte, 4) + binary.BigEndian.PutUint32(indexBytes, uint32(index)) -func parsePrefixedCosignerKey(key []byte) int { - if !bytes.HasPrefix(key, COSIGNER_PSBT_KEY_PREFIX) { - return -1 - } + return append(COSIGNER_PSBT_KEY_PREFIX, indexBytes...) +} - return int(key[len(COSIGNER_PSBT_KEY_PREFIX)]) +func parsePrefixedCosignerKey(key []byte) bool { + return bytes.HasPrefix(key, COSIGNER_PSBT_KEY_PREFIX) } diff --git a/common/bitcointree/testdata/musig2.json b/common/bitcointree/testdata/musig2.json deleted file mode 100644 index 3267e124e..000000000 --- a/common/bitcointree/testdata/musig2.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "treeSignature": { - "valid": [ - { - "receivers": [ - {"amount": 1000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 2000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"} - ] - }, - { - "receivers": [ - {"amount": 1000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 2000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 3000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"} - ] - }, - { - "receivers": [ - {"amount": 1000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 2000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 3000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 4000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"} - ] - }, - { - "receivers": [ - {"amount": 1000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 2000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 3000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 4000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 5000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"} - ] - }, - { - "receivers": [ - {"amount": 1000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 2000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 3000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 4000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 5000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 6000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"} - ] - }, - { - "receivers": [ - {"amount": 1000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 2000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 3000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 4000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 5000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 6000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 7000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 8000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 9000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 10000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 11000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 12000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 13000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 14000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 15000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 16000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 17000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 18000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 19000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 20000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 21000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 22000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 23000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 24000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 25000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 26000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 27000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 28000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 29000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 30000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 31000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 32000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 33000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 34000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"}, - {"amount": 35000, "pubkey": "0000000000000000000000000000000000000000000000000000000000000002"} - ] - } - ] - } -} From 27476bbdbf6548cb3455f19db48728cd685815a5 Mon Sep 17 00:00:00 2001 From: louisinger Date: Thu, 16 Jan 2025 17:50:55 +0100 Subject: [PATCH 04/21] validation.go error message --- common/bitcointree/validation.go | 55 ++++++++++++++++---------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/common/bitcointree/validation.go b/common/bitcointree/validation.go index 39d270a2f..e0fe97fc8 100644 --- a/common/bitcointree/validation.go +++ b/common/bitcointree/validation.go @@ -15,32 +15,33 @@ import ( ) var ( - ErrInvalidRoundTx = fmt.Errorf("invalid round transaction") - ErrInvalidRoundTxOutputs = fmt.Errorf("invalid number of outputs in round transaction") - ErrEmptyTree = fmt.Errorf("empty vtxo tree") - ErrInvalidRootLevel = fmt.Errorf("root level must have only one node") - ErrNoLeaves = fmt.Errorf("no leaves in the tree") - ErrNodeTxEmpty = fmt.Errorf("node transaction is empty") - ErrNodeTxidEmpty = fmt.Errorf("node txid is empty") - ErrNodeParentTxidEmpty = fmt.Errorf("node parent txid is empty") - ErrNodeTxidDifferent = fmt.Errorf("node txid differs from node transaction") - ErrNumberOfInputs = fmt.Errorf("node transaction should have only one input") - ErrNumberOfOutputs = fmt.Errorf("node transaction should have only three or two outputs") - ErrParentTxidInput = fmt.Errorf("parent txid should be the input of the node transaction") - ErrNumberOfChildren = fmt.Errorf("node branch transaction should have two children") - ErrLeafChildren = fmt.Errorf("leaf node should have max 1 child") - ErrInvalidChildTxid = fmt.Errorf("invalid child txid") - ErrInternalKey = fmt.Errorf("invalid taproot internal key") - ErrInvalidTaprootScript = fmt.Errorf("invalid taproot script") - ErrInvalidAmount = fmt.Errorf("children amount is different from parent amount") - ErrInvalidSweepSequence = fmt.Errorf("invalid sweep sequence") - ErrInvalidServer = fmt.Errorf("invalid server") - ErrMissingFeeOutput = fmt.Errorf("missing fee output") - ErrInvalidLeftOutput = fmt.Errorf("invalid left output") - ErrInvalidRightOutput = fmt.Errorf("invalid right output") - ErrMissingSweepTapscript = fmt.Errorf("missing sweep tapscript") - ErrInvalidLeaf = fmt.Errorf("leaf node shouldn't have children") - ErrWrongRoundTxid = fmt.Errorf("the input of the tree root is not the round tx's shared output") + ErrInvalidRoundTx = fmt.Errorf("invalid round transaction") + ErrInvalidRoundTxOutputs = fmt.Errorf("invalid number of outputs in round transaction") + ErrEmptyTree = fmt.Errorf("empty vtxo tree") + ErrInvalidRootLevel = fmt.Errorf("root level must have only one node") + ErrNoLeaves = fmt.Errorf("no leaves in the tree") + ErrNodeTxEmpty = fmt.Errorf("node transaction is empty") + ErrNodeTxidEmpty = fmt.Errorf("node txid is empty") + ErrNodeParentTxidEmpty = fmt.Errorf("node parent txid is empty") + ErrNodeTxidDifferent = fmt.Errorf("node txid differs from node transaction") + ErrNumberOfInputs = fmt.Errorf("node transaction should have only one input") + ErrNumberOfOutputs = fmt.Errorf("node transaction should have only three or two outputs") + ErrParentTxidInput = fmt.Errorf("parent txid should be the input of the node transaction") + ErrNumberOfChildren = fmt.Errorf("node branch transaction should have two children") + ErrLeafChildren = fmt.Errorf("leaf node should have max 1 child") + ErrInvalidChildTxid = fmt.Errorf("invalid child txid") + ErrInternalKey = fmt.Errorf("invalid taproot internal key") + ErrInvalidTaprootScript = fmt.Errorf("invalid taproot script") + ErrMissingCosignersPublicKeys = fmt.Errorf("missing cosigners public keys") + ErrInvalidAmount = fmt.Errorf("children amount is different from parent amount") + ErrInvalidSweepSequence = fmt.Errorf("invalid sweep sequence") + ErrInvalidServer = fmt.Errorf("invalid server") + ErrMissingFeeOutput = fmt.Errorf("missing fee output") + ErrInvalidLeftOutput = fmt.Errorf("invalid left output") + ErrInvalidRightOutput = fmt.Errorf("invalid right output") + ErrMissingSweepTapscript = fmt.Errorf("missing sweep tapscript") + ErrInvalidLeaf = fmt.Errorf("leaf node shouldn't have children") + ErrWrongRoundTxid = fmt.Errorf("the input of the tree root is not the round tx's shared output") ) // 0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0 @@ -203,7 +204,7 @@ func validateNodeTransaction(node tree.Node, tree tree.VtxoTree, tapTreeRoot []b } if len(cosigners) == 0 { - return ErrInvalidTaprootScript + return ErrMissingCosignersPublicKeys } aggregatedKey, err := AggregateKeys(cosigners, tapTreeRoot) From 09e68f8a79242a14e059c49b1283fd12781c0b9e Mon Sep 17 00:00:00 2001 From: Louis Singer <41042567+louisinger@users.noreply.github.com> Date: Thu, 16 Jan 2025 18:20:07 +0100 Subject: [PATCH 05/21] Update server/internal/core/application/covenantless.go Co-authored-by: Pietralberto Mazza <18440657+altafan@users.noreply.github.com> Signed-off-by: Louis Singer <41042567+louisinger@users.noreply.github.com> --- server/internal/core/application/covenantless.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/internal/core/application/covenantless.go b/server/internal/core/application/covenantless.go index 14b17220a..beadf4828 100644 --- a/server/internal/core/application/covenantless.go +++ b/server/internal/core/application/covenantless.go @@ -1064,7 +1064,7 @@ func (s *covenantlessService) startFinalization() { return } - log.Debugf("building round tx for round %s", round.Id) + log.Debugf("building tx for round %s", round.Id) unsignedRoundTx, vtxoTree, connectorAddress, connectors, err := s.builder.BuildRoundTx( s.pubkey, requests, boardingInputs, connectorAddresses, ) From 3de9a03ff75dcd4fbe4f7540e60a380d15625175 Mon Sep 17 00:00:00 2001 From: Louis Singer <41042567+louisinger@users.noreply.github.com> Date: Thu, 16 Jan 2025 18:20:37 +0100 Subject: [PATCH 06/21] Update common/bitcointree/builder.go Co-authored-by: Pietralberto Mazza <18440657+altafan@users.noreply.github.com> Signed-off-by: Louis Singer <41042567+louisinger@users.noreply.github.com> --- common/bitcointree/builder.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/bitcointree/builder.go b/common/bitcointree/builder.go index 39893457a..71929848e 100644 --- a/common/bitcointree/builder.go +++ b/common/bitcointree/builder.go @@ -14,7 +14,7 @@ import ( "github.com/decred/dcrd/dcrec/secp256k1/v4" ) -// CraftSharedOutput returns the taproot script and the amount of the initial root shared output of a vtxo tree +// CraftSharedOutput returns the taproot script and the amount of the root shared output of a vtxo tree func CraftSharedOutput( receivers []tree.VtxoLeaf, feeSatsPerNode uint64, From c6936ee8cfe425a43d6acebf02e726c24f2346c8 Mon Sep 17 00:00:00 2001 From: louisinger Date: Thu, 16 Jan 2025 18:42:22 +0100 Subject: [PATCH 07/21] add psbt_test.go & fix lifetime encoding --- common/bitcointree/psbt.go | 25 +++++++- common/bitcointree/psbt_test.go | 108 ++++++++++++++++++++++++++++++++ common/locktime.go | 16 ----- 3 files changed, 131 insertions(+), 18 deletions(-) create mode 100644 common/bitcointree/psbt_test.go diff --git a/common/bitcointree/psbt.go b/common/bitcointree/psbt.go index 90db3ab27..fb959628c 100644 --- a/common/bitcointree/psbt.go +++ b/common/bitcointree/psbt.go @@ -43,8 +43,29 @@ func GetConditionWitness(in psbt.PInput) (wire.TxWitness, error) { } func AddLifetime(inIndex int, ptx *psbt.Packet, lifetime common.RelativeLocktime) error { + sequence, err := common.BIP68Sequence(lifetime) + if err != nil { + return err + } + + // the sequence must be encoded as minimal little-endian bytes + var sequenceLE [4]byte + binary.LittleEndian.PutUint32(sequenceLE[:], sequence) + + // compute the minimum number of bytes needed + numBytes := 4 + for numBytes > 1 && sequenceLE[numBytes-1] == 0 { + numBytes-- // remove trailing zeros + } + + // if the most significant bit of the last byte is set, + // we need one more byte to avoid sign ambiguity + if sequenceLE[numBytes-1]&0x80 != 0 { + numBytes++ + } + ptx.Inputs[inIndex].Unknowns = append(ptx.Inputs[inIndex].Unknowns, &psbt.Unknown{ - Value: lifetime.Bytes(), + Value: sequenceLE[:numBytes], Key: LIFETIME_PSBT_KEY, }) @@ -54,7 +75,7 @@ func AddLifetime(inIndex int, ptx *psbt.Packet, lifetime common.RelativeLocktime func GetLifetime(in psbt.PInput) (*common.RelativeLocktime, error) { for _, u := range in.Unknowns { if bytes.Contains(u.Key, LIFETIME_PSBT_KEY) { - return common.NewRelativeLocktimeFromBytes(u.Value) + return common.BIP68DecodeSequence(u.Value) } } diff --git a/common/bitcointree/psbt_test.go b/common/bitcointree/psbt_test.go new file mode 100644 index 000000000..50bc377f5 --- /dev/null +++ b/common/bitcointree/psbt_test.go @@ -0,0 +1,108 @@ +package bitcointree_test + +import ( + "testing" + + "github.com/ark-network/ark/common" + "github.com/ark-network/ark/common/bitcointree" + "github.com/btcsuite/btcd/btcutil/psbt" + "github.com/btcsuite/btcd/wire" + "github.com/decred/dcrd/dcrec/secp256k1/v4" + "github.com/stretchr/testify/require" +) + +func TestPsbtCustomUnknownFields(t *testing.T) { + t.Run("condition witness", func(t *testing.T) { + // Create a new PSBT + ptx, err := psbt.New(nil, nil, 2, 0, nil) + require.NoError(t, err) + + // Add an empty input since we need at least one + ptx.UnsignedTx.TxIn = []*wire.TxIn{{ + PreviousOutPoint: wire.OutPoint{}, + Sequence: 0, + }} + ptx.Inputs = []psbt.PInput{{}} + + // Create a sample witness + witness := wire.TxWitness{ + []byte{0x01, 0x02}, + []byte{0x03, 0x04}, + } + + // Add witness to input 0 + err = bitcointree.AddConditionWitness(0, ptx, witness) + require.NoError(t, err) + + // Get witness back and verify + retrievedWitness, err := bitcointree.GetConditionWitness(ptx.Inputs[0]) + require.NoError(t, err) + require.Equal(t, len(witness), len(retrievedWitness)) + + for i := range witness { + require.Equal(t, witness[i], retrievedWitness[i]) + } + }) + + t.Run("lifetime", func(t *testing.T) { + // Create a new PSBT + ptx, err := psbt.New(nil, nil, 2, 0, nil) + require.NoError(t, err) + + // Add an empty input + ptx.UnsignedTx.TxIn = []*wire.TxIn{{ + PreviousOutPoint: wire.OutPoint{}, + Sequence: 0, + }} + ptx.Inputs = []psbt.PInput{{}} + + // Add lifetime + lifetime := common.RelativeLocktime{ + Type: common.LocktimeTypeBlock, + Value: 144, // 1 day worth of blocks + } + err = bitcointree.AddLifetime(0, ptx, lifetime) + require.NoError(t, err) + + // Get lifetime back and verify + retrievedLifetime, err := bitcointree.GetLifetime(ptx.Inputs[0]) + require.NoError(t, err) + require.NotNil(t, retrievedLifetime) + require.Equal(t, lifetime.Type, retrievedLifetime.Type) + require.Equal(t, lifetime.Value, retrievedLifetime.Value) + }) + + t.Run("cosigner keys", func(t *testing.T) { + // Create a new PSBT + ptx, err := psbt.New(nil, nil, 2, 0, nil) + require.NoError(t, err) + + // Add an empty input + ptx.UnsignedTx.TxIn = []*wire.TxIn{{ + PreviousOutPoint: wire.OutPoint{}, + Sequence: 0, + }} + ptx.Inputs = []psbt.PInput{{}} + + // Create and add 40 cosigner keys + var keys []*secp256k1.PublicKey + for i := 0; i < 40; i++ { + key, err := secp256k1.GeneratePrivateKey() + require.NoError(t, err) + keys = append(keys, key.PubKey()) + + err = bitcointree.AddCosignerKey(0, ptx, key.PubKey()) + require.NoError(t, err) + } + + // Get cosigner keys back and verify + retrievedKeys, err := bitcointree.GetCosignerKeys(ptx.Inputs[0]) + require.NoError(t, err) + require.Len(t, retrievedKeys, 40) + + // Verify each key matches and is in the correct order + for i := 0; i < 40; i++ { + require.Equal(t, keys[i].SerializeCompressed(), retrievedKeys[i].SerializeCompressed()) + } + }) +} diff --git a/common/locktime.go b/common/locktime.go index 1cc36c6cb..7d260e8c4 100644 --- a/common/locktime.go +++ b/common/locktime.go @@ -1,7 +1,6 @@ package common import ( - "encoding/binary" "fmt" "github.com/btcsuite/btcd/blockchain" @@ -45,14 +44,6 @@ type RelativeLocktime struct { Value uint32 } -func NewRelativeLocktimeFromBytes(b []byte) (*RelativeLocktime, error) { - if len(b) != 5 { - return nil, fmt.Errorf("invalid locktime bytes length, expected 5, got %d", len(b)) - } - - return &RelativeLocktime{Type: RelativeLocktimeType(b[0]), Value: binary.BigEndian.Uint32(b[1:])}, nil -} - func (l RelativeLocktime) Seconds() int64 { if l.Type == LocktimeTypeBlock { return int64(l.Value) * SECONDS_PER_BLOCK @@ -78,13 +69,6 @@ func (l RelativeLocktime) LessThan(other RelativeLocktime) bool { return l.Compare(other) < 0 } -func (l RelativeLocktime) Bytes() []byte { - b := make([]byte, 5) - b[0] = byte(l.Type) - binary.BigEndian.PutUint32(b[1:], l.Value) - return b -} - func BIP68Sequence(locktime RelativeLocktime) (uint32, error) { value := locktime.Value isSeconds := locktime.Type == LocktimeTypeSecond From 79b88660ac1b5d70fca6a61e56f4800b7a62552d Mon Sep 17 00:00:00 2001 From: louisinger Date: Thu, 16 Jan 2025 20:30:04 +0100 Subject: [PATCH 08/21] fix application, APIs and clients with tree.Musig2 struct --- .../swagger/ark/v1/service.swagger.json | 28 +- api-spec/protobuf/ark/v1/service.proto | 10 +- api-spec/protobuf/gen/ark/v1/service.pb.go | 1283 +++++++++-------- common/bitcointree/builder.go | 18 +- common/bitcointree/musig2_test.go | 19 +- common/tree/type.go | 12 +- pkg/client-sdk/client/client.go | 6 +- pkg/client-sdk/client/grpc/client.go | 20 +- pkg/client-sdk/client/rest/client.go | 22 +- .../client/rest/service/models/v1_musig2.go | 53 + ..._register_inputs_for_next_round_request.go | 6 - ...register_outputs_for_next_round_request.go | 51 + pkg/client-sdk/covenant_client.go | 8 +- pkg/client-sdk/covenantless_client.go | 38 +- server/internal/core/application/covenant.go | 10 +- .../internal/core/application/covenantless.go | 69 +- server/internal/core/application/types.go | 7 +- server/internal/core/application/utils.go | 33 +- server/internal/core/domain/payment.go | 16 +- server/internal/core/ports/tx_builder.go | 1 + .../tx-builder/covenant/builder.go | 1 + .../tx-builder/covenant/builder_test.go | 4 +- .../tx-builder/covenantless/builder.go | 9 +- .../tx-builder/covenantless/builder_test.go | 27 +- .../tx-builder/covenantless/utils.go | 16 +- .../interface/grpc/handlers/arkservice.go | 16 +- 26 files changed, 1002 insertions(+), 781 deletions(-) create mode 100644 pkg/client-sdk/client/rest/service/models/v1_musig2.go diff --git a/api-spec/openapi/swagger/ark/v1/service.swagger.json b/api-spec/openapi/swagger/ark/v1/service.swagger.json index b726e9ae7..820e1a412 100644 --- a/api-spec/openapi/swagger/ark/v1/service.swagger.json +++ b/api-spec/openapi/swagger/ark/v1/service.swagger.json @@ -717,6 +717,21 @@ } } }, + "v1Musig2": { + "type": "object", + "properties": { + "cosignersPublicKeys": { + "type": "array", + "items": { + "type": "string" + } + }, + "signingType": { + "type": "integer", + "format": "int64" + } + } + }, "v1Node": { "type": "object", "properties": { @@ -808,21 +823,11 @@ "$ref": "#/definitions/v1Input" } }, - "signerPubkeys": { - "type": "array", - "items": { - "type": "string" - } - }, "notes": { "type": "array", "items": { "type": "string" } - }, - "signingType": { - "type": "integer", - "format": "int64" } } }, @@ -847,6 +852,9 @@ "$ref": "#/definitions/v1Output" }, "description": "List of receivers for to convert to leaves in the next VTXO tree." + }, + "musig2": { + "$ref": "#/definitions/v1Musig2" } } }, diff --git a/api-spec/protobuf/ark/v1/service.proto b/api-spec/protobuf/ark/v1/service.proto index be06dc5ec..ca34034d5 100755 --- a/api-spec/protobuf/ark/v1/service.proto +++ b/api-spec/protobuf/ark/v1/service.proto @@ -140,9 +140,7 @@ message GetBoardingAddressResponse { message RegisterInputsForNextRoundRequest { repeated Input inputs = 1; - repeated string signer_pubkeys = 2; - repeated string notes = 3; - uint32 signing_type = 4; + repeated string notes = 2; } message RegisterInputsForNextRoundResponse { string request_id = 1; @@ -152,6 +150,7 @@ message RegisterOutputsForNextRoundRequest { string request_id = 1; // List of receivers for to convert to leaves in the next VTXO tree. repeated Output outputs = 2; + optional Musig2 musig2 = 3; } message RegisterOutputsForNextRoundResponse {} @@ -290,6 +289,11 @@ message Input { } } +message Musig2 { + repeated string cosigners_public_keys = 1; + uint32 signing_type = 2; +} + message Output { string address = 1; // onchain or off-chain uint64 amount = 2; // Amount to send in satoshis. diff --git a/api-spec/protobuf/gen/ark/v1/service.pb.go b/api-spec/protobuf/gen/ark/v1/service.pb.go index 3c552abbb..54502f337 100644 --- a/api-spec/protobuf/gen/ark/v1/service.pb.go +++ b/api-spec/protobuf/gen/ark/v1/service.pb.go @@ -376,10 +376,8 @@ type RegisterInputsForNextRoundRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Inputs []*Input `protobuf:"bytes,1,rep,name=inputs,proto3" json:"inputs,omitempty"` - SignerPubkeys []string `protobuf:"bytes,2,rep,name=signer_pubkeys,json=signerPubkeys,proto3" json:"signer_pubkeys,omitempty"` - Notes []string `protobuf:"bytes,3,rep,name=notes,proto3" json:"notes,omitempty"` - SigningType uint32 `protobuf:"varint,4,opt,name=signing_type,json=signingType,proto3" json:"signing_type,omitempty"` + Inputs []*Input `protobuf:"bytes,1,rep,name=inputs,proto3" json:"inputs,omitempty"` + Notes []string `protobuf:"bytes,2,rep,name=notes,proto3" json:"notes,omitempty"` } func (x *RegisterInputsForNextRoundRequest) Reset() { @@ -421,13 +419,6 @@ func (x *RegisterInputsForNextRoundRequest) GetInputs() []*Input { return nil } -func (x *RegisterInputsForNextRoundRequest) GetSignerPubkeys() []string { - if x != nil { - return x.SignerPubkeys - } - return nil -} - func (x *RegisterInputsForNextRoundRequest) GetNotes() []string { if x != nil { return x.Notes @@ -435,13 +426,6 @@ func (x *RegisterInputsForNextRoundRequest) GetNotes() []string { return nil } -func (x *RegisterInputsForNextRoundRequest) GetSigningType() uint32 { - if x != nil { - return x.SigningType - } - return 0 -} - type RegisterInputsForNextRoundResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -497,6 +481,7 @@ type RegisterOutputsForNextRoundRequest struct { RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` // List of receivers for to convert to leaves in the next VTXO tree. Outputs []*Output `protobuf:"bytes,2,rep,name=outputs,proto3" json:"outputs,omitempty"` + Musig2 *Musig2 `protobuf:"bytes,3,opt,name=musig2,proto3,oneof" json:"musig2,omitempty"` } func (x *RegisterOutputsForNextRoundRequest) Reset() { @@ -545,6 +530,13 @@ func (x *RegisterOutputsForNextRoundRequest) GetOutputs() []*Output { return nil } +func (x *RegisterOutputsForNextRoundRequest) GetMusig2() *Musig2 { + if x != nil { + return x.Musig2 + } + return nil +} + type RegisterOutputsForNextRoundResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2065,6 +2057,61 @@ func (*Input_Descriptor_) isInput_TaprootTree() {} func (*Input_Tapscripts) isInput_TaprootTree() {} +type Musig2 struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CosignersPublicKeys []string `protobuf:"bytes,1,rep,name=cosigners_public_keys,json=cosignersPublicKeys,proto3" json:"cosigners_public_keys,omitempty"` + SigningType uint32 `protobuf:"varint,2,opt,name=signing_type,json=signingType,proto3" json:"signing_type,omitempty"` +} + +func (x *Musig2) Reset() { + *x = Musig2{} + if protoimpl.UnsafeEnabled { + mi := &file_ark_v1_service_proto_msgTypes[34] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Musig2) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Musig2) ProtoMessage() {} + +func (x *Musig2) ProtoReflect() protoreflect.Message { + mi := &file_ark_v1_service_proto_msgTypes[34] + 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 Musig2.ProtoReflect.Descriptor instead. +func (*Musig2) Descriptor() ([]byte, []int) { + return file_ark_v1_service_proto_rawDescGZIP(), []int{34} +} + +func (x *Musig2) GetCosignersPublicKeys() []string { + if x != nil { + return x.CosignersPublicKeys + } + return nil +} + +func (x *Musig2) GetSigningType() uint32 { + if x != nil { + return x.SigningType + } + return 0 +} + type Output struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2077,7 +2124,7 @@ type Output struct { func (x *Output) Reset() { *x = Output{} if protoimpl.UnsafeEnabled { - mi := &file_ark_v1_service_proto_msgTypes[34] + mi := &file_ark_v1_service_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2090,7 +2137,7 @@ func (x *Output) String() string { func (*Output) ProtoMessage() {} func (x *Output) ProtoReflect() protoreflect.Message { - mi := &file_ark_v1_service_proto_msgTypes[34] + mi := &file_ark_v1_service_proto_msgTypes[35] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2103,7 +2150,7 @@ func (x *Output) ProtoReflect() protoreflect.Message { // Deprecated: Use Output.ProtoReflect.Descriptor instead. func (*Output) Descriptor() ([]byte, []int) { - return file_ark_v1_service_proto_rawDescGZIP(), []int{34} + return file_ark_v1_service_proto_rawDescGZIP(), []int{35} } func (x *Output) GetAddress() string { @@ -2131,7 +2178,7 @@ type Tree struct { func (x *Tree) Reset() { *x = Tree{} if protoimpl.UnsafeEnabled { - mi := &file_ark_v1_service_proto_msgTypes[35] + mi := &file_ark_v1_service_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2144,7 +2191,7 @@ func (x *Tree) String() string { func (*Tree) ProtoMessage() {} func (x *Tree) ProtoReflect() protoreflect.Message { - mi := &file_ark_v1_service_proto_msgTypes[35] + mi := &file_ark_v1_service_proto_msgTypes[36] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2157,7 +2204,7 @@ func (x *Tree) ProtoReflect() protoreflect.Message { // Deprecated: Use Tree.ProtoReflect.Descriptor instead. func (*Tree) Descriptor() ([]byte, []int) { - return file_ark_v1_service_proto_rawDescGZIP(), []int{35} + return file_ark_v1_service_proto_rawDescGZIP(), []int{36} } func (x *Tree) GetLevels() []*TreeLevel { @@ -2178,7 +2225,7 @@ type TreeLevel struct { func (x *TreeLevel) Reset() { *x = TreeLevel{} if protoimpl.UnsafeEnabled { - mi := &file_ark_v1_service_proto_msgTypes[36] + mi := &file_ark_v1_service_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2191,7 +2238,7 @@ func (x *TreeLevel) String() string { func (*TreeLevel) ProtoMessage() {} func (x *TreeLevel) ProtoReflect() protoreflect.Message { - mi := &file_ark_v1_service_proto_msgTypes[36] + mi := &file_ark_v1_service_proto_msgTypes[37] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2204,7 +2251,7 @@ func (x *TreeLevel) ProtoReflect() protoreflect.Message { // Deprecated: Use TreeLevel.ProtoReflect.Descriptor instead. func (*TreeLevel) Descriptor() ([]byte, []int) { - return file_ark_v1_service_proto_rawDescGZIP(), []int{36} + return file_ark_v1_service_proto_rawDescGZIP(), []int{37} } func (x *TreeLevel) GetNodes() []*Node { @@ -2227,7 +2274,7 @@ type Node struct { func (x *Node) Reset() { *x = Node{} if protoimpl.UnsafeEnabled { - mi := &file_ark_v1_service_proto_msgTypes[37] + mi := &file_ark_v1_service_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2240,7 +2287,7 @@ func (x *Node) String() string { func (*Node) ProtoMessage() {} func (x *Node) ProtoReflect() protoreflect.Message { - mi := &file_ark_v1_service_proto_msgTypes[37] + mi := &file_ark_v1_service_proto_msgTypes[38] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2253,7 +2300,7 @@ func (x *Node) ProtoReflect() protoreflect.Message { // Deprecated: Use Node.ProtoReflect.Descriptor instead. func (*Node) Descriptor() ([]byte, []int) { - return file_ark_v1_service_proto_rawDescGZIP(), []int{37} + return file_ark_v1_service_proto_rawDescGZIP(), []int{38} } func (x *Node) GetTxid() string { @@ -2298,7 +2345,7 @@ type Vtxo struct { func (x *Vtxo) Reset() { *x = Vtxo{} if protoimpl.UnsafeEnabled { - mi := &file_ark_v1_service_proto_msgTypes[38] + mi := &file_ark_v1_service_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2311,7 +2358,7 @@ func (x *Vtxo) String() string { func (*Vtxo) ProtoMessage() {} func (x *Vtxo) ProtoReflect() protoreflect.Message { - mi := &file_ark_v1_service_proto_msgTypes[38] + mi := &file_ark_v1_service_proto_msgTypes[39] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2324,7 +2371,7 @@ func (x *Vtxo) ProtoReflect() protoreflect.Message { // Deprecated: Use Vtxo.ProtoReflect.Descriptor instead. func (*Vtxo) Descriptor() ([]byte, []int) { - return file_ark_v1_service_proto_rawDescGZIP(), []int{38} + return file_ark_v1_service_proto_rawDescGZIP(), []int{39} } func (x *Vtxo) GetOutpoint() *Outpoint { @@ -2413,7 +2460,7 @@ type GetTransactionsStreamRequest struct { func (x *GetTransactionsStreamRequest) Reset() { *x = GetTransactionsStreamRequest{} if protoimpl.UnsafeEnabled { - mi := &file_ark_v1_service_proto_msgTypes[39] + mi := &file_ark_v1_service_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2426,7 +2473,7 @@ func (x *GetTransactionsStreamRequest) String() string { func (*GetTransactionsStreamRequest) ProtoMessage() {} func (x *GetTransactionsStreamRequest) ProtoReflect() protoreflect.Message { - mi := &file_ark_v1_service_proto_msgTypes[39] + mi := &file_ark_v1_service_proto_msgTypes[40] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2439,7 +2486,7 @@ func (x *GetTransactionsStreamRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetTransactionsStreamRequest.ProtoReflect.Descriptor instead. func (*GetTransactionsStreamRequest) Descriptor() ([]byte, []int) { - return file_ark_v1_service_proto_rawDescGZIP(), []int{39} + return file_ark_v1_service_proto_rawDescGZIP(), []int{40} } type GetTransactionsStreamResponse struct { @@ -2457,7 +2504,7 @@ type GetTransactionsStreamResponse struct { func (x *GetTransactionsStreamResponse) Reset() { *x = GetTransactionsStreamResponse{} if protoimpl.UnsafeEnabled { - mi := &file_ark_v1_service_proto_msgTypes[40] + mi := &file_ark_v1_service_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2470,7 +2517,7 @@ func (x *GetTransactionsStreamResponse) String() string { func (*GetTransactionsStreamResponse) ProtoMessage() {} func (x *GetTransactionsStreamResponse) ProtoReflect() protoreflect.Message { - mi := &file_ark_v1_service_proto_msgTypes[40] + mi := &file_ark_v1_service_proto_msgTypes[41] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2483,7 +2530,7 @@ func (x *GetTransactionsStreamResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetTransactionsStreamResponse.ProtoReflect.Descriptor instead. func (*GetTransactionsStreamResponse) Descriptor() ([]byte, []int) { - return file_ark_v1_service_proto_rawDescGZIP(), []int{40} + return file_ark_v1_service_proto_rawDescGZIP(), []int{41} } func (m *GetTransactionsStreamResponse) GetTx() isGetTransactionsStreamResponse_Tx { @@ -2537,7 +2584,7 @@ type RoundTransaction struct { func (x *RoundTransaction) Reset() { *x = RoundTransaction{} if protoimpl.UnsafeEnabled { - mi := &file_ark_v1_service_proto_msgTypes[41] + mi := &file_ark_v1_service_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2550,7 +2597,7 @@ func (x *RoundTransaction) String() string { func (*RoundTransaction) ProtoMessage() {} func (x *RoundTransaction) ProtoReflect() protoreflect.Message { - mi := &file_ark_v1_service_proto_msgTypes[41] + mi := &file_ark_v1_service_proto_msgTypes[42] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2563,7 +2610,7 @@ func (x *RoundTransaction) ProtoReflect() protoreflect.Message { // Deprecated: Use RoundTransaction.ProtoReflect.Descriptor instead. func (*RoundTransaction) Descriptor() ([]byte, []int) { - return file_ark_v1_service_proto_rawDescGZIP(), []int{41} + return file_ark_v1_service_proto_rawDescGZIP(), []int{42} } func (x *RoundTransaction) GetTxid() string { @@ -2607,7 +2654,7 @@ type RedeemTransaction struct { func (x *RedeemTransaction) Reset() { *x = RedeemTransaction{} if protoimpl.UnsafeEnabled { - mi := &file_ark_v1_service_proto_msgTypes[42] + mi := &file_ark_v1_service_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2620,7 +2667,7 @@ func (x *RedeemTransaction) String() string { func (*RedeemTransaction) ProtoMessage() {} func (x *RedeemTransaction) ProtoReflect() protoreflect.Message { - mi := &file_ark_v1_service_proto_msgTypes[42] + mi := &file_ark_v1_service_proto_msgTypes[43] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2633,7 +2680,7 @@ func (x *RedeemTransaction) ProtoReflect() protoreflect.Message { // Deprecated: Use RedeemTransaction.ProtoReflect.Descriptor instead. func (*RedeemTransaction) Descriptor() ([]byte, []int) { - return file_ark_v1_service_proto_rawDescGZIP(), []int{42} + return file_ark_v1_service_proto_rawDescGZIP(), []int{43} } func (x *RedeemTransaction) GetTxid() string { @@ -2671,7 +2718,7 @@ type OwnershipProof struct { func (x *OwnershipProof) Reset() { *x = OwnershipProof{} if protoimpl.UnsafeEnabled { - mi := &file_ark_v1_service_proto_msgTypes[43] + mi := &file_ark_v1_service_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2684,7 +2731,7 @@ func (x *OwnershipProof) String() string { func (*OwnershipProof) ProtoMessage() {} func (x *OwnershipProof) ProtoReflect() protoreflect.Message { - mi := &file_ark_v1_service_proto_msgTypes[43] + mi := &file_ark_v1_service_proto_msgTypes[44] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2697,7 +2744,7 @@ func (x *OwnershipProof) ProtoReflect() protoreflect.Message { // Deprecated: Use OwnershipProof.ProtoReflect.Descriptor instead. func (*OwnershipProof) Descriptor() ([]byte, []int) { - return file_ark_v1_service_proto_rawDescGZIP(), []int{43} + return file_ark_v1_service_proto_rawDescGZIP(), []int{44} } func (x *OwnershipProof) GetControlBlock() string { @@ -2733,7 +2780,7 @@ type SignedVtxoOutpoint struct { func (x *SignedVtxoOutpoint) Reset() { *x = SignedVtxoOutpoint{} if protoimpl.UnsafeEnabled { - mi := &file_ark_v1_service_proto_msgTypes[44] + mi := &file_ark_v1_service_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2746,7 +2793,7 @@ func (x *SignedVtxoOutpoint) String() string { func (*SignedVtxoOutpoint) ProtoMessage() {} func (x *SignedVtxoOutpoint) ProtoReflect() protoreflect.Message { - mi := &file_ark_v1_service_proto_msgTypes[44] + mi := &file_ark_v1_service_proto_msgTypes[45] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2759,7 +2806,7 @@ func (x *SignedVtxoOutpoint) ProtoReflect() protoreflect.Message { // Deprecated: Use SignedVtxoOutpoint.ProtoReflect.Descriptor instead. func (*SignedVtxoOutpoint) Descriptor() ([]byte, []int) { - return file_ark_v1_service_proto_rawDescGZIP(), []int{44} + return file_ark_v1_service_proto_rawDescGZIP(), []int{45} } func (x *SignedVtxoOutpoint) GetOutpoint() *Outpoint { @@ -2788,7 +2835,7 @@ type SetNostrRecipientRequest struct { func (x *SetNostrRecipientRequest) Reset() { *x = SetNostrRecipientRequest{} if protoimpl.UnsafeEnabled { - mi := &file_ark_v1_service_proto_msgTypes[45] + mi := &file_ark_v1_service_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2801,7 +2848,7 @@ func (x *SetNostrRecipientRequest) String() string { func (*SetNostrRecipientRequest) ProtoMessage() {} func (x *SetNostrRecipientRequest) ProtoReflect() protoreflect.Message { - mi := &file_ark_v1_service_proto_msgTypes[45] + mi := &file_ark_v1_service_proto_msgTypes[46] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2814,7 +2861,7 @@ func (x *SetNostrRecipientRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetNostrRecipientRequest.ProtoReflect.Descriptor instead. func (*SetNostrRecipientRequest) Descriptor() ([]byte, []int) { - return file_ark_v1_service_proto_rawDescGZIP(), []int{45} + return file_ark_v1_service_proto_rawDescGZIP(), []int{46} } func (x *SetNostrRecipientRequest) GetNostrRecipient() string { @@ -2840,7 +2887,7 @@ type SetNostrRecipientResponse struct { func (x *SetNostrRecipientResponse) Reset() { *x = SetNostrRecipientResponse{} if protoimpl.UnsafeEnabled { - mi := &file_ark_v1_service_proto_msgTypes[46] + mi := &file_ark_v1_service_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2853,7 +2900,7 @@ func (x *SetNostrRecipientResponse) String() string { func (*SetNostrRecipientResponse) ProtoMessage() {} func (x *SetNostrRecipientResponse) ProtoReflect() protoreflect.Message { - mi := &file_ark_v1_service_proto_msgTypes[46] + mi := &file_ark_v1_service_proto_msgTypes[47] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2866,7 +2913,7 @@ func (x *SetNostrRecipientResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetNostrRecipientResponse.ProtoReflect.Descriptor instead. func (*SetNostrRecipientResponse) Descriptor() ([]byte, []int) { - return file_ark_v1_service_proto_rawDescGZIP(), []int{46} + return file_ark_v1_service_proto_rawDescGZIP(), []int{47} } type DeleteNostrRecipientRequest struct { @@ -2880,7 +2927,7 @@ type DeleteNostrRecipientRequest struct { func (x *DeleteNostrRecipientRequest) Reset() { *x = DeleteNostrRecipientRequest{} if protoimpl.UnsafeEnabled { - mi := &file_ark_v1_service_proto_msgTypes[47] + mi := &file_ark_v1_service_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2893,7 +2940,7 @@ func (x *DeleteNostrRecipientRequest) String() string { func (*DeleteNostrRecipientRequest) ProtoMessage() {} func (x *DeleteNostrRecipientRequest) ProtoReflect() protoreflect.Message { - mi := &file_ark_v1_service_proto_msgTypes[47] + mi := &file_ark_v1_service_proto_msgTypes[48] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2906,7 +2953,7 @@ func (x *DeleteNostrRecipientRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteNostrRecipientRequest.ProtoReflect.Descriptor instead. func (*DeleteNostrRecipientRequest) Descriptor() ([]byte, []int) { - return file_ark_v1_service_proto_rawDescGZIP(), []int{47} + return file_ark_v1_service_proto_rawDescGZIP(), []int{48} } func (x *DeleteNostrRecipientRequest) GetVtxos() []*SignedVtxoOutpoint { @@ -2925,7 +2972,7 @@ type DeleteNostrRecipientResponse struct { func (x *DeleteNostrRecipientResponse) Reset() { *x = DeleteNostrRecipientResponse{} if protoimpl.UnsafeEnabled { - mi := &file_ark_v1_service_proto_msgTypes[48] + mi := &file_ark_v1_service_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2938,7 +2985,7 @@ func (x *DeleteNostrRecipientResponse) String() string { func (*DeleteNostrRecipientResponse) ProtoMessage() {} func (x *DeleteNostrRecipientResponse) ProtoReflect() protoreflect.Message { - mi := &file_ark_v1_service_proto_msgTypes[48] + mi := &file_ark_v1_service_proto_msgTypes[49] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2951,7 +2998,7 @@ func (x *DeleteNostrRecipientResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteNostrRecipientResponse.ProtoReflect.Descriptor instead. func (*DeleteNostrRecipientResponse) Descriptor() ([]byte, []int) { - return file_ark_v1_service_proto_rawDescGZIP(), []int{48} + return file_ark_v1_service_proto_rawDescGZIP(), []int{49} } type Tapscripts struct { @@ -2965,7 +3012,7 @@ type Tapscripts struct { func (x *Tapscripts) Reset() { *x = Tapscripts{} if protoimpl.UnsafeEnabled { - mi := &file_ark_v1_service_proto_msgTypes[49] + mi := &file_ark_v1_service_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2978,7 +3025,7 @@ func (x *Tapscripts) String() string { func (*Tapscripts) ProtoMessage() {} func (x *Tapscripts) ProtoReflect() protoreflect.Message { - mi := &file_ark_v1_service_proto_msgTypes[49] + mi := &file_ark_v1_service_proto_msgTypes[50] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2991,7 +3038,7 @@ func (x *Tapscripts) ProtoReflect() protoreflect.Message { // Deprecated: Use Tapscripts.ProtoReflect.Descriptor instead. func (*Tapscripts) Descriptor() ([]byte, []int) { - return file_ark_v1_service_proto_rawDescGZIP(), []int{49} + return file_ark_v1_service_proto_rawDescGZIP(), []int{50} } func (x *Tapscripts) GetScripts() []string { @@ -3015,7 +3062,7 @@ type MarketHour struct { func (x *MarketHour) Reset() { *x = MarketHour{} if protoimpl.UnsafeEnabled { - mi := &file_ark_v1_service_proto_msgTypes[50] + mi := &file_ark_v1_service_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3028,7 +3075,7 @@ func (x *MarketHour) String() string { func (*MarketHour) ProtoMessage() {} func (x *MarketHour) ProtoReflect() protoreflect.Message { - mi := &file_ark_v1_service_proto_msgTypes[50] + mi := &file_ark_v1_service_proto_msgTypes[51] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3041,7 +3088,7 @@ func (x *MarketHour) ProtoReflect() protoreflect.Message { // Deprecated: Use MarketHour.ProtoReflect.Descriptor instead. func (*MarketHour) Descriptor() ([]byte, []int) { - return file_ark_v1_service_proto_rawDescGZIP(), []int{50} + return file_ark_v1_service_proto_rawDescGZIP(), []int{51} } func (x *MarketHour) GetNextStartTime() *timestamppb.Timestamp { @@ -3124,443 +3171,448 @@ var file_ark_v1_service_proto_rawDesc = []byte{ 0x72, 0x69, 0x70, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x48, 0x00, 0x52, 0x0a, 0x74, 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x42, 0x0e, 0x0a, - 0x0c, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x22, 0xaa, 0x01, - 0x0a, 0x21, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, - 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x70, - 0x75, 0x74, 0x52, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x69, - 0x67, 0x6e, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, - 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x69, 0x67, 0x6e, 0x69, - 0x6e, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x73, - 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x22, 0x43, 0x0a, 0x22, 0x52, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, - 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x22, - 0x6d, 0x0a, 0x22, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, - 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x22, 0x25, - 0x0a, 0x23, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, + 0x0c, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x22, 0x60, 0x0a, + 0x21, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, + 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x25, 0x0a, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x70, 0x75, + 0x74, 0x52, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x74, + 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x22, + 0x43, 0x0a, 0x22, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6d, 0x0a, 0x17, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, - 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x19, 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, - 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, - 0x6b, 0x65, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, - 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x72, 0x65, 0x65, 0x4e, 0x6f, - 0x6e, 0x63, 0x65, 0x73, 0x22, 0x1a, 0x0a, 0x18, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, - 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x79, 0x0a, 0x1b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x19, 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, - 0x62, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, - 0x65, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x72, 0x65, - 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x22, 0x1e, 0x0a, 0x1c, 0x53, - 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x8e, 0x01, 0x0a, 0x1d, - 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, - 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, - 0x12, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x66, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x5f, - 0x74, 0x78, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x73, 0x69, 0x67, 0x6e, 0x65, - 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x2b, 0x0a, 0x0f, 0x73, - 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x52, 0x6f, - 0x75, 0x6e, 0x64, 0x54, 0x78, 0x88, 0x01, 0x01, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x73, 0x69, 0x67, - 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x22, 0x20, 0x0a, 0x1e, - 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, - 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, - 0x0a, 0x15, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xa7, 0x03, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x12, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x66, 0x69, 0x6e, 0x61, - 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, - 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, - 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, - 0x52, 0x11, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x0a, 0x0f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x66, 0x69, 0x6e, - 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x49, 0x64, 0x22, 0xa5, 0x01, 0x0a, 0x22, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, + 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, + 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x07, 0x6f, 0x75, + 0x74, 0x70, 0x75, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x72, + 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x52, 0x07, 0x6f, 0x75, 0x74, + 0x70, 0x75, 0x74, 0x73, 0x12, 0x2b, 0x0a, 0x06, 0x6d, 0x75, 0x73, 0x69, 0x67, 0x32, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, + 0x73, 0x69, 0x67, 0x32, 0x48, 0x00, 0x52, 0x06, 0x6d, 0x75, 0x73, 0x69, 0x67, 0x32, 0x88, 0x01, + 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x6d, 0x75, 0x73, 0x69, 0x67, 0x32, 0x22, 0x25, 0x0a, 0x23, + 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, + 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x6d, 0x0a, 0x17, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, + 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, + 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, + 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, + 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, + 0x65, 0x73, 0x22, 0x1a, 0x0a, 0x18, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, + 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x79, + 0x0a, 0x1b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, + 0x08, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, + 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, + 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x72, 0x65, 0x65, 0x53, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x22, 0x1e, 0x0a, 0x1c, 0x53, 0x75, 0x62, + 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x8e, 0x01, 0x0a, 0x1d, 0x53, 0x75, + 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, + 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x73, + 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x66, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x5f, 0x74, 0x78, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, + 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x2b, 0x0a, 0x0f, 0x73, 0x69, 0x67, + 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x48, 0x00, 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x6e, + 0x64, 0x54, 0x78, 0x88, 0x01, 0x01, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x65, + 0x64, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x22, 0x20, 0x0a, 0x1e, 0x53, 0x75, + 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, + 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x0a, 0x15, + 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xa7, 0x03, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x4f, 0x0a, 0x12, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, + 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, - 0x69, 0x7a, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0e, 0x72, 0x6f, 0x75, - 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x38, 0x0a, 0x0c, 0x72, - 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x13, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, - 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0b, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x46, - 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x40, 0x0a, 0x0d, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, - 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, - 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, - 0x6e, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x72, 0x6f, 0x75, 0x6e, 0x64, - 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x6f, 0x0a, 0x1e, 0x72, 0x6f, 0x75, 0x6e, 0x64, - 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x5f, - 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x28, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, - 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x47, 0x65, 0x6e, 0x65, 0x72, - 0x61, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1b, 0x72, 0x6f, 0x75, - 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x47, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x22, 0x2c, 0x0a, 0x0b, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x22, - 0x0e, 0x0a, 0x0c, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x34, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, - 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x64, 0x65, - 0x65, 0x6d, 0x5f, 0x74, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x64, - 0x65, 0x65, 0x6d, 0x54, 0x78, 0x22, 0x42, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, - 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x28, 0x0a, 0x10, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, - 0x5f, 0x74, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x69, 0x67, 0x6e, 0x65, - 0x64, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x22, 0x25, 0x0a, 0x0f, 0x47, 0x65, 0x74, - 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, - 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, - 0x22, 0x37, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, - 0x6e, 0x64, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x25, 0x0a, 0x13, 0x47, 0x65, 0x74, - 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, - 0x22, 0x3b, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x2c, 0x0a, - 0x10, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x79, 0x0a, 0x11, 0x4c, - 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x35, 0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x74, - 0x78, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, - 0x76, 0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x0e, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, - 0x6c, 0x65, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x2d, 0x0a, 0x0b, 0x73, 0x70, 0x65, 0x6e, 0x74, - 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, - 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x0a, 0x73, 0x70, 0x65, 0x6e, - 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x22, 0xbb, 0x01, 0x0a, 0x16, 0x52, 0x6f, 0x75, 0x6e, 0x64, - 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, + 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x11, + 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x46, 0x0a, 0x0f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x66, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x7a, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, 0x72, 0x6b, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, + 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0e, 0x72, 0x6f, 0x75, 0x6e, 0x64, + 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x38, 0x0a, 0x0c, 0x72, 0x6f, 0x75, + 0x6e, 0x64, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x13, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x61, + 0x69, 0x6c, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0b, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x61, 0x69, + 0x6c, 0x65, 0x64, 0x12, 0x40, 0x0a, 0x0d, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, 0x69, 0x67, + 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x72, 0x6b, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, + 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x6f, 0x0a, 0x1e, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, + 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x5f, 0x67, 0x65, + 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, + 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, + 0x69, 0x6e, 0x67, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1b, 0x72, 0x6f, 0x75, 0x6e, 0x64, + 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x47, 0x65, 0x6e, + 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, + 0x2c, 0x0a, 0x0b, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, + 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x22, 0x0e, 0x0a, + 0x0c, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x0a, + 0x15, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, + 0x5f, 0x74, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x64, 0x65, 0x65, + 0x6d, 0x54, 0x78, 0x22, 0x42, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, + 0x65, 0x65, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, + 0x10, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x5f, 0x74, + 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x52, + 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x22, 0x25, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x52, 0x6f, + 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x22, 0x37, + 0x0a, 0x10, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, + 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x25, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x52, 0x6f, + 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x3b, + 0x0a, 0x14, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x2c, 0x0a, 0x10, 0x4c, + 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x79, 0x0a, 0x11, 0x4c, 0x69, 0x73, + 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, + 0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x74, 0x78, 0x6f, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x0e, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, + 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x2d, 0x0a, 0x0b, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x76, + 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, + 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x0a, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x56, + 0x74, 0x78, 0x6f, 0x73, 0x22, 0xbb, 0x01, 0x0a, 0x16, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, + 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x19, 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x12, 0x29, 0x0a, 0x09, 0x76, 0x74, + 0x78, 0x6f, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, + 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x52, 0x08, 0x76, 0x74, 0x78, + 0x6f, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x6f, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x2b, 0x0a, 0x12, 0x6d, 0x69, 0x6e, 0x5f, 0x72, 0x65, 0x6c, + 0x61, 0x79, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x46, 0x65, 0x65, 0x52, 0x61, + 0x74, 0x65, 0x22, 0x44, 0x0a, 0x13, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x7a, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x75, + 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, + 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x69, 0x64, 0x22, 0x35, 0x0a, 0x0b, 0x52, 0x6f, 0x75, 0x6e, + 0x64, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, + 0x8b, 0x01, 0x0a, 0x11, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x3a, 0x0a, 0x12, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, + 0x64, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x52, + 0x10, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, 0x54, 0x72, 0x65, + 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x6f, + 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x75, 0x6e, + 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x22, 0x53, 0x0a, + 0x20, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4e, 0x6f, 0x6e, + 0x63, 0x65, 0x73, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, - 0x64, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x12, 0x29, 0x0a, 0x09, - 0x76, 0x74, 0x78, 0x6f, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x52, 0x08, 0x76, - 0x74, 0x78, 0x6f, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x2b, 0x0a, 0x12, 0x6d, 0x69, 0x6e, 0x5f, 0x72, - 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x46, 0x65, 0x65, - 0x52, 0x61, 0x74, 0x65, 0x22, 0x44, 0x0a, 0x13, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, - 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, - 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x69, 0x64, 0x22, 0x35, 0x0a, 0x0b, 0x52, 0x6f, - 0x75, 0x6e, 0x64, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, - 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, - 0x6e, 0x22, 0x8b, 0x01, 0x0a, 0x11, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, - 0x6e, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x3a, 0x0a, 0x12, 0x75, 0x6e, 0x73, 0x69, 0x67, - 0x6e, 0x65, 0x64, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, - 0x65, 0x52, 0x10, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, 0x54, - 0x72, 0x65, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, - 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, - 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x22, - 0x53, 0x0a, 0x20, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4e, - 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x02, 0x69, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, - 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x72, 0x65, 0x65, 0x4e, 0x6f, - 0x6e, 0x63, 0x65, 0x73, 0x22, 0xf0, 0x01, 0x0a, 0x05, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x0e, - 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, - 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, - 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, - 0x74, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, - 0x78, 0x12, 0x29, 0x0a, 0x09, 0x76, 0x74, 0x78, 0x6f, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, - 0x65, 0x65, 0x52, 0x08, 0x76, 0x74, 0x78, 0x6f, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1f, 0x0a, 0x0b, - 0x66, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x5f, 0x74, 0x78, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0a, 0x66, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x1e, 0x0a, - 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x28, 0x0a, - 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x61, - 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x67, 0x65, - 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x22, 0x32, 0x0a, 0x08, 0x4f, 0x75, 0x74, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x76, 0x6f, 0x75, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x76, 0x6f, 0x75, 0x74, 0x22, 0x9d, 0x01, 0x0a, 0x05, - 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x12, 0x20, 0x0a, 0x0a, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, - 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x64, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x34, 0x0a, 0x0a, 0x74, 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x72, 0x6b, 0x2e, - 0x76, 0x31, 0x2e, 0x54, 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x48, 0x00, 0x52, - 0x0a, 0x74, 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x42, 0x0e, 0x0a, 0x0c, 0x74, - 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x22, 0x3a, 0x0a, 0x06, 0x4f, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, - 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x31, 0x0a, 0x04, 0x54, 0x72, 0x65, 0x65, 0x12, - 0x29, 0x0a, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x11, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x65, 0x76, - 0x65, 0x6c, 0x52, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x22, 0x2f, 0x0a, 0x09, 0x54, 0x72, - 0x65, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x22, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, - 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x4b, 0x0a, 0x04, 0x4e, - 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x78, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x02, 0x74, 0x78, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, - 0x74, 0x5f, 0x74, 0x78, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x54, 0x78, 0x69, 0x64, 0x22, 0xc2, 0x02, 0x0a, 0x04, 0x56, 0x74, 0x78, - 0x6f, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, - 0x14, 0x0a, 0x05, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, - 0x73, 0x70, 0x65, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, - 0x78, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x6f, 0x75, 0x6e, 0x64, - 0x54, 0x78, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x12, - 0x1b, 0x0a, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x08, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x74, 0x12, 0x14, 0x0a, 0x05, - 0x73, 0x77, 0x65, 0x70, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x73, 0x77, 0x65, - 0x70, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x5f, 0x74, 0x78, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x12, 0x16, - 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, - 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x1d, - 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x1e, 0x0a, - 0x1c, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x8c, 0x01, - 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x30, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, - 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, - 0x64, 0x12, 0x33, 0x0a, 0x06, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x65, 0x65, - 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x06, - 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x42, 0x04, 0x0a, 0x02, 0x74, 0x78, 0x22, 0xd8, 0x01, 0x0a, - 0x10, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x31, 0x0a, 0x0b, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x76, - 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, - 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x73, 0x70, - 0x65, 0x6e, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x35, 0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, - 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, - 0x0e, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, - 0x46, 0x0a, 0x16, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x5f, 0x62, 0x6f, 0x61, 0x72, 0x64, - 0x69, 0x6e, 0x67, 0x5f, 0x75, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, + 0x65, 0x73, 0x22, 0xf0, 0x01, 0x0a, 0x05, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x0e, 0x0a, 0x02, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x03, 0x65, 0x6e, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x12, + 0x29, 0x0a, 0x09, 0x76, 0x74, 0x78, 0x6f, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, + 0x52, 0x08, 0x76, 0x74, 0x78, 0x6f, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x6f, + 0x72, 0x66, 0x65, 0x69, 0x74, 0x5f, 0x74, 0x78, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0a, 0x66, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x28, 0x0a, 0x05, 0x73, + 0x74, 0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x61, 0x72, 0x6b, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x05, + 0x73, 0x74, 0x61, 0x67, 0x65, 0x22, 0x32, 0x0a, 0x08, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x76, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x04, 0x76, 0x6f, 0x75, 0x74, 0x22, 0x9d, 0x01, 0x0a, 0x05, 0x49, 0x6e, + 0x70, 0x75, 0x74, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, + 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x12, 0x20, 0x0a, 0x0a, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x6f, 0x72, 0x12, 0x34, 0x0a, 0x0a, 0x74, 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x54, 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x48, 0x00, 0x52, 0x0a, 0x74, + 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x42, 0x0e, 0x0a, 0x0c, 0x74, 0x61, 0x70, + 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x22, 0x5f, 0x0a, 0x06, 0x4d, 0x75, 0x73, + 0x69, 0x67, 0x32, 0x12, 0x32, 0x0a, 0x15, 0x63, 0x6f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, + 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x13, 0x63, 0x6f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x50, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x69, 0x67, 0x6e, 0x69, + 0x6e, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x73, + 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x0a, 0x06, 0x4f, 0x75, + 0x74, 0x70, 0x75, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, + 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, + 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x31, 0x0a, 0x04, 0x54, 0x72, 0x65, 0x65, 0x12, 0x29, + 0x0a, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, + 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x65, 0x76, 0x65, + 0x6c, 0x52, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x22, 0x2f, 0x0a, 0x09, 0x54, 0x72, 0x65, + 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x22, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4e, + 0x6f, 0x64, 0x65, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x4b, 0x0a, 0x04, 0x4e, 0x6f, + 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x78, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x74, 0x78, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x5f, 0x74, 0x78, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x72, + 0x65, 0x6e, 0x74, 0x54, 0x78, 0x69, 0x64, 0x22, 0xc2, 0x02, 0x0a, 0x04, 0x56, 0x74, 0x78, 0x6f, + 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x14, + 0x0a, 0x05, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x73, + 0x70, 0x65, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, + 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, + 0x78, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x12, 0x1b, + 0x0a, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x08, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, + 0x77, 0x65, 0x70, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x73, 0x77, 0x65, 0x70, + 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, + 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x5f, 0x74, 0x78, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x12, 0x16, 0x0a, + 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, + 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x1d, 0x0a, + 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x1e, 0x0a, 0x1c, + 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x8c, 0x01, 0x0a, + 0x1d, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, + 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, + 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, + 0x12, 0x33, 0x0a, 0x06, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x19, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x06, 0x72, + 0x65, 0x64, 0x65, 0x65, 0x6d, 0x42, 0x04, 0x0a, 0x02, 0x74, 0x78, 0x22, 0xd8, 0x01, 0x0a, 0x10, + 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x74, 0x78, 0x69, 0x64, 0x12, 0x31, 0x0a, 0x0b, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x74, + 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, + 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x73, 0x70, 0x65, + 0x6e, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x35, 0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, 0x64, + 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x0e, + 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x46, + 0x0a, 0x16, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x5f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, + 0x6e, 0x67, 0x5f, 0x75, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, + 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x52, 0x14, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, + 0x67, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x91, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x64, 0x65, 0x65, + 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, + 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, + 0x12, 0x31, 0x0a, 0x0b, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, + 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x56, 0x74, + 0x78, 0x6f, 0x73, 0x12, 0x35, 0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, + 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, + 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x0e, 0x73, 0x70, 0x65, 0x6e, + 0x64, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x6b, 0x0a, 0x0e, 0x4f, 0x77, + 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x23, 0x0a, 0x0d, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x70, 0x0a, 0x12, 0x53, 0x69, 0x67, 0x6e, 0x65, + 0x64, 0x56, 0x74, 0x78, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2c, 0x0a, + 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x52, 0x14, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, - 0x6e, 0x67, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x91, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x64, 0x65, - 0x65, 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, - 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, - 0x64, 0x12, 0x31, 0x0a, 0x0b, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, - 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x56, - 0x74, 0x78, 0x6f, 0x73, 0x12, 0x35, 0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, - 0x65, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, - 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x0e, 0x73, 0x70, 0x65, - 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x6b, 0x0a, 0x0e, 0x4f, - 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x23, 0x0a, - 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x70, 0x0a, 0x12, 0x53, 0x69, 0x67, 0x6e, - 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2c, - 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x05, - 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x72, - 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x72, - 0x6f, 0x6f, 0x66, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x75, 0x0a, 0x18, 0x53, 0x65, - 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x5f, - 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0e, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, - 0x30, 0x0a, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, - 0x78, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x05, 0x76, 0x74, 0x78, 0x6f, - 0x73, 0x22, 0x1b, 0x0a, 0x19, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, - 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4f, - 0x0a, 0x1b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, - 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, - 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, - 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, - 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x22, - 0x1e, 0x0a, 0x1c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, - 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x26, 0x0a, 0x0a, 0x54, 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x12, 0x18, 0x0a, - 0x07, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x22, 0x85, 0x02, 0x0a, 0x0a, 0x4d, 0x61, 0x72, 0x6b, - 0x65, 0x74, 0x48, 0x6f, 0x75, 0x72, 0x12, 0x42, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x73, - 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x6e, 0x65, 0x78, - 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0d, 0x6e, 0x65, - 0x78, 0x74, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x6e, - 0x65, 0x78, 0x74, 0x45, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x31, 0x0a, 0x06, 0x70, 0x65, - 0x72, 0x69, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x12, 0x40, 0x0a, - 0x0e, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x0d, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x2a, - 0x98, 0x01, 0x0a, 0x0a, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x1b, - 0x0a, 0x17, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x55, 0x4e, - 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x52, - 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x52, 0x45, 0x47, 0x49, 0x53, - 0x54, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, 0x55, - 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x49, 0x5a, - 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x52, 0x4f, 0x55, 0x4e, 0x44, - 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x49, 0x5a, 0x45, 0x44, - 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, - 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x04, 0x32, 0xf0, 0x0e, 0x0a, 0x0a, 0x41, - 0x72, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x07, 0x47, 0x65, 0x74, - 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, - 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x61, - 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, - 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x74, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x42, 0x6f, - 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x21, 0x2e, - 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, - 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x22, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, - 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x3a, 0x01, 0x2a, 0x22, - 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x98, 0x01, - 0x0a, 0x1a, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, - 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x29, 0x2e, 0x61, - 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, - 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, - 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x3a, 0x01, 0x2a, 0x22, 0x18, - 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, - 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x9c, 0x01, 0x0a, 0x1b, 0x52, 0x65, 0x67, + 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x05, 0x70, + 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x72, 0x6b, + 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x72, 0x6f, + 0x6f, 0x66, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x75, 0x0a, 0x18, 0x53, 0x65, 0x74, + 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x5f, 0x72, + 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, + 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x30, + 0x0a, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, + 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, + 0x22, 0x1b, 0x0a, 0x19, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, + 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4f, 0x0a, + 0x1b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, + 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x05, + 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x72, + 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, 0x4f, + 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x1e, + 0x0a, 0x1c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, + 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, + 0x0a, 0x0a, 0x54, 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x12, 0x18, 0x0a, 0x07, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x22, 0x85, 0x02, 0x0a, 0x0a, 0x4d, 0x61, 0x72, 0x6b, 0x65, + 0x74, 0x48, 0x6f, 0x75, 0x72, 0x12, 0x42, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0d, 0x6e, 0x65, 0x78, + 0x74, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x6e, 0x65, + 0x78, 0x74, 0x45, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x31, 0x0a, 0x06, 0x70, 0x65, 0x72, + 0x69, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x12, 0x40, 0x0a, 0x0e, + 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x0d, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x2a, 0x98, + 0x01, 0x0a, 0x0a, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, + 0x17, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x55, 0x4e, 0x53, + 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, + 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, + 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, 0x55, 0x4e, + 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x49, 0x5a, 0x41, + 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, + 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x49, 0x5a, 0x45, 0x44, 0x10, + 0x03, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, + 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x04, 0x32, 0xf0, 0x0e, 0x0a, 0x0a, 0x41, 0x72, + 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, + 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, + 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x61, 0x72, + 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, + 0x31, 0x2f, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x74, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, + 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x21, 0x2e, 0x61, + 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, + 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x22, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, + 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x3a, 0x01, 0x2a, 0x22, 0x0c, + 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x98, 0x01, 0x0a, + 0x1a, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, + 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x29, 0x2e, 0x61, 0x72, + 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, + 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, + 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x3a, 0x01, 0x2a, 0x22, 0x18, 0x2f, + 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, + 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x9c, 0x01, 0x0a, 0x1b, 0x52, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, + 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, + 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, - 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, - 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, - 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, - 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x3a, 0x01, 0x2a, 0x22, 0x19, 0x2f, 0x76, - 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, - 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x12, 0x7d, 0x0a, 0x10, 0x53, 0x75, 0x62, 0x6d, 0x69, - 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x61, 0x72, + 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x3a, 0x01, 0x2a, 0x22, 0x19, 0x2f, 0x76, 0x31, + 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, + 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x12, 0x7d, 0x0a, 0x10, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, + 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x61, 0x72, 0x6b, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, + 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, - 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x61, - 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, - 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, 0x2a, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x72, - 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, - 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x8d, 0x01, 0x0a, 0x14, 0x53, 0x75, 0x62, 0x6d, 0x69, - 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, - 0x23, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, - 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, - 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x24, 0x3a, 0x01, 0x2a, 0x22, 0x1f, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, - 0x2f, 0x74, 0x72, 0x65, 0x65, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x8e, 0x01, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, - 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, - 0x73, 0x12, 0x25, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, - 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, - 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x3a, 0x01, 0x2a, 0x22, 0x1a, 0x2f, 0x76, 0x31, - 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x46, 0x6f, 0x72, - 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x65, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, - 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, + 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, 0x2a, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, + 0x75, 0x6e, 0x64, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4e, + 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x8d, 0x01, 0x0a, 0x14, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, + 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x23, + 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, + 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, + 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x24, 0x3a, 0x01, 0x2a, 0x22, 0x1f, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, + 0x74, 0x72, 0x65, 0x65, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x8e, 0x01, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, + 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, + 0x12, 0x25, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, + 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, + 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x3a, 0x01, 0x2a, 0x22, 0x1a, 0x2f, 0x76, 0x31, 0x2f, + 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x66, + 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x65, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x12, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0c, - 0x12, 0x0a, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x30, 0x01, 0x12, 0x56, - 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x13, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, - 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x72, - 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x72, - 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x70, 0x69, 0x6e, 0x67, 0x2f, 0x7b, 0x72, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x69, 0x0a, 0x0e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, - 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x12, 0x1d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x12, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0c, 0x12, + 0x0a, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x30, 0x01, 0x12, 0x56, 0x0a, + 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x13, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x72, 0x6b, + 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, + 0x75, 0x6e, 0x64, 0x2f, 0x70, 0x69, 0x6e, 0x67, 0x2f, 0x7b, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x69, 0x0a, 0x0e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, + 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x12, 0x1d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x3a, - 0x01, 0x2a, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x2d, 0x74, - 0x78, 0x12, 0x57, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x17, 0x2e, - 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, - 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, - 0x75, 0x6e, 0x64, 0x2f, 0x7b, 0x74, 0x78, 0x69, 0x64, 0x7d, 0x12, 0x64, 0x0a, 0x0c, 0x47, 0x65, - 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x12, 0x1b, 0x2e, 0x61, 0x72, 0x6b, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, - 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x69, 0x64, 0x2f, 0x7b, 0x69, 0x64, 0x7d, - 0x12, 0x5d, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x18, 0x2e, - 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, - 0x76, 0x74, 0x78, 0x6f, 0x73, 0x2f, 0x7b, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x7d, 0x12, - 0x80, 0x01, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x25, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, - 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x30, 0x01, 0x12, 0x73, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, - 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x20, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x61, 0x72, 0x6b, 0x2e, - 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, - 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x22, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78, - 0x6f, 0x2f, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x12, 0x83, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, - 0x12, 0x23, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, - 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x1a, 0x3a, 0x01, 0x2a, 0x22, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78, 0x6f, - 0x2f, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x2f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x92, 0x01, - 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3d, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x6b, 0x2d, 0x6e, 0x65, 0x74, - 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x61, 0x72, 0x6b, 0x2f, 0x61, 0x70, 0x69, 0x2d, 0x73, 0x70, 0x65, - 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x61, - 0x72, 0x6b, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x72, 0x6b, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x41, 0x58, - 0x58, 0xaa, 0x02, 0x06, 0x41, 0x72, 0x6b, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x06, 0x41, 0x72, 0x6b, - 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x12, 0x41, 0x72, 0x6b, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x07, 0x41, 0x72, 0x6b, 0x3a, 0x3a, - 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x3a, 0x01, + 0x2a, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x2d, 0x74, 0x78, + 0x12, 0x57, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x17, 0x2e, 0x61, + 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, + 0x6e, 0x64, 0x2f, 0x7b, 0x74, 0x78, 0x69, 0x64, 0x7d, 0x12, 0x64, 0x0a, 0x0c, 0x47, 0x65, 0x74, + 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x12, 0x1b, 0x2e, 0x61, 0x72, 0x6b, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, + 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x69, 0x64, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, + 0x5d, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x18, 0x2e, 0x61, + 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x76, + 0x74, 0x78, 0x6f, 0x73, 0x2f, 0x7b, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x7d, 0x12, 0x80, + 0x01, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, + 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, + 0x76, 0x31, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x30, + 0x01, 0x12, 0x73, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, + 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x20, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, + 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x22, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78, 0x6f, + 0x2f, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x12, 0x83, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, + 0x23, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, + 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x1a, 0x3a, 0x01, 0x2a, 0x22, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78, 0x6f, 0x2f, + 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x2f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x92, 0x01, 0x0a, + 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3d, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x6b, 0x2d, 0x6e, 0x65, 0x74, 0x77, + 0x6f, 0x72, 0x6b, 0x2f, 0x61, 0x72, 0x6b, 0x2f, 0x61, 0x70, 0x69, 0x2d, 0x73, 0x70, 0x65, 0x63, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x61, 0x72, + 0x6b, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x72, 0x6b, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x41, 0x58, 0x58, + 0xaa, 0x02, 0x06, 0x41, 0x72, 0x6b, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x06, 0x41, 0x72, 0x6b, 0x5c, + 0x56, 0x31, 0xe2, 0x02, 0x12, 0x41, 0x72, 0x6b, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x07, 0x41, 0x72, 0x6b, 0x3a, 0x3a, 0x56, + 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3576,7 +3628,7 @@ func file_ark_v1_service_proto_rawDescGZIP() []byte { } var file_ark_v1_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_ark_v1_service_proto_msgTypes = make([]protoimpl.MessageInfo, 51) +var file_ark_v1_service_proto_msgTypes = make([]protoimpl.MessageInfo, 52) var file_ark_v1_service_proto_goTypes = []interface{}{ (RoundStage)(0), // 0: ark.v1.RoundStage (*GetInfoRequest)(nil), // 1: ark.v1.GetInfoRequest @@ -3613,101 +3665,103 @@ var file_ark_v1_service_proto_goTypes = []interface{}{ (*Round)(nil), // 32: ark.v1.Round (*Outpoint)(nil), // 33: ark.v1.Outpoint (*Input)(nil), // 34: ark.v1.Input - (*Output)(nil), // 35: ark.v1.Output - (*Tree)(nil), // 36: ark.v1.Tree - (*TreeLevel)(nil), // 37: ark.v1.TreeLevel - (*Node)(nil), // 38: ark.v1.Node - (*Vtxo)(nil), // 39: ark.v1.Vtxo - (*GetTransactionsStreamRequest)(nil), // 40: ark.v1.GetTransactionsStreamRequest - (*GetTransactionsStreamResponse)(nil), // 41: ark.v1.GetTransactionsStreamResponse - (*RoundTransaction)(nil), // 42: ark.v1.RoundTransaction - (*RedeemTransaction)(nil), // 43: ark.v1.RedeemTransaction - (*OwnershipProof)(nil), // 44: ark.v1.OwnershipProof - (*SignedVtxoOutpoint)(nil), // 45: ark.v1.SignedVtxoOutpoint - (*SetNostrRecipientRequest)(nil), // 46: ark.v1.SetNostrRecipientRequest - (*SetNostrRecipientResponse)(nil), // 47: ark.v1.SetNostrRecipientResponse - (*DeleteNostrRecipientRequest)(nil), // 48: ark.v1.DeleteNostrRecipientRequest - (*DeleteNostrRecipientResponse)(nil), // 49: ark.v1.DeleteNostrRecipientResponse - (*Tapscripts)(nil), // 50: ark.v1.Tapscripts - (*MarketHour)(nil), // 51: ark.v1.MarketHour - (*timestamppb.Timestamp)(nil), // 52: google.protobuf.Timestamp - (*durationpb.Duration)(nil), // 53: google.protobuf.Duration + (*Musig2)(nil), // 35: ark.v1.Musig2 + (*Output)(nil), // 36: ark.v1.Output + (*Tree)(nil), // 37: ark.v1.Tree + (*TreeLevel)(nil), // 38: ark.v1.TreeLevel + (*Node)(nil), // 39: ark.v1.Node + (*Vtxo)(nil), // 40: ark.v1.Vtxo + (*GetTransactionsStreamRequest)(nil), // 41: ark.v1.GetTransactionsStreamRequest + (*GetTransactionsStreamResponse)(nil), // 42: ark.v1.GetTransactionsStreamResponse + (*RoundTransaction)(nil), // 43: ark.v1.RoundTransaction + (*RedeemTransaction)(nil), // 44: ark.v1.RedeemTransaction + (*OwnershipProof)(nil), // 45: ark.v1.OwnershipProof + (*SignedVtxoOutpoint)(nil), // 46: ark.v1.SignedVtxoOutpoint + (*SetNostrRecipientRequest)(nil), // 47: ark.v1.SetNostrRecipientRequest + (*SetNostrRecipientResponse)(nil), // 48: ark.v1.SetNostrRecipientResponse + (*DeleteNostrRecipientRequest)(nil), // 49: ark.v1.DeleteNostrRecipientRequest + (*DeleteNostrRecipientResponse)(nil), // 50: ark.v1.DeleteNostrRecipientResponse + (*Tapscripts)(nil), // 51: ark.v1.Tapscripts + (*MarketHour)(nil), // 52: ark.v1.MarketHour + (*timestamppb.Timestamp)(nil), // 53: google.protobuf.Timestamp + (*durationpb.Duration)(nil), // 54: google.protobuf.Duration } var file_ark_v1_service_proto_depIdxs = []int32{ - 51, // 0: ark.v1.GetInfoResponse.market_hour:type_name -> ark.v1.MarketHour - 50, // 1: ark.v1.GetBoardingAddressResponse.tapscripts:type_name -> ark.v1.Tapscripts + 52, // 0: ark.v1.GetInfoResponse.market_hour:type_name -> ark.v1.MarketHour + 51, // 1: ark.v1.GetBoardingAddressResponse.tapscripts:type_name -> ark.v1.Tapscripts 34, // 2: ark.v1.RegisterInputsForNextRoundRequest.inputs:type_name -> ark.v1.Input - 35, // 3: ark.v1.RegisterOutputsForNextRoundRequest.outputs:type_name -> ark.v1.Output - 27, // 4: ark.v1.GetEventStreamResponse.round_finalization:type_name -> ark.v1.RoundFinalizationEvent - 28, // 5: ark.v1.GetEventStreamResponse.round_finalized:type_name -> ark.v1.RoundFinalizedEvent - 29, // 6: ark.v1.GetEventStreamResponse.round_failed:type_name -> ark.v1.RoundFailed - 30, // 7: ark.v1.GetEventStreamResponse.round_signing:type_name -> ark.v1.RoundSigningEvent - 31, // 8: ark.v1.GetEventStreamResponse.round_signing_nonces_generated:type_name -> ark.v1.RoundSigningNoncesGeneratedEvent - 32, // 9: ark.v1.GetRoundResponse.round:type_name -> ark.v1.Round - 32, // 10: ark.v1.GetRoundByIdResponse.round:type_name -> ark.v1.Round - 39, // 11: ark.v1.ListVtxosResponse.spendable_vtxos:type_name -> ark.v1.Vtxo - 39, // 12: ark.v1.ListVtxosResponse.spent_vtxos:type_name -> ark.v1.Vtxo - 36, // 13: ark.v1.RoundFinalizationEvent.vtxo_tree:type_name -> ark.v1.Tree - 36, // 14: ark.v1.RoundSigningEvent.unsigned_vtxo_tree:type_name -> ark.v1.Tree - 36, // 15: ark.v1.Round.vtxo_tree:type_name -> ark.v1.Tree - 0, // 16: ark.v1.Round.stage:type_name -> ark.v1.RoundStage - 33, // 17: ark.v1.Input.outpoint:type_name -> ark.v1.Outpoint - 50, // 18: ark.v1.Input.tapscripts:type_name -> ark.v1.Tapscripts - 37, // 19: ark.v1.Tree.levels:type_name -> ark.v1.TreeLevel - 38, // 20: ark.v1.TreeLevel.nodes:type_name -> ark.v1.Node - 33, // 21: ark.v1.Vtxo.outpoint:type_name -> ark.v1.Outpoint - 42, // 22: ark.v1.GetTransactionsStreamResponse.round:type_name -> ark.v1.RoundTransaction - 43, // 23: ark.v1.GetTransactionsStreamResponse.redeem:type_name -> ark.v1.RedeemTransaction - 33, // 24: ark.v1.RoundTransaction.spent_vtxos:type_name -> ark.v1.Outpoint - 39, // 25: ark.v1.RoundTransaction.spendable_vtxos:type_name -> ark.v1.Vtxo - 33, // 26: ark.v1.RoundTransaction.claimed_boarding_utxos:type_name -> ark.v1.Outpoint - 33, // 27: ark.v1.RedeemTransaction.spent_vtxos:type_name -> ark.v1.Outpoint - 39, // 28: ark.v1.RedeemTransaction.spendable_vtxos:type_name -> ark.v1.Vtxo - 33, // 29: ark.v1.SignedVtxoOutpoint.outpoint:type_name -> ark.v1.Outpoint - 44, // 30: ark.v1.SignedVtxoOutpoint.proof:type_name -> ark.v1.OwnershipProof - 45, // 31: ark.v1.SetNostrRecipientRequest.vtxos:type_name -> ark.v1.SignedVtxoOutpoint - 45, // 32: ark.v1.DeleteNostrRecipientRequest.vtxos:type_name -> ark.v1.SignedVtxoOutpoint - 52, // 33: ark.v1.MarketHour.next_start_time:type_name -> google.protobuf.Timestamp - 52, // 34: ark.v1.MarketHour.next_end_time:type_name -> google.protobuf.Timestamp - 53, // 35: ark.v1.MarketHour.period:type_name -> google.protobuf.Duration - 53, // 36: ark.v1.MarketHour.round_interval:type_name -> google.protobuf.Duration - 1, // 37: ark.v1.ArkService.GetInfo:input_type -> ark.v1.GetInfoRequest - 3, // 38: ark.v1.ArkService.GetBoardingAddress:input_type -> ark.v1.GetBoardingAddressRequest - 5, // 39: ark.v1.ArkService.RegisterInputsForNextRound:input_type -> ark.v1.RegisterInputsForNextRoundRequest - 7, // 40: ark.v1.ArkService.RegisterOutputsForNextRound:input_type -> ark.v1.RegisterOutputsForNextRoundRequest - 9, // 41: ark.v1.ArkService.SubmitTreeNonces:input_type -> ark.v1.SubmitTreeNoncesRequest - 11, // 42: ark.v1.ArkService.SubmitTreeSignatures:input_type -> ark.v1.SubmitTreeSignaturesRequest - 13, // 43: ark.v1.ArkService.SubmitSignedForfeitTxs:input_type -> ark.v1.SubmitSignedForfeitTxsRequest - 15, // 44: ark.v1.ArkService.GetEventStream:input_type -> ark.v1.GetEventStreamRequest - 17, // 45: ark.v1.ArkService.Ping:input_type -> ark.v1.PingRequest - 19, // 46: ark.v1.ArkService.SubmitRedeemTx:input_type -> ark.v1.SubmitRedeemTxRequest - 21, // 47: ark.v1.ArkService.GetRound:input_type -> ark.v1.GetRoundRequest - 23, // 48: ark.v1.ArkService.GetRoundById:input_type -> ark.v1.GetRoundByIdRequest - 25, // 49: ark.v1.ArkService.ListVtxos:input_type -> ark.v1.ListVtxosRequest - 40, // 50: ark.v1.ArkService.GetTransactionsStream:input_type -> ark.v1.GetTransactionsStreamRequest - 46, // 51: ark.v1.ArkService.SetNostrRecipient:input_type -> ark.v1.SetNostrRecipientRequest - 48, // 52: ark.v1.ArkService.DeleteNostrRecipient:input_type -> ark.v1.DeleteNostrRecipientRequest - 2, // 53: ark.v1.ArkService.GetInfo:output_type -> ark.v1.GetInfoResponse - 4, // 54: ark.v1.ArkService.GetBoardingAddress:output_type -> ark.v1.GetBoardingAddressResponse - 6, // 55: ark.v1.ArkService.RegisterInputsForNextRound:output_type -> ark.v1.RegisterInputsForNextRoundResponse - 8, // 56: ark.v1.ArkService.RegisterOutputsForNextRound:output_type -> ark.v1.RegisterOutputsForNextRoundResponse - 10, // 57: ark.v1.ArkService.SubmitTreeNonces:output_type -> ark.v1.SubmitTreeNoncesResponse - 12, // 58: ark.v1.ArkService.SubmitTreeSignatures:output_type -> ark.v1.SubmitTreeSignaturesResponse - 14, // 59: ark.v1.ArkService.SubmitSignedForfeitTxs:output_type -> ark.v1.SubmitSignedForfeitTxsResponse - 16, // 60: ark.v1.ArkService.GetEventStream:output_type -> ark.v1.GetEventStreamResponse - 18, // 61: ark.v1.ArkService.Ping:output_type -> ark.v1.PingResponse - 20, // 62: ark.v1.ArkService.SubmitRedeemTx:output_type -> ark.v1.SubmitRedeemTxResponse - 22, // 63: ark.v1.ArkService.GetRound:output_type -> ark.v1.GetRoundResponse - 24, // 64: ark.v1.ArkService.GetRoundById:output_type -> ark.v1.GetRoundByIdResponse - 26, // 65: ark.v1.ArkService.ListVtxos:output_type -> ark.v1.ListVtxosResponse - 41, // 66: ark.v1.ArkService.GetTransactionsStream:output_type -> ark.v1.GetTransactionsStreamResponse - 47, // 67: ark.v1.ArkService.SetNostrRecipient:output_type -> ark.v1.SetNostrRecipientResponse - 49, // 68: ark.v1.ArkService.DeleteNostrRecipient:output_type -> ark.v1.DeleteNostrRecipientResponse - 53, // [53:69] is the sub-list for method output_type - 37, // [37:53] is the sub-list for method input_type - 37, // [37:37] is the sub-list for extension type_name - 37, // [37:37] is the sub-list for extension extendee - 0, // [0:37] is the sub-list for field type_name + 36, // 3: ark.v1.RegisterOutputsForNextRoundRequest.outputs:type_name -> ark.v1.Output + 35, // 4: ark.v1.RegisterOutputsForNextRoundRequest.musig2:type_name -> ark.v1.Musig2 + 27, // 5: ark.v1.GetEventStreamResponse.round_finalization:type_name -> ark.v1.RoundFinalizationEvent + 28, // 6: ark.v1.GetEventStreamResponse.round_finalized:type_name -> ark.v1.RoundFinalizedEvent + 29, // 7: ark.v1.GetEventStreamResponse.round_failed:type_name -> ark.v1.RoundFailed + 30, // 8: ark.v1.GetEventStreamResponse.round_signing:type_name -> ark.v1.RoundSigningEvent + 31, // 9: ark.v1.GetEventStreamResponse.round_signing_nonces_generated:type_name -> ark.v1.RoundSigningNoncesGeneratedEvent + 32, // 10: ark.v1.GetRoundResponse.round:type_name -> ark.v1.Round + 32, // 11: ark.v1.GetRoundByIdResponse.round:type_name -> ark.v1.Round + 40, // 12: ark.v1.ListVtxosResponse.spendable_vtxos:type_name -> ark.v1.Vtxo + 40, // 13: ark.v1.ListVtxosResponse.spent_vtxos:type_name -> ark.v1.Vtxo + 37, // 14: ark.v1.RoundFinalizationEvent.vtxo_tree:type_name -> ark.v1.Tree + 37, // 15: ark.v1.RoundSigningEvent.unsigned_vtxo_tree:type_name -> ark.v1.Tree + 37, // 16: ark.v1.Round.vtxo_tree:type_name -> ark.v1.Tree + 0, // 17: ark.v1.Round.stage:type_name -> ark.v1.RoundStage + 33, // 18: ark.v1.Input.outpoint:type_name -> ark.v1.Outpoint + 51, // 19: ark.v1.Input.tapscripts:type_name -> ark.v1.Tapscripts + 38, // 20: ark.v1.Tree.levels:type_name -> ark.v1.TreeLevel + 39, // 21: ark.v1.TreeLevel.nodes:type_name -> ark.v1.Node + 33, // 22: ark.v1.Vtxo.outpoint:type_name -> ark.v1.Outpoint + 43, // 23: ark.v1.GetTransactionsStreamResponse.round:type_name -> ark.v1.RoundTransaction + 44, // 24: ark.v1.GetTransactionsStreamResponse.redeem:type_name -> ark.v1.RedeemTransaction + 33, // 25: ark.v1.RoundTransaction.spent_vtxos:type_name -> ark.v1.Outpoint + 40, // 26: ark.v1.RoundTransaction.spendable_vtxos:type_name -> ark.v1.Vtxo + 33, // 27: ark.v1.RoundTransaction.claimed_boarding_utxos:type_name -> ark.v1.Outpoint + 33, // 28: ark.v1.RedeemTransaction.spent_vtxos:type_name -> ark.v1.Outpoint + 40, // 29: ark.v1.RedeemTransaction.spendable_vtxos:type_name -> ark.v1.Vtxo + 33, // 30: ark.v1.SignedVtxoOutpoint.outpoint:type_name -> ark.v1.Outpoint + 45, // 31: ark.v1.SignedVtxoOutpoint.proof:type_name -> ark.v1.OwnershipProof + 46, // 32: ark.v1.SetNostrRecipientRequest.vtxos:type_name -> ark.v1.SignedVtxoOutpoint + 46, // 33: ark.v1.DeleteNostrRecipientRequest.vtxos:type_name -> ark.v1.SignedVtxoOutpoint + 53, // 34: ark.v1.MarketHour.next_start_time:type_name -> google.protobuf.Timestamp + 53, // 35: ark.v1.MarketHour.next_end_time:type_name -> google.protobuf.Timestamp + 54, // 36: ark.v1.MarketHour.period:type_name -> google.protobuf.Duration + 54, // 37: ark.v1.MarketHour.round_interval:type_name -> google.protobuf.Duration + 1, // 38: ark.v1.ArkService.GetInfo:input_type -> ark.v1.GetInfoRequest + 3, // 39: ark.v1.ArkService.GetBoardingAddress:input_type -> ark.v1.GetBoardingAddressRequest + 5, // 40: ark.v1.ArkService.RegisterInputsForNextRound:input_type -> ark.v1.RegisterInputsForNextRoundRequest + 7, // 41: ark.v1.ArkService.RegisterOutputsForNextRound:input_type -> ark.v1.RegisterOutputsForNextRoundRequest + 9, // 42: ark.v1.ArkService.SubmitTreeNonces:input_type -> ark.v1.SubmitTreeNoncesRequest + 11, // 43: ark.v1.ArkService.SubmitTreeSignatures:input_type -> ark.v1.SubmitTreeSignaturesRequest + 13, // 44: ark.v1.ArkService.SubmitSignedForfeitTxs:input_type -> ark.v1.SubmitSignedForfeitTxsRequest + 15, // 45: ark.v1.ArkService.GetEventStream:input_type -> ark.v1.GetEventStreamRequest + 17, // 46: ark.v1.ArkService.Ping:input_type -> ark.v1.PingRequest + 19, // 47: ark.v1.ArkService.SubmitRedeemTx:input_type -> ark.v1.SubmitRedeemTxRequest + 21, // 48: ark.v1.ArkService.GetRound:input_type -> ark.v1.GetRoundRequest + 23, // 49: ark.v1.ArkService.GetRoundById:input_type -> ark.v1.GetRoundByIdRequest + 25, // 50: ark.v1.ArkService.ListVtxos:input_type -> ark.v1.ListVtxosRequest + 41, // 51: ark.v1.ArkService.GetTransactionsStream:input_type -> ark.v1.GetTransactionsStreamRequest + 47, // 52: ark.v1.ArkService.SetNostrRecipient:input_type -> ark.v1.SetNostrRecipientRequest + 49, // 53: ark.v1.ArkService.DeleteNostrRecipient:input_type -> ark.v1.DeleteNostrRecipientRequest + 2, // 54: ark.v1.ArkService.GetInfo:output_type -> ark.v1.GetInfoResponse + 4, // 55: ark.v1.ArkService.GetBoardingAddress:output_type -> ark.v1.GetBoardingAddressResponse + 6, // 56: ark.v1.ArkService.RegisterInputsForNextRound:output_type -> ark.v1.RegisterInputsForNextRoundResponse + 8, // 57: ark.v1.ArkService.RegisterOutputsForNextRound:output_type -> ark.v1.RegisterOutputsForNextRoundResponse + 10, // 58: ark.v1.ArkService.SubmitTreeNonces:output_type -> ark.v1.SubmitTreeNoncesResponse + 12, // 59: ark.v1.ArkService.SubmitTreeSignatures:output_type -> ark.v1.SubmitTreeSignaturesResponse + 14, // 60: ark.v1.ArkService.SubmitSignedForfeitTxs:output_type -> ark.v1.SubmitSignedForfeitTxsResponse + 16, // 61: ark.v1.ArkService.GetEventStream:output_type -> ark.v1.GetEventStreamResponse + 18, // 62: ark.v1.ArkService.Ping:output_type -> ark.v1.PingResponse + 20, // 63: ark.v1.ArkService.SubmitRedeemTx:output_type -> ark.v1.SubmitRedeemTxResponse + 22, // 64: ark.v1.ArkService.GetRound:output_type -> ark.v1.GetRoundResponse + 24, // 65: ark.v1.ArkService.GetRoundById:output_type -> ark.v1.GetRoundByIdResponse + 26, // 66: ark.v1.ArkService.ListVtxos:output_type -> ark.v1.ListVtxosResponse + 42, // 67: ark.v1.ArkService.GetTransactionsStream:output_type -> ark.v1.GetTransactionsStreamResponse + 48, // 68: ark.v1.ArkService.SetNostrRecipient:output_type -> ark.v1.SetNostrRecipientResponse + 50, // 69: ark.v1.ArkService.DeleteNostrRecipient:output_type -> ark.v1.DeleteNostrRecipientResponse + 54, // [54:70] is the sub-list for method output_type + 38, // [38:54] is the sub-list for method input_type + 38, // [38:38] is the sub-list for extension type_name + 38, // [38:38] is the sub-list for extension extendee + 0, // [0:38] is the sub-list for field type_name } func init() { file_ark_v1_service_proto_init() } @@ -4125,7 +4179,7 @@ func file_ark_v1_service_proto_init() { } } file_ark_v1_service_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Output); i { + switch v := v.(*Musig2); i { case 0: return &v.state case 1: @@ -4137,7 +4191,7 @@ func file_ark_v1_service_proto_init() { } } file_ark_v1_service_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Tree); i { + switch v := v.(*Output); i { case 0: return &v.state case 1: @@ -4149,7 +4203,7 @@ func file_ark_v1_service_proto_init() { } } file_ark_v1_service_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TreeLevel); i { + switch v := v.(*Tree); i { case 0: return &v.state case 1: @@ -4161,7 +4215,7 @@ func file_ark_v1_service_proto_init() { } } file_ark_v1_service_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Node); i { + switch v := v.(*TreeLevel); i { case 0: return &v.state case 1: @@ -4173,7 +4227,7 @@ func file_ark_v1_service_proto_init() { } } file_ark_v1_service_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Vtxo); i { + switch v := v.(*Node); i { case 0: return &v.state case 1: @@ -4185,7 +4239,7 @@ func file_ark_v1_service_proto_init() { } } file_ark_v1_service_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetTransactionsStreamRequest); i { + switch v := v.(*Vtxo); i { case 0: return &v.state case 1: @@ -4197,7 +4251,7 @@ func file_ark_v1_service_proto_init() { } } file_ark_v1_service_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetTransactionsStreamResponse); i { + switch v := v.(*GetTransactionsStreamRequest); i { case 0: return &v.state case 1: @@ -4209,7 +4263,7 @@ func file_ark_v1_service_proto_init() { } } file_ark_v1_service_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RoundTransaction); i { + switch v := v.(*GetTransactionsStreamResponse); i { case 0: return &v.state case 1: @@ -4221,7 +4275,7 @@ func file_ark_v1_service_proto_init() { } } file_ark_v1_service_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RedeemTransaction); i { + switch v := v.(*RoundTransaction); i { case 0: return &v.state case 1: @@ -4233,7 +4287,7 @@ func file_ark_v1_service_proto_init() { } } file_ark_v1_service_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OwnershipProof); i { + switch v := v.(*RedeemTransaction); i { case 0: return &v.state case 1: @@ -4245,7 +4299,7 @@ func file_ark_v1_service_proto_init() { } } file_ark_v1_service_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedVtxoOutpoint); i { + switch v := v.(*OwnershipProof); i { case 0: return &v.state case 1: @@ -4257,7 +4311,7 @@ func file_ark_v1_service_proto_init() { } } file_ark_v1_service_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetNostrRecipientRequest); i { + switch v := v.(*SignedVtxoOutpoint); i { case 0: return &v.state case 1: @@ -4269,7 +4323,7 @@ func file_ark_v1_service_proto_init() { } } file_ark_v1_service_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetNostrRecipientResponse); i { + switch v := v.(*SetNostrRecipientRequest); i { case 0: return &v.state case 1: @@ -4281,7 +4335,7 @@ func file_ark_v1_service_proto_init() { } } file_ark_v1_service_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeleteNostrRecipientRequest); i { + switch v := v.(*SetNostrRecipientResponse); i { case 0: return &v.state case 1: @@ -4293,7 +4347,7 @@ func file_ark_v1_service_proto_init() { } } file_ark_v1_service_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeleteNostrRecipientResponse); i { + switch v := v.(*DeleteNostrRecipientRequest); i { case 0: return &v.state case 1: @@ -4305,7 +4359,7 @@ func file_ark_v1_service_proto_init() { } } file_ark_v1_service_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Tapscripts); i { + switch v := v.(*DeleteNostrRecipientResponse); i { case 0: return &v.state case 1: @@ -4317,6 +4371,18 @@ func file_ark_v1_service_proto_init() { } } file_ark_v1_service_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Tapscripts); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ark_v1_service_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*MarketHour); i { case 0: return &v.state @@ -4333,6 +4399,7 @@ func file_ark_v1_service_proto_init() { (*GetBoardingAddressResponse_Descriptor_)(nil), (*GetBoardingAddressResponse_Tapscripts)(nil), } + file_ark_v1_service_proto_msgTypes[6].OneofWrappers = []interface{}{} file_ark_v1_service_proto_msgTypes[12].OneofWrappers = []interface{}{} file_ark_v1_service_proto_msgTypes[15].OneofWrappers = []interface{}{ (*GetEventStreamResponse_RoundFinalization)(nil), @@ -4345,7 +4412,7 @@ func file_ark_v1_service_proto_init() { (*Input_Descriptor_)(nil), (*Input_Tapscripts)(nil), } - file_ark_v1_service_proto_msgTypes[40].OneofWrappers = []interface{}{ + file_ark_v1_service_proto_msgTypes[41].OneofWrappers = []interface{}{ (*GetTransactionsStreamResponse_Round)(nil), (*GetTransactionsStreamResponse_Redeem)(nil), } @@ -4355,7 +4422,7 @@ func file_ark_v1_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_ark_v1_service_proto_rawDesc, NumEnums: 1, - NumMessages: 51, + NumMessages: 52, NumExtensions: 0, NumServices: 1, }, diff --git a/common/bitcointree/builder.go b/common/bitcointree/builder.go index 39893457a..5ea2ac834 100644 --- a/common/bitcointree/builder.go +++ b/common/bitcointree/builder.go @@ -243,15 +243,19 @@ func createRootNode( cosignersALL := make([]*secp256k1.PublicKey, 0) for _, r := range receivers { - if r.Type != tree.SignAll { + if r.Musig2Data == nil { + return nil, fmt.Errorf("musig2 data is nil for %s", r.PubKey) + } + + if r.Musig2Data.SigningType != tree.SignAll { continue } - if len(r.SignersPublicKeys) == 0 { - return nil, fmt.Errorf("signers public keys for %s are empty", r.PubKey) + if len(r.Musig2Data.CosignersPublicKeys) == 0 { + return nil, fmt.Errorf("cosigners public keys for %s are empty", r.PubKey) } - for _, cosigner := range r.SignersPublicKeys { + for _, cosigner := range r.Musig2Data.CosignersPublicKeys { pubkeyBytes, err := hex.DecodeString(cosigner) if err != nil { return nil, err @@ -284,9 +288,9 @@ func createRootNode( cosigners := make([]*secp256k1.PublicKey, 0) - switch r.Type { + switch r.Musig2Data.SigningType { case tree.SignBranch: - for _, cosigner := range r.SignersPublicKeys { + for _, cosigner := range r.Musig2Data.CosignersPublicKeys { pubkeyBytes, err := hex.DecodeString(cosigner) if err != nil { return nil, fmt.Errorf("failed to decode cosigner pubkey: %w", err) @@ -311,7 +315,7 @@ func createRootNode( amount: int64(r.Amount), pkScript: pkScript, cosigners: cosigners, - signerType: r.Type, + signerType: r.Musig2Data.SigningType, } nodes = append(nodes, leafNode) } diff --git a/common/bitcointree/musig2_test.go b/common/bitcointree/musig2_test.go index d1f70598e..81497deac 100644 --- a/common/bitcointree/musig2_test.go +++ b/common/bitcointree/musig2_test.go @@ -131,9 +131,12 @@ func generateReceiversFixture(count int) ([]tree.VtxoLeaf, []*secp256k1.PrivateK receivers = append(receivers, tree.VtxoLeaf{ PubKey: "0000000000000000000000000000000000000000000000000000000000000002", Amount: uint64((i + 1) * 1000), - SignersPublicKeys: []string{ - hex.EncodeToString(prvkey.PubKey().SerializeCompressed()), - hex.EncodeToString(serverPrivKey.PubKey().SerializeCompressed()), + Musig2Data: &tree.Musig2{ + CosignersPublicKeys: []string{ + hex.EncodeToString(prvkey.PubKey().SerializeCompressed()), + hex.EncodeToString(serverPrivKey.PubKey().SerializeCompressed()), + }, + SigningType: tree.SignAll, }, }) privKeys = append(privKeys, prvkey) @@ -145,10 +148,12 @@ func withSigningType(signingType tree.SigningType, receivers []tree.VtxoLeaf) [] newReceivers := make([]tree.VtxoLeaf, 0, len(receivers)) for _, receiver := range receivers { newReceivers = append(newReceivers, tree.VtxoLeaf{ - PubKey: receiver.PubKey, - Amount: receiver.Amount, - SignersPublicKeys: receiver.SignersPublicKeys, - Type: signingType, + PubKey: receiver.PubKey, + Amount: receiver.Amount, + Musig2Data: &tree.Musig2{ + CosignersPublicKeys: receiver.Musig2Data.CosignersPublicKeys, + SigningType: signingType, + }, }) } return newReceivers diff --git a/common/tree/type.go b/common/tree/type.go index 1ab753a60..5d62cefd4 100644 --- a/common/tree/type.go +++ b/common/tree/type.go @@ -16,8 +16,12 @@ const ( type TreeFactory func(outpoint psetv2.InputArgs) (VtxoTree, error) type VtxoLeaf struct { - PubKey string - Amount uint64 - Type SigningType - SignersPublicKeys []string + PubKey string + Amount uint64 + Musig2Data *Musig2 +} + +type Musig2 struct { + CosignersPublicKeys []string + SigningType SigningType } diff --git a/pkg/client-sdk/client/client.go b/pkg/client-sdk/client/client.go index 27bc67c6b..41c9a5d41 100644 --- a/pkg/client-sdk/client/client.go +++ b/pkg/client-sdk/client/client.go @@ -25,13 +25,13 @@ type RoundEvent interface { type TransportClient interface { GetInfo(ctx context.Context) (*Info, error) RegisterInputsForNextRound( - ctx context.Context, inputs []Input, signerPubKeys []string, signingType tree.SigningType, + ctx context.Context, inputs []Input, ) (string, error) RegisterNotesForNextRound( - ctx context.Context, notes []string, signerPubKeys []string, signingType tree.SigningType, + ctx context.Context, notes []string, ) (string, error) RegisterOutputsForNextRound( - ctx context.Context, requestID string, outputs []Output, + ctx context.Context, requestID string, outputs []Output, musig2 *tree.Musig2, ) error SubmitTreeNonces( ctx context.Context, roundID, cosignerPubkey string, nonces bitcointree.TreeNonces, diff --git a/pkg/client-sdk/client/grpc/client.go b/pkg/client-sdk/client/grpc/client.go index c9005e035..df1892e33 100644 --- a/pkg/client-sdk/client/grpc/client.go +++ b/pkg/client-sdk/client/grpc/client.go @@ -85,15 +85,11 @@ func (a *grpcClient) GetBoardingAddress( } func (a *grpcClient) RegisterInputsForNextRound( - ctx context.Context, inputs []client.Input, signerPubKeys []string, signingType tree.SigningType, + ctx context.Context, inputs []client.Input, ) (string, error) { req := &arkv1.RegisterInputsForNextRoundRequest{ Inputs: ins(inputs).toProto(), } - if len(signerPubKeys) > 0 { - req.SignerPubkeys = signerPubKeys - req.SigningType = uint32(signingType) - } resp, err := a.svc.RegisterInputsForNextRound(ctx, req) if err != nil { @@ -103,15 +99,11 @@ func (a *grpcClient) RegisterInputsForNextRound( } func (a *grpcClient) RegisterNotesForNextRound( - ctx context.Context, notes []string, signerPubKeys []string, signingType tree.SigningType, + ctx context.Context, notes []string, ) (string, error) { req := &arkv1.RegisterInputsForNextRoundRequest{ Notes: notes, } - if len(signerPubKeys) > 0 { - req.SignerPubkeys = signerPubKeys - req.SigningType = uint32(signingType) - } resp, err := a.svc.RegisterInputsForNextRound(ctx, req) if err != nil { return "", err @@ -120,12 +112,18 @@ func (a *grpcClient) RegisterNotesForNextRound( } func (a *grpcClient) RegisterOutputsForNextRound( - ctx context.Context, requestID string, outputs []client.Output, + ctx context.Context, requestID string, outputs []client.Output, musig2 *tree.Musig2, ) error { req := &arkv1.RegisterOutputsForNextRoundRequest{ RequestId: requestID, Outputs: outs(outputs).toProto(), } + if musig2 != nil { + req.Musig2 = &arkv1.Musig2{ + CosignersPublicKeys: musig2.CosignersPublicKeys, + SigningType: uint32(musig2.SigningType), + } + } _, err := a.svc.RegisterOutputsForNextRound(ctx, req) return err } diff --git a/pkg/client-sdk/client/rest/client.go b/pkg/client-sdk/client/rest/client.go index fff3853cc..a18a34be4 100644 --- a/pkg/client-sdk/client/rest/client.go +++ b/pkg/client-sdk/client/rest/client.go @@ -107,7 +107,7 @@ func (a *restClient) GetBoardingAddress( } func (a *restClient) RegisterInputsForNextRound( - ctx context.Context, inputs []client.Input, signerPubKeys []string, signingType tree.SigningType, + ctx context.Context, inputs []client.Input, ) (string, error) { ins := make([]*models.V1Input, 0, len(inputs)) for _, i := range inputs { @@ -124,11 +124,6 @@ func (a *restClient) RegisterInputsForNextRound( body := &models.V1RegisterInputsForNextRoundRequest{ Inputs: ins, } - if len(signerPubKeys) > 0 { - body.SignerPubkeys = signerPubKeys - body.SigningType = int64(signingType) - } - resp, err := a.svc.ArkServiceRegisterInputsForNextRound( ark_service.NewArkServiceRegisterInputsForNextRoundParams().WithBody(body), ) @@ -140,15 +135,11 @@ func (a *restClient) RegisterInputsForNextRound( } func (a *restClient) RegisterNotesForNextRound( - ctx context.Context, notes []string, signerPubKeys []string, signingType tree.SigningType, + ctx context.Context, notes []string, ) (string, error) { body := &models.V1RegisterInputsForNextRoundRequest{ Notes: notes, } - if len(signerPubKeys) > 0 { - body.SignerPubkeys = signerPubKeys - body.SigningType = int64(signingType) - } resp, err := a.svc.ArkServiceRegisterInputsForNextRound( ark_service.NewArkServiceRegisterInputsForNextRoundParams().WithBody(body), ) @@ -159,7 +150,7 @@ func (a *restClient) RegisterNotesForNextRound( } func (a *restClient) RegisterOutputsForNextRound( - ctx context.Context, requestID string, outputs []client.Output, + ctx context.Context, requestID string, outputs []client.Output, musig2 *tree.Musig2, ) error { outs := make([]*models.V1Output, 0, len(outputs)) for _, o := range outputs { @@ -172,7 +163,12 @@ func (a *restClient) RegisterOutputsForNextRound( RequestID: requestID, Outputs: outs, } - + if musig2 != nil { + body.Musig2 = &models.V1Musig2{ + CosignersPublicKeys: musig2.CosignersPublicKeys, + SigningType: int64(musig2.SigningType), + } + } _, err := a.svc.ArkServiceRegisterOutputsForNextRound( ark_service.NewArkServiceRegisterOutputsForNextRoundParams().WithBody(&body), ) diff --git a/pkg/client-sdk/client/rest/service/models/v1_musig2.go b/pkg/client-sdk/client/rest/service/models/v1_musig2.go new file mode 100644 index 000000000..90df1329b --- /dev/null +++ b/pkg/client-sdk/client/rest/service/models/v1_musig2.go @@ -0,0 +1,53 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// V1Musig2 v1 musig2 +// +// swagger:model v1Musig2 +type V1Musig2 struct { + + // cosigners public keys + CosignersPublicKeys []string `json:"cosignersPublicKeys"` + + // signing type + SigningType int64 `json:"signingType,omitempty"` +} + +// Validate validates this v1 musig2 +func (m *V1Musig2) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this v1 musig2 based on context it is used +func (m *V1Musig2) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *V1Musig2) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *V1Musig2) UnmarshalBinary(b []byte) error { + var res V1Musig2 + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/pkg/client-sdk/client/rest/service/models/v1_register_inputs_for_next_round_request.go b/pkg/client-sdk/client/rest/service/models/v1_register_inputs_for_next_round_request.go index afb534394..96e0d4a17 100644 --- a/pkg/client-sdk/client/rest/service/models/v1_register_inputs_for_next_round_request.go +++ b/pkg/client-sdk/client/rest/service/models/v1_register_inputs_for_next_round_request.go @@ -24,12 +24,6 @@ type V1RegisterInputsForNextRoundRequest struct { // notes Notes []string `json:"notes"` - - // signer pubkeys - SignerPubkeys []string `json:"signerPubkeys"` - - // signing type - SigningType int64 `json:"signingType,omitempty"` } // Validate validates this v1 register inputs for next round request diff --git a/pkg/client-sdk/client/rest/service/models/v1_register_outputs_for_next_round_request.go b/pkg/client-sdk/client/rest/service/models/v1_register_outputs_for_next_round_request.go index 812d9769f..bc2581baa 100644 --- a/pkg/client-sdk/client/rest/service/models/v1_register_outputs_for_next_round_request.go +++ b/pkg/client-sdk/client/rest/service/models/v1_register_outputs_for_next_round_request.go @@ -19,6 +19,9 @@ import ( // swagger:model v1RegisterOutputsForNextRoundRequest type V1RegisterOutputsForNextRoundRequest struct { + // musig2 + Musig2 *V1Musig2 `json:"musig2,omitempty"` + // List of receivers for to convert to leaves in the next VTXO tree. Outputs []*V1Output `json:"outputs"` @@ -30,6 +33,10 @@ type V1RegisterOutputsForNextRoundRequest struct { func (m *V1RegisterOutputsForNextRoundRequest) Validate(formats strfmt.Registry) error { var res []error + if err := m.validateMusig2(formats); err != nil { + res = append(res, err) + } + if err := m.validateOutputs(formats); err != nil { res = append(res, err) } @@ -40,6 +47,25 @@ func (m *V1RegisterOutputsForNextRoundRequest) Validate(formats strfmt.Registry) return nil } +func (m *V1RegisterOutputsForNextRoundRequest) validateMusig2(formats strfmt.Registry) error { + if swag.IsZero(m.Musig2) { // not required + return nil + } + + if m.Musig2 != nil { + if err := m.Musig2.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("musig2") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("musig2") + } + return err + } + } + + return nil +} + func (m *V1RegisterOutputsForNextRoundRequest) validateOutputs(formats strfmt.Registry) error { if swag.IsZero(m.Outputs) { // not required return nil @@ -70,6 +96,10 @@ func (m *V1RegisterOutputsForNextRoundRequest) validateOutputs(formats strfmt.Re func (m *V1RegisterOutputsForNextRoundRequest) ContextValidate(ctx context.Context, formats strfmt.Registry) error { var res []error + if err := m.contextValidateMusig2(ctx, formats); err != nil { + res = append(res, err) + } + if err := m.contextValidateOutputs(ctx, formats); err != nil { res = append(res, err) } @@ -80,6 +110,27 @@ func (m *V1RegisterOutputsForNextRoundRequest) ContextValidate(ctx context.Conte return nil } +func (m *V1RegisterOutputsForNextRoundRequest) contextValidateMusig2(ctx context.Context, formats strfmt.Registry) error { + + if m.Musig2 != nil { + + if swag.IsZero(m.Musig2) { // not required + return nil + } + + if err := m.Musig2.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("musig2") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("musig2") + } + return err + } + } + + return nil +} + func (m *V1RegisterOutputsForNextRoundRequest) contextValidateOutputs(ctx context.Context, formats strfmt.Registry) error { for i := 0; i < len(m.Outputs); i++ { diff --git a/pkg/client-sdk/covenant_client.go b/pkg/client-sdk/covenant_client.go index 8d24f00f4..c89b9a946 100644 --- a/pkg/client-sdk/covenant_client.go +++ b/pkg/client-sdk/covenant_client.go @@ -586,12 +586,12 @@ func (a *covenantArkClient) CollaborativeRedeem( }) } - requestID, err := a.client.RegisterInputsForNextRound(ctx, inputs, nil, 0) + requestID, err := a.client.RegisterInputsForNextRound(ctx, inputs) if err != nil { return "", err } - if err := a.client.RegisterOutputsForNextRound(ctx, requestID, receivers); err != nil { + if err := a.client.RegisterOutputsForNextRound(ctx, requestID, receivers, nil); err != nil { return "", err } @@ -1014,13 +1014,13 @@ func (a *covenantArkClient) sendOffchain( }) } - requestID, err := a.client.RegisterInputsForNextRound(ctx, inputs, nil, 0) + requestID, err := a.client.RegisterInputsForNextRound(ctx, inputs) if err != nil { return "", err } if err := a.client.RegisterOutputsForNextRound( - ctx, requestID, outputs, + ctx, requestID, outputs, nil, ); err != nil { return "", err } diff --git a/pkg/client-sdk/covenantless_client.go b/pkg/client-sdk/covenantless_client.go index 1bf0ef9af..3b93751c7 100644 --- a/pkg/client-sdk/covenantless_client.go +++ b/pkg/client-sdk/covenantless_client.go @@ -34,16 +34,16 @@ import ( log "github.com/sirupsen/logrus" ) -// SettleOptions are only available for covenantless clients +// Musig2SignOptions is only available for covenantless clients // it allows to customize the vtxo signing process -type SettleOptions struct { +type Musig2SignOptions struct { CustomSignerPrivKeys []*secp256k1.PrivateKey SigningType *tree.SigningType } // WithSignAll sets the signing type to ALL instead of the default BRANCH func WithSignAll(o interface{}) error { - opts, ok := o.(*SettleOptions) + opts, ok := o.(*Musig2SignOptions) if !ok { return fmt.Errorf("invalid options type") } @@ -56,7 +56,7 @@ func WithSignAll(o interface{}) error { // WithCustomTreeSigner allows to use a set of custom signer for the vtxo tree signing process func WithCustomTreeSigner(privKeys []*secp256k1.PrivateKey) Option { return func(o interface{}) error { - opts, ok := o.(*SettleOptions) + opts, ok := o.(*Musig2SignOptions) if !ok { return fmt.Errorf("invalid options type") } @@ -869,7 +869,7 @@ func (a *covenantlessArkClient) SendOffChain( func (a *covenantlessArkClient) RedeemNotes(ctx context.Context, notes []string, opts ...Option) (string, error) { amount := uint64(0) - options := &SettleOptions{} + options := &Musig2SignOptions{} for _, opt := range opts { if err := opt(options); err != nil { return "", err @@ -898,7 +898,7 @@ func (a *covenantlessArkClient) RedeemNotes(ctx context.Context, notes []string, } requestID, err := a.client.RegisterNotesForNextRound( - ctx, notes, signerPubKeys, signingType, + ctx, notes, ) if err != nil { return "", err @@ -913,6 +913,10 @@ func (a *covenantlessArkClient) RedeemNotes(ctx context.Context, notes []string, if err := a.client.RegisterOutputsForNextRound( ctx, requestID, receiversOutput, + &tree.Musig2{ + CosignersPublicKeys: signerPubKeys, + SigningType: tree.SigningType(signingType), + }, ); err != nil { return "", err } @@ -993,7 +997,7 @@ func (a *covenantlessArkClient) CollaborativeRedeem( addr string, amount uint64, withExpiryCoinselect bool, opts ...Option, ) (string, error) { - options := &SettleOptions{} + options := &Musig2SignOptions{} for _, opt := range opts { if err := opt(options); err != nil { return "", err @@ -1096,14 +1100,18 @@ func (a *covenantlessArkClient) CollaborativeRedeem( requestID, err := a.client.RegisterInputsForNextRound( ctx, inputs, - signerPubKeys, - signingType, ) if err != nil { return "", err } - if err := a.client.RegisterOutputsForNextRound(ctx, requestID, receivers); err != nil { + if err := a.client.RegisterOutputsForNextRound( + ctx, requestID, receivers, + &tree.Musig2{ + CosignersPublicKeys: signerPubKeys, + SigningType: tree.SigningType(signingType), + }, + ); err != nil { return "", err } @@ -1399,7 +1407,7 @@ func (a *covenantlessArkClient) sendOffchain( settleOpts ...Option, ) (string, error) { - options := &SettleOptions{} + options := &Musig2SignOptions{} for _, opt := range settleOpts { if err := opt(options); err != nil { return "", err @@ -1544,7 +1552,7 @@ func (a *covenantlessArkClient) sendOffchain( } requestID, err := a.client.RegisterInputsForNextRound( - ctx, inputs, signerPubKeys, signingType, + ctx, inputs, ) if err != nil { return "", err @@ -1552,6 +1560,10 @@ func (a *covenantlessArkClient) sendOffchain( if err := a.client.RegisterOutputsForNextRound( ctx, requestID, outputs, + &tree.Musig2{ + CosignersPublicKeys: signerPubKeys, + SigningType: tree.SigningType(signingType), + }, ); err != nil { return "", err } @@ -2772,7 +2784,7 @@ func buildRedeemTx( return bitcointree.BuildRedeemTx(ins, outs) } -func handleOptions(options *SettleOptions) ([]*secp256k1.PrivateKey, []string, tree.SigningType, error) { +func handleOptions(options *Musig2SignOptions) ([]*secp256k1.PrivateKey, []string, tree.SigningType, error) { signerPrivKeys := make([]*secp256k1.PrivateKey, 0) signerPubKeys := make([]string, 0) if len(options.CustomSignerPrivKeys) > 0 { diff --git a/server/internal/core/application/covenant.go b/server/internal/core/application/covenant.go index 7b8956d03..2e4cff7bd 100644 --- a/server/internal/core/application/covenant.go +++ b/server/internal/core/application/covenant.go @@ -188,11 +188,11 @@ func (s *covenantService) GetBoardingAddress(ctx context.Context, userPubkey *se return addr, scripts, nil } -func (s *covenantService) SpendNotes(_ context.Context, _ []note.Note, _ []string, _ domain.SigningType) (string, error) { +func (s *covenantService) SpendNotes(_ context.Context, _ []note.Note) (string, error) { return "", fmt.Errorf("unimplemented") } -func (s *covenantService) SpendVtxos(ctx context.Context, inputs []ports.Input, _ []string, _ domain.SigningType) (string, error) { +func (s *covenantService) SpendVtxos(ctx context.Context, inputs []ports.Input) (string, error) { vtxosInputs := make([]domain.Vtxo, 0) boardingInputs := make([]ports.BoardingInput, 0) @@ -343,7 +343,7 @@ func (s *covenantService) newBoardingInput(tx *transaction.Transaction, input po }, nil } -func (s *covenantService) ClaimVtxos(ctx context.Context, creds string, receivers []domain.Receiver) error { +func (s *covenantService) ClaimVtxos(ctx context.Context, creds string, receivers []domain.Receiver, _ *tree.Musig2) error { // Check credentials request, ok := s.txRequests.view(creds) if !ok { @@ -557,7 +557,7 @@ func (s *covenantService) startFinalization() { if num > txRequestsThreshold { num = txRequestsThreshold } - requests, boardingInputs, _ := s.txRequests.pop(num) + requests, boardingInputs, _, _ := s.txRequests.pop(num) if _, err := round.RegisterTxRequests(requests); err != nil { round.Fail(fmt.Errorf("failed to register tx requests: %s", err)) log.WithError(err).Warn("failed to register tx requests") @@ -571,7 +571,7 @@ func (s *covenantService) startFinalization() { return } - unsignedRoundTx, tree, connectorAddress, connectors, err := s.builder.BuildRoundTx(s.pubkey, requests, boardingInputs, sweptRounds) + unsignedRoundTx, tree, connectorAddress, connectors, err := s.builder.BuildRoundTx(s.pubkey, requests, boardingInputs, sweptRounds, nil) if err != nil { round.Fail(fmt.Errorf("failed to create round tx: %s", err)) log.WithError(err).Warn("failed to create round tx") diff --git a/server/internal/core/application/covenantless.go b/server/internal/core/application/covenantless.go index 14b17220a..e4c18d16c 100644 --- a/server/internal/core/application/covenantless.go +++ b/server/internal/core/application/covenantless.go @@ -506,7 +506,7 @@ func (s *covenantlessService) GetBoardingAddress( return } -func (s *covenantlessService) SpendNotes(ctx context.Context, notes []note.Note, signerPubkeys []string, signingType domain.SigningType) (string, error) { +func (s *covenantlessService) SpendNotes(ctx context.Context, notes []note.Note) (string, error) { notesRepo := s.repoManager.Notes() for _, note := range notes { @@ -538,12 +538,6 @@ func (s *covenantlessService) SpendNotes(ctx context.Context, notes []note.Note, return "", fmt.Errorf("failed to create tx request: %s", err) } - // add the server pubkey as a signer - signerPubkeys = append(signerPubkeys, hex.EncodeToString(s.serverSigningPubKey.SerializeCompressed())) - - request.AddSignerPubKeys(signerPubkeys) - request.AddSigningType(signingType) - if err := s.txRequests.pushWithNotes(*request, notes); err != nil { return "", fmt.Errorf("failed to push tx requests: %s", err) } @@ -551,7 +545,7 @@ func (s *covenantlessService) SpendNotes(ctx context.Context, notes []note.Note, return request.Id, nil } -func (s *covenantlessService) SpendVtxos(ctx context.Context, inputs []ports.Input, signerPubkeys []string, signingType domain.SigningType) (string, error) { +func (s *covenantlessService) SpendVtxos(ctx context.Context, inputs []ports.Input) (string, error) { vtxosInputs := make([]domain.Vtxo, 0) boardingInputs := make([]ports.BoardingInput, 0) @@ -652,15 +646,6 @@ func (s *covenantlessService) SpendVtxos(ctx context.Context, inputs []ports.Inp return "", err } - if len(signerPubkeys) <= 0 { - return "", fmt.Errorf("signer pubkeys are required") - } - - signerPubkeys = append(signerPubkeys, hex.EncodeToString(s.serverSigningPubKey.SerializeCompressed())) - - request.AddSignerPubKeys(signerPubkeys) - request.AddSigningType(signingType) - if err := s.txRequests.push(*request, boardingInputs); err != nil { return "", err } @@ -703,7 +688,7 @@ func (s *covenantlessService) newBoardingInput(tx wire.MsgTx, input ports.Input) }, nil } -func (s *covenantlessService) ClaimVtxos(ctx context.Context, creds string, receivers []domain.Receiver) error { +func (s *covenantlessService) ClaimVtxos(ctx context.Context, creds string, receivers []domain.Receiver, musig2Data *tree.Musig2) error { // Check credentials request, ok := s.txRequests.view(creds) if !ok { @@ -715,10 +700,34 @@ func (s *covenantlessService) ClaimVtxos(ctx context.Context, creds string, rece return fmt.Errorf("unable to verify receiver amount, failed to get dust: %s", err) } + hasOffChainReceiver := false + for _, rcv := range receivers { if rcv.Amount <= dustAmount { return fmt.Errorf("receiver amount must be greater than dust amount %d", dustAmount) } + + if !rcv.IsOnchain() { + hasOffChainReceiver = true + } + } + + if hasOffChainReceiver { + if musig2Data == nil { + return fmt.Errorf("musig2 data is required for offchain receivers") + } + + // check if the server pubkey has been set as cosigner + serverPubKeyHex := hex.EncodeToString(s.serverSigningPubKey.SerializeCompressed()) + for _, pubkey := range musig2Data.CosignersPublicKeys { + if pubkey == serverPubKeyHex { + return fmt.Errorf("server pubkey already in musig2 data") + } + } + + if err := s.txRequests.addMusig2Data(request.Id, musig2Data); err != nil { + return fmt.Errorf("failed to add musig2 data: %s", err) + } } if err := request.AddReceivers(receivers); err != nil { @@ -1048,7 +1057,7 @@ func (s *covenantlessService) startFinalization() { if num > txRequestsThreshold { num = txRequestsThreshold } - requests, boardingInputs, redeeemedNotes := s.txRequests.pop(num) + requests, boardingInputs, redeeemedNotes, musig2data := s.txRequests.pop(num) notes = redeeemedNotes if _, err := round.RegisterTxRequests(requests); err != nil { @@ -1064,9 +1073,19 @@ func (s *covenantlessService) startFinalization() { return } + // add server pubkey in musig2data and count the number of unique keys + uniqueSignerPubkeys := make(map[string]struct{}) + serverPubKeyHex := hex.EncodeToString(s.serverSigningPubKey.SerializeCompressed()) + for _, data := range musig2data { + for _, pubkey := range data.CosignersPublicKeys { + uniqueSignerPubkeys[pubkey] = struct{}{} + } + data.CosignersPublicKeys = append(data.CosignersPublicKeys, serverPubKeyHex) + } + log.Debugf("building round tx for round %s", round.Id) unsignedRoundTx, vtxoTree, connectorAddress, connectors, err := s.builder.BuildRoundTx( - s.pubkey, requests, boardingInputs, connectorAddresses, + s.pubkey, requests, boardingInputs, connectorAddresses, musig2data, ) if err != nil { round.Fail(fmt.Errorf("failed to create round tx: %s", err)) @@ -1078,15 +1097,7 @@ func (s *covenantlessService) startFinalization() { s.forfeitTxs.init(connectors, requests) if len(vtxoTree) > 0 { - - uniqueSignerPubkeys := make(map[string]struct{}) - for _, request := range requests { - for _, pubkey := range request.SignerPubKeys { - uniqueSignerPubkeys[pubkey] = struct{}{} - } - } - - nbOfCosigners := len(uniqueSignerPubkeys) + nbOfCosigners := len(uniqueSignerPubkeys) + 1 // +1 for the server signingSession := newMusigSigningSession(nbOfCosigners) s.treeSigningSessions[round.Id] = signingSession diff --git a/server/internal/core/application/types.go b/server/internal/core/application/types.go index a5750197b..511d26076 100644 --- a/server/internal/core/application/types.go +++ b/server/internal/core/application/types.go @@ -5,6 +5,7 @@ import ( "time" "github.com/ark-network/ark/common/note" + "github.com/ark-network/ark/common/tree" "github.com/ark-network/ark/server/internal/core/domain" "github.com/ark-network/ark/server/internal/core/ports" "github.com/decred/dcrd/dcrec/secp256k1/v4" @@ -17,9 +18,9 @@ var ( type Service interface { Start() error Stop() - SpendNotes(ctx context.Context, notes []note.Note, signerPubkeys []string, signingType domain.SigningType) (string, error) - SpendVtxos(ctx context.Context, inputs []ports.Input, signerPubkeys []string, signingType domain.SigningType) (string, error) - ClaimVtxos(ctx context.Context, creds string, receivers []domain.Receiver) error + SpendNotes(ctx context.Context, notes []note.Note) (string, error) + SpendVtxos(ctx context.Context, inputs []ports.Input) (string, error) + ClaimVtxos(ctx context.Context, creds string, receivers []domain.Receiver, musig2Data *tree.Musig2) error SignVtxos(ctx context.Context, forfeitTxs []string) error SignRoundTx(ctx context.Context, roundTx string) error GetRoundByTxid(ctx context.Context, roundTxid string) (*domain.Round, error) diff --git a/server/internal/core/application/utils.go b/server/internal/core/application/utils.go index 4fabd5322..e244e7a57 100644 --- a/server/internal/core/application/utils.go +++ b/server/internal/core/application/utils.go @@ -22,6 +22,7 @@ type timedTxRequest struct { notes []note.Note timestamp time.Time pingTimestamp time.Time + musig2Data *tree.Musig2 } type txRequestsQueue struct { @@ -66,7 +67,7 @@ func (m *txRequestsQueue) pushWithNotes(request domain.TxRequest, notes []note.N } } - m.requests[request.Id] = &timedTxRequest{request, make([]ports.BoardingInput, 0), notes, time.Now(), time.Time{}} + m.requests[request.Id] = &timedTxRequest{request, make([]ports.BoardingInput, 0), notes, time.Now(), time.Time{}, nil} return nil } @@ -101,11 +102,11 @@ func (m *txRequestsQueue) push( } } - m.requests[request.Id] = &timedTxRequest{request, boardingInputs, make([]note.Note, 0), time.Now(), time.Time{}} + m.requests[request.Id] = &timedTxRequest{request, boardingInputs, make([]note.Note, 0), time.Now(), time.Time{}, nil} return nil } -func (m *txRequestsQueue) pop(num int64) ([]domain.TxRequest, []ports.BoardingInput, []note.Note) { +func (m *txRequestsQueue) pop(num int64) ([]domain.TxRequest, []ports.BoardingInput, []note.Note, []*tree.Musig2) { m.lock.Lock() defer m.lock.Unlock() @@ -132,13 +133,15 @@ func (m *txRequestsQueue) pop(num int64) ([]domain.TxRequest, []ports.BoardingIn requests := make([]domain.TxRequest, 0, num) boardingInputs := make([]ports.BoardingInput, 0) notes := make([]note.Note, 0) + musig2Data := make([]*tree.Musig2, 0) for _, p := range requestsByTime[:num] { boardingInputs = append(boardingInputs, p.boardingInputs...) requests = append(requests, p.TxRequest) + musig2Data = append(musig2Data, p.musig2Data) notes = append(notes, p.notes...) delete(m.requests, p.Id) } - return requests, boardingInputs, notes + return requests, boardingInputs, notes, musig2Data } func (m *txRequestsQueue) update(request domain.TxRequest) error { @@ -179,6 +182,20 @@ func (m *txRequestsQueue) update(request domain.TxRequest) error { return nil } +func (m *txRequestsQueue) addMusig2Data(id string, data *tree.Musig2) error { + m.lock.Lock() + defer m.lock.Unlock() + + r, ok := m.requests[id] + if !ok { + return fmt.Errorf("tx request %s not found", id) + } + + r.musig2Data = data + m.requests[id] = r + return nil +} + func (m *txRequestsQueue) updatePingTimestamp(id string) error { m.lock.Lock() defer m.lock.Unlock() @@ -202,11 +219,9 @@ func (m *txRequestsQueue) view(id string) (*domain.TxRequest, bool) { } return &domain.TxRequest{ - Id: request.Id, - Inputs: request.Inputs, - Receivers: request.Receivers, - SignerPubKeys: request.SignerPubKeys, - SigningType: request.SigningType, + Id: request.Id, + Inputs: request.Inputs, + Receivers: request.Receivers, }, true } diff --git a/server/internal/core/domain/payment.go b/server/internal/core/domain/payment.go index 85653596e..f4c59b63d 100644 --- a/server/internal/core/domain/payment.go +++ b/server/internal/core/domain/payment.go @@ -19,11 +19,9 @@ const ( ) type TxRequest struct { - Id string - Inputs []Vtxo - Receivers []Receiver - SignerPubKeys []string // pubkeys signing the shared output - SigningType SigningType + Id string + Inputs []Vtxo + Receivers []Receiver } func NewTxRequest(inputs []Vtxo) (*TxRequest, error) { @@ -37,14 +35,6 @@ func NewTxRequest(inputs []Vtxo) (*TxRequest, error) { return request, nil } -func (r *TxRequest) AddSignerPubKeys(pubkeys []string) { - r.SignerPubKeys = append(r.SignerPubKeys, pubkeys...) -} - -func (r *TxRequest) AddSigningType(signingType SigningType) { - r.SigningType = signingType -} - func (r *TxRequest) AddReceivers(receivers []Receiver) (err error) { if r.Receivers == nil { r.Receivers = make([]Receiver, 0) diff --git a/server/internal/core/ports/tx_builder.go b/server/internal/core/ports/tx_builder.go index 6ce2d07ef..ae325e275 100644 --- a/server/internal/core/ports/tx_builder.go +++ b/server/internal/core/ports/tx_builder.go @@ -36,6 +36,7 @@ type TxBuilder interface { BuildRoundTx( serverPubkey *secp256k1.PublicKey, txRequests []domain.TxRequest, boardingInputs []BoardingInput, connectorAddresses []string, + musig2Data []*tree.Musig2, // only for covenantless ) ( roundTx string, vtxoTree tree.VtxoTree, diff --git a/server/internal/infrastructure/tx-builder/covenant/builder.go b/server/internal/infrastructure/tx-builder/covenant/builder.go index 64a4d4444..08b8487d8 100644 --- a/server/internal/infrastructure/tx-builder/covenant/builder.go +++ b/server/internal/infrastructure/tx-builder/covenant/builder.go @@ -366,6 +366,7 @@ func (b *txBuilder) BuildRoundTx( requests []domain.TxRequest, boardingInputs []ports.BoardingInput, connectorAddresses []string, + _ []*tree.Musig2, ) (roundTx string, vtxoTree tree.VtxoTree, nextConnectorAddress string, connectors []string, err error) { // The creation of the tree and the round tx are tightly coupled: // - building the tree requires knowing the shared outpoint (txid:vout) diff --git a/server/internal/infrastructure/tx-builder/covenant/builder_test.go b/server/internal/infrastructure/tx-builder/covenant/builder_test.go index 079d8c42f..4204a3a40 100644 --- a/server/internal/infrastructure/tx-builder/covenant/builder_test.go +++ b/server/internal/infrastructure/tx-builder/covenant/builder_test.go @@ -67,7 +67,7 @@ func TestBuildRoundTx(t *testing.T) { t.Run("valid", func(t *testing.T) { for _, f := range fixtures.Valid { roundTx, vtxoTree, connAddr, _, err := builder.BuildRoundTx( - pubkey, f.Requests, []ports.BoardingInput{}, []string{}, + pubkey, f.Requests, []ports.BoardingInput{}, []string{}, nil, ) require.NoError(t, err) require.NotEmpty(t, roundTx) @@ -88,7 +88,7 @@ func TestBuildRoundTx(t *testing.T) { t.Run("invalid", func(t *testing.T) { for _, f := range fixtures.Invalid { roundTx, vtxoTree, connAddr, _, err := builder.BuildRoundTx( - pubkey, f.Requests, []ports.BoardingInput{}, []string{}, + pubkey, f.Requests, []ports.BoardingInput{}, []string{}, nil, ) require.EqualError(t, err, f.ExpectedErr) require.Empty(t, roundTx) diff --git a/server/internal/infrastructure/tx-builder/covenantless/builder.go b/server/internal/infrastructure/tx-builder/covenantless/builder.go index cced2c7f7..5d8d9a722 100644 --- a/server/internal/infrastructure/tx-builder/covenantless/builder.go +++ b/server/internal/infrastructure/tx-builder/covenantless/builder.go @@ -554,17 +554,12 @@ func (b *txBuilder) BuildRoundTx( requests []domain.TxRequest, boardingInputs []ports.BoardingInput, connectorAddresses []string, + musig2Data []*tree.Musig2, ) (roundTx string, vtxoTree tree.VtxoTree, nextConnectorAddress string, connectors []string, err error) { var sharedOutputScript []byte var sharedOutputAmount int64 - for _, request := range requests { - if len(request.SignerPubKeys) == 0 { - return "", nil, "", nil, fmt.Errorf("missing signer pubkeys for request ID %s", request.Id) - } - } - - receivers, err := getOutputVtxosLeaves(requests) + receivers, err := getOutputVtxosLeaves(requests, musig2Data) if err != nil { return "", nil, "", nil, err } diff --git a/server/internal/infrastructure/tx-builder/covenantless/builder_test.go b/server/internal/infrastructure/tx-builder/covenantless/builder_test.go index c7bf0afd8..8b716b0ab 100644 --- a/server/internal/infrastructure/tx-builder/covenantless/builder_test.go +++ b/server/internal/infrastructure/tx-builder/covenantless/builder_test.go @@ -9,6 +9,7 @@ import ( "github.com/ark-network/ark/common" "github.com/ark-network/ark/common/bitcointree" + "github.com/ark-network/ark/common/tree" "github.com/ark-network/ark/server/internal/core/domain" "github.com/ark-network/ark/server/internal/core/ports" txbuilder "github.com/ark-network/ark/server/internal/infrastructure/tx-builder/covenantless" @@ -68,25 +69,22 @@ func TestBuildRoundTx(t *testing.T) { if len(fixtures.Valid) > 0 { t.Run("valid", func(t *testing.T) { for _, f := range fixtures.Valid { - requests := make([]domain.TxRequest, 0) + musig2Data := make([]*tree.Musig2, 0) - for _, request := range f.Requests { + for range f.Requests { randKey, err := secp256k1.GeneratePrivateKey() require.NoError(t, err) - requests = append(requests, domain.TxRequest{ - Id: request.Id, - SignerPubKeys: []string{ + musig2Data = append(musig2Data, &tree.Musig2{ + CosignersPublicKeys: []string{ hex.EncodeToString(randKey.PubKey().SerializeCompressed()), }, SigningType: 0, - Inputs: request.Inputs, - Receivers: request.Receivers, }) } roundTx, vtxoTree, connAddr, _, err := builder.BuildRoundTx( - pubkey, requests, []ports.BoardingInput{}, []string{}, + pubkey, f.Requests, []ports.BoardingInput{}, []string{}, musig2Data, ) require.NoError(t, err) require.NotEmpty(t, roundTx) @@ -106,22 +104,19 @@ func TestBuildRoundTx(t *testing.T) { if len(fixtures.Invalid) > 0 { t.Run("invalid", func(t *testing.T) { for _, f := range fixtures.Invalid { - requests := make([]domain.TxRequest, 0) + musig2Data := make([]*tree.Musig2, 0) - for _, request := range f.Requests { - requests = append(requests, domain.TxRequest{ - Id: request.Id, - SignerPubKeys: []string{ + for range f.Requests { + musig2Data = append(musig2Data, &tree.Musig2{ + CosignersPublicKeys: []string{ hex.EncodeToString(pubkey.SerializeCompressed()), }, SigningType: 0, - Inputs: request.Inputs, - Receivers: request.Receivers, }) } roundTx, vtxoTree, connAddr, _, err := builder.BuildRoundTx( - pubkey, requests, []ports.BoardingInput{}, []string{}, + pubkey, f.Requests, []ports.BoardingInput{}, []string{}, musig2Data, ) require.EqualError(t, err, f.ExpectedErr) require.Empty(t, roundTx) diff --git a/server/internal/infrastructure/tx-builder/covenantless/utils.go b/server/internal/infrastructure/tx-builder/covenantless/utils.go index 7741518aa..fe7af3bbe 100644 --- a/server/internal/infrastructure/tx-builder/covenantless/utils.go +++ b/server/internal/infrastructure/tx-builder/covenantless/utils.go @@ -1,6 +1,8 @@ package txbuilder import ( + "fmt" + "github.com/ark-network/ark/common/tree" "github.com/ark-network/ark/server/internal/core/domain" "github.com/btcsuite/btcd/btcec/v2/schnorr" @@ -40,16 +42,20 @@ func getOnchainOutputs( func getOutputVtxosLeaves( requests []domain.TxRequest, + musig2Data []*tree.Musig2, ) ([]tree.VtxoLeaf, error) { + if len(musig2Data) != len(requests) { + return nil, fmt.Errorf("musig2 data length %d does not match requests length %d", len(musig2Data), len(requests)) + } + leaves := make([]tree.VtxoLeaf, 0) - for _, request := range requests { + for i, request := range requests { for _, receiver := range request.Receivers { if !receiver.IsOnchain() { leaves = append(leaves, tree.VtxoLeaf{ - PubKey: receiver.PubKey, - Amount: receiver.Amount, - Type: tree.SigningType(request.SigningType), - SignersPublicKeys: request.SignerPubKeys, + PubKey: receiver.PubKey, + Amount: receiver.Amount, + Musig2Data: musig2Data[i], }) } } diff --git a/server/internal/interface/grpc/handlers/arkservice.go b/server/internal/interface/grpc/handlers/arkservice.go index 115f8a282..671a0b478 100644 --- a/server/internal/interface/grpc/handlers/arkservice.go +++ b/server/internal/interface/grpc/handlers/arkservice.go @@ -12,6 +12,7 @@ import ( arkv1 "github.com/ark-network/ark/api-spec/protobuf/gen/ark/v1" "github.com/ark-network/ark/common/bitcointree" "github.com/ark-network/ark/common/descriptor" + "github.com/ark-network/ark/common/tree" "github.com/ark-network/ark/server/internal/core/application" "github.com/ark-network/ark/server/internal/core/domain" "github.com/decred/dcrd/dcrec/secp256k1/v4" @@ -131,7 +132,7 @@ func (h *handler) RegisterInputsForNextRound( if err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } - requestID, err = h.svc.SpendVtxos(ctx, inputs, req.GetSignerPubkeys(), domain.SigningType(req.GetSigningType())) + requestID, err = h.svc.SpendVtxos(ctx, inputs) if err != nil { return nil, err } @@ -142,7 +143,7 @@ func (h *handler) RegisterInputsForNextRound( if err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } - requestID, err = h.svc.SpendNotes(ctx, notes, req.GetSignerPubkeys(), domain.SigningType(req.GetSigningType())) + requestID, err = h.svc.SpendNotes(ctx, notes) if err != nil { return nil, err } @@ -161,7 +162,16 @@ func (h *handler) RegisterOutputsForNextRound( return nil, status.Error(codes.InvalidArgument, err.Error()) } - if err := h.svc.ClaimVtxos(ctx, req.GetRequestId(), receivers); err != nil { + musig2Data := req.GetMusig2() + var musig2 *tree.Musig2 + if musig2Data != nil { + musig2 = &tree.Musig2{ + CosignersPublicKeys: musig2Data.GetCosignersPublicKeys(), + SigningType: tree.SigningType(musig2Data.GetSigningType()), + } + } + + if err := h.svc.ClaimVtxos(ctx, req.GetRequestId(), receivers, musig2); err != nil { return nil, err } From ab7f60dfd01b27b0de73ff90bb4341a0078a44e0 Mon Sep 17 00:00:00 2001 From: louisinger Date: Sat, 18 Jan 2025 08:32:33 +0100 Subject: [PATCH 09/21] RoundSigningEvent: add cosigners public key list involved in the tree --- .../swagger/ark/v1/service.swagger.json | 6 + api-spec/protobuf/ark/v1/service.proto | 5 +- api-spec/protobuf/gen/ark/v1/service.pb.go | 615 +++++++++--------- pkg/client-sdk/client/client.go | 7 +- pkg/client-sdk/client/grpc/types.go | 7 +- pkg/client-sdk/client/rest/client.go | 7 +- .../service/models/v1_round_signing_event.go | 3 + .../internal/core/application/covenantless.go | 10 +- .../core/application/covenantless_event.go | 1 + .../interface/grpc/handlers/arkservice.go | 1 + 10 files changed, 347 insertions(+), 315 deletions(-) diff --git a/api-spec/openapi/swagger/ark/v1/service.swagger.json b/api-spec/openapi/swagger/ark/v1/service.swagger.json index 820e1a412..81ab8b6b7 100644 --- a/api-spec/openapi/swagger/ark/v1/service.swagger.json +++ b/api-spec/openapi/swagger/ark/v1/service.swagger.json @@ -950,6 +950,12 @@ "id": { "type": "string" }, + "cosignersPubkeys": { + "type": "array", + "items": { + "type": "string" + } + }, "unsignedVtxoTree": { "$ref": "#/definitions/v1Tree" }, diff --git a/api-spec/protobuf/ark/v1/service.proto b/api-spec/protobuf/ark/v1/service.proto index ca34034d5..7abca09d1 100755 --- a/api-spec/protobuf/ark/v1/service.proto +++ b/api-spec/protobuf/ark/v1/service.proto @@ -246,8 +246,9 @@ message RoundFailed { message RoundSigningEvent { string id = 1; - Tree unsigned_vtxo_tree = 2; - string unsigned_round_tx = 3; + repeated string cosigners_pubkeys = 2; + Tree unsigned_vtxo_tree = 3; + string unsigned_round_tx = 4; } message RoundSigningNoncesGeneratedEvent { diff --git a/api-spec/protobuf/gen/ark/v1/service.pb.go b/api-spec/protobuf/gen/ark/v1/service.pb.go index 54502f337..9d12a9d79 100644 --- a/api-spec/protobuf/gen/ark/v1/service.pb.go +++ b/api-spec/protobuf/gen/ark/v1/service.pb.go @@ -1697,9 +1697,10 @@ type RoundSigningEvent struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - UnsignedVtxoTree *Tree `protobuf:"bytes,2,opt,name=unsigned_vtxo_tree,json=unsignedVtxoTree,proto3" json:"unsigned_vtxo_tree,omitempty"` - UnsignedRoundTx string `protobuf:"bytes,3,opt,name=unsigned_round_tx,json=unsignedRoundTx,proto3" json:"unsigned_round_tx,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + CosignersPubkeys []string `protobuf:"bytes,2,rep,name=cosigners_pubkeys,json=cosignersPubkeys,proto3" json:"cosigners_pubkeys,omitempty"` + UnsignedVtxoTree *Tree `protobuf:"bytes,3,opt,name=unsigned_vtxo_tree,json=unsignedVtxoTree,proto3" json:"unsigned_vtxo_tree,omitempty"` + UnsignedRoundTx string `protobuf:"bytes,4,opt,name=unsigned_round_tx,json=unsignedRoundTx,proto3" json:"unsigned_round_tx,omitempty"` } func (x *RoundSigningEvent) Reset() { @@ -1741,6 +1742,13 @@ func (x *RoundSigningEvent) GetId() string { return "" } +func (x *RoundSigningEvent) GetCosignersPubkeys() []string { + if x != nil { + return x.CosignersPubkeys + } + return nil +} + func (x *RoundSigningEvent) GetUnsignedVtxoTree() *Tree { if x != nil { return x.UnsignedVtxoTree @@ -3307,312 +3315,315 @@ var file_ark_v1_service_proto_rawDesc = []byte{ 0x64, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, - 0x8b, 0x01, 0x0a, 0x11, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, + 0xb8, 0x01, 0x0a, 0x11, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x3a, 0x0a, 0x12, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, - 0x64, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x52, - 0x10, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, 0x54, 0x72, 0x65, - 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x6f, - 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x75, 0x6e, - 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x22, 0x53, 0x0a, - 0x20, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4e, 0x6f, 0x6e, - 0x63, 0x65, 0x73, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, - 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, - 0x65, 0x73, 0x22, 0xf0, 0x01, 0x0a, 0x05, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x0e, 0x0a, 0x02, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, - 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x74, 0x61, - 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x03, 0x65, 0x6e, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x12, - 0x29, 0x0a, 0x09, 0x76, 0x74, 0x78, 0x6f, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, - 0x52, 0x08, 0x76, 0x74, 0x78, 0x6f, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x6f, - 0x72, 0x66, 0x65, 0x69, 0x74, 0x5f, 0x74, 0x78, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x0a, 0x66, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x28, 0x0a, 0x05, 0x73, - 0x74, 0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x61, 0x72, 0x6b, - 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x05, - 0x73, 0x74, 0x61, 0x67, 0x65, 0x22, 0x32, 0x0a, 0x08, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x76, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x04, 0x76, 0x6f, 0x75, 0x74, 0x22, 0x9d, 0x01, 0x0a, 0x05, 0x49, 0x6e, - 0x70, 0x75, 0x74, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, - 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x12, 0x20, 0x0a, 0x0a, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x6f, 0x72, 0x12, 0x34, 0x0a, 0x0a, 0x74, 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x54, 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x48, 0x00, 0x52, 0x0a, 0x74, - 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x42, 0x0e, 0x0a, 0x0c, 0x74, 0x61, 0x70, - 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x22, 0x5f, 0x0a, 0x06, 0x4d, 0x75, 0x73, - 0x69, 0x67, 0x32, 0x12, 0x32, 0x0a, 0x15, 0x63, 0x6f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, - 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x13, 0x63, 0x6f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x50, 0x75, 0x62, - 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x69, 0x67, 0x6e, 0x69, - 0x6e, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x73, - 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x0a, 0x06, 0x4f, 0x75, - 0x74, 0x70, 0x75, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, - 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, - 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x31, 0x0a, 0x04, 0x54, 0x72, 0x65, 0x65, 0x12, 0x29, - 0x0a, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, - 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x65, 0x76, 0x65, - 0x6c, 0x52, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x22, 0x2f, 0x0a, 0x09, 0x54, 0x72, 0x65, - 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x22, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4e, - 0x6f, 0x64, 0x65, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x4b, 0x0a, 0x04, 0x4e, 0x6f, - 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x78, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x74, 0x78, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, - 0x5f, 0x74, 0x78, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x72, - 0x65, 0x6e, 0x74, 0x54, 0x78, 0x69, 0x64, 0x22, 0xc2, 0x02, 0x0a, 0x04, 0x56, 0x74, 0x78, 0x6f, + 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x63, 0x6f, 0x73, 0x69, 0x67, 0x6e, 0x65, + 0x72, 0x73, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x10, 0x63, 0x6f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x50, 0x75, 0x62, 0x6b, 0x65, + 0x79, 0x73, 0x12, 0x3a, 0x0a, 0x12, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x76, + 0x74, 0x78, 0x6f, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, + 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x52, 0x10, 0x75, 0x6e, + 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, 0x54, 0x72, 0x65, 0x65, 0x12, 0x2a, + 0x0a, 0x11, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, + 0x5f, 0x74, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x75, 0x6e, 0x73, 0x69, 0x67, + 0x6e, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x22, 0x53, 0x0a, 0x20, 0x52, 0x6f, + 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, + 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1f, + 0x0a, 0x0b, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x22, + 0xf0, 0x01, 0x0a, 0x05, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, + 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x65, 0x6e, + 0x64, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x12, 0x29, 0x0a, 0x09, + 0x76, 0x74, 0x78, 0x6f, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x52, 0x08, 0x76, + 0x74, 0x78, 0x6f, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x6f, 0x72, 0x66, 0x65, + 0x69, 0x74, 0x5f, 0x74, 0x78, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x6f, + 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x28, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, + 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, + 0x67, 0x65, 0x22, 0x32, 0x0a, 0x08, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x12, + 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, + 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x76, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x04, 0x76, 0x6f, 0x75, 0x74, 0x22, 0x9d, 0x01, 0x0a, 0x05, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x14, - 0x0a, 0x05, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x73, - 0x70, 0x65, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, - 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, - 0x78, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x12, 0x1b, - 0x0a, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x08, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, - 0x77, 0x65, 0x70, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x73, 0x77, 0x65, 0x70, - 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, - 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x5f, 0x74, 0x78, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x12, 0x16, 0x0a, - 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, - 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, - 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x1d, 0x0a, - 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x1e, 0x0a, 0x1c, - 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x8c, 0x01, 0x0a, - 0x1d, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, - 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, - 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, - 0x12, 0x33, 0x0a, 0x06, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x19, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x06, 0x72, - 0x65, 0x64, 0x65, 0x65, 0x6d, 0x42, 0x04, 0x0a, 0x02, 0x74, 0x78, 0x22, 0xd8, 0x01, 0x0a, 0x10, - 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x74, 0x78, 0x69, 0x64, 0x12, 0x31, 0x0a, 0x0b, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x74, - 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, - 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x73, 0x70, 0x65, - 0x6e, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x35, 0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, 0x64, - 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x0e, - 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x46, - 0x0a, 0x16, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x5f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, - 0x6e, 0x67, 0x5f, 0x75, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, - 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x52, 0x14, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, - 0x67, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x91, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x64, 0x65, 0x65, - 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, - 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, - 0x12, 0x31, 0x0a, 0x0b, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, - 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x56, 0x74, - 0x78, 0x6f, 0x73, 0x12, 0x35, 0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, - 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, - 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x0e, 0x73, 0x70, 0x65, 0x6e, - 0x64, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x6b, 0x0a, 0x0e, 0x4f, 0x77, - 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x23, 0x0a, 0x0d, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x70, 0x0a, 0x12, 0x53, 0x69, 0x67, 0x6e, 0x65, - 0x64, 0x56, 0x74, 0x78, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2c, 0x0a, + 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x20, + 0x0a, 0x0a, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, + 0x12, 0x34, 0x0a, 0x0a, 0x74, 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, + 0x70, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x48, 0x00, 0x52, 0x0a, 0x74, 0x61, 0x70, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x42, 0x0e, 0x0a, 0x0c, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, + 0x74, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x22, 0x5f, 0x0a, 0x06, 0x4d, 0x75, 0x73, 0x69, 0x67, 0x32, + 0x12, 0x32, 0x0a, 0x15, 0x63, 0x6f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x5f, 0x70, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x13, 0x63, 0x6f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, + 0x4b, 0x65, 0x79, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x73, 0x69, 0x67, 0x6e, + 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x0a, 0x06, 0x4f, 0x75, 0x74, 0x70, 0x75, + 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x61, + 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, + 0x75, 0x6e, 0x74, 0x22, 0x31, 0x0a, 0x04, 0x54, 0x72, 0x65, 0x65, 0x12, 0x29, 0x0a, 0x06, 0x6c, + 0x65, 0x76, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x72, + 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x06, + 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x22, 0x2f, 0x0a, 0x09, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x65, + 0x76, 0x65, 0x6c, 0x12, 0x22, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, + 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x4b, 0x0a, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, + 0x78, 0x69, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x74, 0x78, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x78, + 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x54, 0x78, 0x69, 0x64, 0x22, 0xc2, 0x02, 0x0a, 0x04, 0x56, 0x74, 0x78, 0x6f, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x05, 0x70, - 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x72, 0x6b, - 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x72, 0x6f, - 0x6f, 0x66, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x75, 0x0a, 0x18, 0x53, 0x65, 0x74, - 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x5f, 0x72, - 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, - 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x30, - 0x0a, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, - 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, - 0x22, 0x1b, 0x0a, 0x19, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, - 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4f, 0x0a, - 0x1b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, - 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x05, - 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x72, - 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, 0x4f, - 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x1e, - 0x0a, 0x1c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, - 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, - 0x0a, 0x0a, 0x54, 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x12, 0x18, 0x0a, 0x07, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x22, 0x85, 0x02, 0x0a, 0x0a, 0x4d, 0x61, 0x72, 0x6b, 0x65, - 0x74, 0x48, 0x6f, 0x75, 0x72, 0x12, 0x42, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x74, - 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, - 0x53, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0d, 0x6e, 0x65, 0x78, - 0x74, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x6e, 0x65, - 0x78, 0x74, 0x45, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x31, 0x0a, 0x06, 0x70, 0x65, 0x72, - 0x69, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x12, 0x40, 0x0a, 0x0e, - 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x0d, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x2a, 0x98, - 0x01, 0x0a, 0x0a, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, - 0x17, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x55, 0x4e, 0x53, - 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, - 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, - 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, 0x55, 0x4e, - 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x49, 0x5a, 0x41, - 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, - 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x49, 0x5a, 0x45, 0x44, 0x10, - 0x03, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, - 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x04, 0x32, 0xf0, 0x0e, 0x0a, 0x0a, 0x41, 0x72, - 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, - 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, - 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x61, 0x72, - 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, - 0x31, 0x2f, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x74, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, - 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x21, 0x2e, 0x61, + 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, + 0x70, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x73, 0x70, 0x65, 0x6e, + 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x69, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x69, 0x64, + 0x12, 0x19, 0x0a, 0x08, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x65, + 0x78, 0x70, 0x69, 0x72, 0x65, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, + 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x77, 0x65, 0x70, + 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x73, 0x77, 0x65, 0x70, 0x74, 0x12, 0x1d, + 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x1b, 0x0a, + 0x09, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x5f, 0x74, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, + 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, + 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x1e, 0x0a, 0x1c, 0x47, 0x65, 0x74, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x8c, 0x01, 0x0a, 0x1d, 0x47, 0x65, + 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x72, + 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x61, 0x72, 0x6b, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x33, 0x0a, + 0x06, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x64, 0x65, + 0x65, 0x6d, 0x42, 0x04, 0x0a, 0x02, 0x74, 0x78, 0x22, 0xd8, 0x01, 0x0a, 0x10, 0x52, 0x6f, 0x75, + 0x6e, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, + 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, + 0x64, 0x12, 0x31, 0x0a, 0x0b, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, + 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x56, + 0x74, 0x78, 0x6f, 0x73, 0x12, 0x35, 0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, + 0x65, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, + 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x0e, 0x73, 0x70, 0x65, + 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x46, 0x0a, 0x16, 0x63, + 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x5f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x5f, + 0x75, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, + 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x14, 0x63, + 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x55, 0x74, + 0x78, 0x6f, 0x73, 0x22, 0x91, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x31, 0x0a, + 0x0b, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, + 0x12, 0x35, 0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x74, + 0x78, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, + 0x76, 0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x0e, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, + 0x6c, 0x65, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x6b, 0x0a, 0x0e, 0x4f, 0x77, 0x6e, 0x65, 0x72, + 0x73, 0x68, 0x69, 0x70, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x16, + 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x22, 0x70, 0x0a, 0x12, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, + 0x78, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x75, + 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, + 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, + 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x6f, + 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, + 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x75, 0x0a, 0x18, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, + 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x5f, 0x72, 0x65, 0x63, 0x69, + 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6e, 0x6f, 0x73, + 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x05, 0x76, + 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x72, 0x6b, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, 0x4f, 0x75, + 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x1b, 0x0a, + 0x19, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4f, 0x0a, 0x1b, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x74, 0x78, + 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, 0x4f, 0x75, 0x74, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x1e, 0x0a, 0x1c, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, + 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x0a, 0x0a, 0x54, + 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x73, 0x22, 0x85, 0x02, 0x0a, 0x0a, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x48, 0x6f, + 0x75, 0x72, 0x12, 0x42, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x53, 0x74, 0x61, + 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x65, + 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x6e, 0x65, 0x78, 0x74, 0x45, + 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x31, 0x0a, 0x06, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x06, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x12, 0x40, 0x0a, 0x0e, 0x72, 0x6f, 0x75, + 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x72, 0x6f, + 0x75, 0x6e, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x2a, 0x98, 0x01, 0x0a, 0x0a, + 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x4f, + 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, + 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, 0x55, 0x4e, 0x44, + 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x52, 0x41, 0x54, + 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, + 0x54, 0x41, 0x47, 0x45, 0x5f, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, + 0x4e, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, + 0x47, 0x45, 0x5f, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x49, 0x5a, 0x45, 0x44, 0x10, 0x03, 0x12, 0x16, + 0x0a, 0x12, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x46, 0x41, + 0x49, 0x4c, 0x45, 0x44, 0x10, 0x04, 0x32, 0xf0, 0x0e, 0x0a, 0x0a, 0x41, 0x72, 0x6b, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, + 0x12, 0x16, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, + 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x69, + 0x6e, 0x66, 0x6f, 0x12, 0x74, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, + 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x21, 0x2e, 0x61, 0x72, 0x6b, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, - 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x22, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, - 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x3a, 0x01, 0x2a, 0x22, 0x0c, - 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x98, 0x01, 0x0a, - 0x1a, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, - 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x29, 0x2e, 0x61, 0x72, - 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, - 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, - 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, - 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x3a, 0x01, 0x2a, 0x22, 0x18, 0x2f, - 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, - 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x9c, 0x01, 0x0a, 0x1b, 0x52, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, - 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, + 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x3a, 0x01, 0x2a, 0x22, 0x0c, 0x2f, 0x76, 0x31, + 0x2f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x98, 0x01, 0x0a, 0x1a, 0x52, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, + 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x29, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, - 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x3a, 0x01, 0x2a, 0x22, 0x19, 0x2f, 0x76, 0x31, - 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x12, 0x7d, 0x0a, 0x10, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, - 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x61, 0x72, 0x6b, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, - 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x61, 0x72, - 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, - 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, 0x2a, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, - 0x75, 0x6e, 0x64, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4e, - 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x8d, 0x01, 0x0a, 0x14, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, - 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x23, - 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, - 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, - 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x24, 0x3a, 0x01, 0x2a, 0x22, 0x1f, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, - 0x74, 0x72, 0x65, 0x65, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x8e, 0x01, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, - 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, - 0x12, 0x25, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, - 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, - 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x3a, 0x01, 0x2a, 0x22, 0x1a, 0x2f, 0x76, 0x31, 0x2f, - 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x66, - 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x65, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x12, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0c, 0x12, - 0x0a, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x30, 0x01, 0x12, 0x56, 0x0a, - 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x13, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x50, - 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x72, 0x6b, - 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, - 0x75, 0x6e, 0x64, 0x2f, 0x70, 0x69, 0x6e, 0x67, 0x2f, 0x7b, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x69, 0x0a, 0x0e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, - 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x12, 0x1d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, - 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x3a, 0x01, - 0x2a, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x2d, 0x74, 0x78, - 0x12, 0x57, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x17, 0x2e, 0x61, - 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, - 0x6e, 0x64, 0x2f, 0x7b, 0x74, 0x78, 0x69, 0x64, 0x7d, 0x12, 0x64, 0x0a, 0x0c, 0x47, 0x65, 0x74, - 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x12, 0x1b, 0x2e, 0x61, 0x72, 0x6b, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, - 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, - 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x69, 0x64, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, - 0x5d, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x18, 0x2e, 0x61, - 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x76, - 0x74, 0x78, 0x6f, 0x73, 0x2f, 0x7b, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x7d, 0x12, 0x80, - 0x01, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, - 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, - 0x76, 0x31, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x30, - 0x01, 0x12, 0x73, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, - 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x20, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, - 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, - 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x22, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78, 0x6f, - 0x2f, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x12, 0x83, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, - 0x23, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, - 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x1a, 0x3a, 0x01, 0x2a, 0x22, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78, 0x6f, 0x2f, - 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x2f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x92, 0x01, 0x0a, - 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3d, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x6b, 0x2d, 0x6e, 0x65, 0x74, 0x77, - 0x6f, 0x72, 0x6b, 0x2f, 0x61, 0x72, 0x6b, 0x2f, 0x61, 0x70, 0x69, 0x2d, 0x73, 0x70, 0x65, 0x63, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x61, 0x72, - 0x6b, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x72, 0x6b, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x41, 0x58, 0x58, - 0xaa, 0x02, 0x06, 0x41, 0x72, 0x6b, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x06, 0x41, 0x72, 0x6b, 0x5c, - 0x56, 0x31, 0xe2, 0x02, 0x12, 0x41, 0x72, 0x6b, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x07, 0x41, 0x72, 0x6b, 0x3a, 0x3a, 0x56, - 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, + 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x3a, 0x01, 0x2a, 0x22, 0x18, 0x2f, 0x76, 0x31, 0x2f, + 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, + 0x70, 0x75, 0x74, 0x73, 0x12, 0x9c, 0x01, 0x0a, 0x1b, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, + 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, + 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, + 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2b, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, + 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x3a, 0x01, 0x2a, 0x22, 0x19, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, + 0x75, 0x6e, 0x64, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, + 0x75, 0x74, 0x73, 0x12, 0x7d, 0x0a, 0x10, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, + 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x20, 0x3a, 0x01, 0x2a, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, + 0x2f, 0x74, 0x72, 0x65, 0x65, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4e, 0x6f, 0x6e, 0x63, + 0x65, 0x73, 0x12, 0x8d, 0x01, 0x0a, 0x14, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, + 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x23, 0x2e, 0x61, 0x72, + 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, + 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x3a, 0x01, + 0x2a, 0x22, 0x1f, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x74, 0x72, 0x65, + 0x65, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x73, 0x12, 0x8e, 0x01, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, + 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x25, 0x2e, + 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, + 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, + 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, + 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x1f, 0x3a, 0x01, 0x2a, 0x22, 0x1a, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, + 0x6e, 0x64, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, + 0x54, 0x78, 0x73, 0x12, 0x65, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, + 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x12, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0c, 0x12, 0x0a, 0x2f, 0x76, + 0x31, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x30, 0x01, 0x12, 0x56, 0x0a, 0x04, 0x50, 0x69, + 0x6e, 0x67, 0x12, 0x13, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, + 0x2f, 0x70, 0x69, 0x6e, 0x67, 0x2f, 0x7b, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, + 0x64, 0x7d, 0x12, 0x69, 0x0a, 0x0e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, + 0x65, 0x6d, 0x54, 0x78, 0x12, 0x1d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, + 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, + 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x3a, 0x01, 0x2a, 0x22, 0x0d, + 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x2d, 0x74, 0x78, 0x12, 0x57, 0x0a, + 0x08, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x17, 0x2e, 0x61, 0x72, 0x6b, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, + 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, + 0x7b, 0x74, 0x78, 0x69, 0x64, 0x7d, 0x12, 0x64, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, + 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x12, 0x1b, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, + 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x72, + 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x69, 0x64, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x5d, 0x0a, 0x09, + 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x18, 0x2e, 0x61, 0x72, 0x6b, 0x2e, + 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78, 0x6f, + 0x73, 0x2f, 0x7b, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x7d, 0x12, 0x80, 0x01, 0x0a, 0x15, + 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x61, 0x72, + 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x30, 0x01, 0x12, 0x73, + 0x0a, 0x11, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, + 0x65, 0x6e, 0x74, 0x12, 0x20, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, + 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, + 0x3a, 0x01, 0x2a, 0x22, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78, 0x6f, 0x2f, 0x6e, 0x6f, + 0x73, 0x74, 0x72, 0x12, 0x83, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, + 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x2e, 0x61, + 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, + 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x3a, + 0x01, 0x2a, 0x22, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78, 0x6f, 0x2f, 0x6e, 0x6f, 0x73, + 0x74, 0x72, 0x2f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x92, 0x01, 0x0a, 0x0a, 0x63, 0x6f, + 0x6d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x6b, 0x2d, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, + 0x2f, 0x61, 0x72, 0x6b, 0x2f, 0x61, 0x70, 0x69, 0x2d, 0x73, 0x70, 0x65, 0x63, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x61, 0x72, 0x6b, 0x2f, 0x76, + 0x31, 0x3b, 0x61, 0x72, 0x6b, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x41, 0x58, 0x58, 0xaa, 0x02, 0x06, + 0x41, 0x72, 0x6b, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x06, 0x41, 0x72, 0x6b, 0x5c, 0x56, 0x31, 0xe2, + 0x02, 0x12, 0x41, 0x72, 0x6b, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x07, 0x41, 0x72, 0x6b, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/client-sdk/client/client.go b/pkg/client-sdk/client/client.go index 41c9a5d41..d7e6b7aad 100644 --- a/pkg/client-sdk/client/client.go +++ b/pkg/client-sdk/client/client.go @@ -191,9 +191,10 @@ type RoundFailedEvent struct { func (e RoundFailedEvent) isRoundEvent() {} type RoundSigningStartedEvent struct { - ID string - UnsignedTree tree.VtxoTree - UnsignedRoundTx string + ID string + UnsignedTree tree.VtxoTree + UnsignedRoundTx string + CosignersPubkeys []string } func (e RoundSigningStartedEvent) isRoundEvent() {} diff --git a/pkg/client-sdk/client/grpc/types.go b/pkg/client-sdk/client/grpc/types.go index ab4d6a6e8..cdb8315bc 100644 --- a/pkg/client-sdk/client/grpc/types.go +++ b/pkg/client-sdk/client/grpc/types.go @@ -72,9 +72,10 @@ func (e event) toRoundEvent() (client.RoundEvent, error) { if ee := e.GetRoundSigning(); ee != nil { return client.RoundSigningStartedEvent{ - ID: ee.GetId(), - UnsignedTree: treeFromProto{ee.GetUnsignedVtxoTree()}.parse(), - UnsignedRoundTx: ee.GetUnsignedRoundTx(), + ID: ee.GetId(), + UnsignedTree: treeFromProto{ee.GetUnsignedVtxoTree()}.parse(), + UnsignedRoundTx: ee.GetUnsignedRoundTx(), + CosignersPubkeys: ee.GetCosignersPubkeys(), }, nil } diff --git a/pkg/client-sdk/client/rest/client.go b/pkg/client-sdk/client/rest/client.go index a18a34be4..47f4e7960 100644 --- a/pkg/client-sdk/client/rest/client.go +++ b/pkg/client-sdk/client/rest/client.go @@ -336,9 +336,10 @@ func (c *restClient) GetEventStream( case resp.Result.RoundSigning != nil: e := resp.Result.RoundSigning event = client.RoundSigningStartedEvent{ - ID: e.ID, - UnsignedTree: treeFromProto{e.UnsignedVtxoTree}.parse(), - UnsignedRoundTx: e.UnsignedRoundTx, + ID: e.ID, + UnsignedTree: treeFromProto{e.UnsignedVtxoTree}.parse(), + UnsignedRoundTx: e.UnsignedRoundTx, + CosignersPubkeys: e.CosignersPubkeys, } case resp.Result.RoundSigningNoncesGenerated != nil: e := resp.Result.RoundSigningNoncesGenerated diff --git a/pkg/client-sdk/client/rest/service/models/v1_round_signing_event.go b/pkg/client-sdk/client/rest/service/models/v1_round_signing_event.go index cde59f8aa..3fb052fae 100644 --- a/pkg/client-sdk/client/rest/service/models/v1_round_signing_event.go +++ b/pkg/client-sdk/client/rest/service/models/v1_round_signing_event.go @@ -18,6 +18,9 @@ import ( // swagger:model v1RoundSigningEvent type V1RoundSigningEvent struct { + // cosigners pubkeys + CosignersPubkeys []string `json:"cosignersPubkeys"` + // id ID string `json:"id,omitempty"` diff --git a/server/internal/core/application/covenantless.go b/server/internal/core/application/covenantless.go index d1b9786d8..94d48fdbf 100644 --- a/server/internal/core/application/covenantless.go +++ b/server/internal/core/application/covenantless.go @@ -1106,7 +1106,12 @@ func (s *covenantlessService) startFinalization() { s.currentRound.UnsignedTx = unsignedRoundTx // send back the unsigned tree & all cosigners pubkeys - s.propagateRoundSigningStartedEvent(vtxoTree) + listOfCosignersPubkeys := make([]string, 0, len(uniqueSignerPubkeys)) + for pubkey := range uniqueSignerPubkeys { + listOfCosignersPubkeys = append(listOfCosignersPubkeys, pubkey) + } + + s.propagateRoundSigningStartedEvent(vtxoTree, listOfCosignersPubkeys) sweepClosure := tree.CSVMultisigClosure{ MultisigClosure: tree.MultisigClosure{PubKeys: []*secp256k1.PublicKey{s.pubkey}}, @@ -1238,11 +1243,12 @@ func (s *covenantlessService) startFinalization() { log.Debugf("started finalization stage for round: %s", round.Id) } -func (s *covenantlessService) propagateRoundSigningStartedEvent(unsignedVtxoTree tree.VtxoTree) { +func (s *covenantlessService) propagateRoundSigningStartedEvent(unsignedVtxoTree tree.VtxoTree, cosignersPubkeys []string) { ev := RoundSigningStarted{ Id: s.currentRound.Id, UnsignedVtxoTree: unsignedVtxoTree, UnsignedRoundTx: s.currentRound.UnsignedTx, + CosignersPubkeys: cosignersPubkeys, } s.eventsCh <- ev diff --git a/server/internal/core/application/covenantless_event.go b/server/internal/core/application/covenantless_event.go index 76a18ed01..ee02bc757 100644 --- a/server/internal/core/application/covenantless_event.go +++ b/server/internal/core/application/covenantless_event.go @@ -18,6 +18,7 @@ type RoundSigningStarted struct { Id string UnsignedVtxoTree tree.VtxoTree UnsignedRoundTx string + CosignersPubkeys []string } // signer should react to this event by partially signing the vtxo tree transactions diff --git a/server/internal/interface/grpc/handlers/arkservice.go b/server/internal/interface/grpc/handlers/arkservice.go index 671a0b478..980190ed7 100644 --- a/server/internal/interface/grpc/handlers/arkservice.go +++ b/server/internal/interface/grpc/handlers/arkservice.go @@ -528,6 +528,7 @@ func (h *handler) listenToEvents() { Id: e.Id, UnsignedVtxoTree: vtxoTree(e.UnsignedVtxoTree).toProto(), UnsignedRoundTx: e.UnsignedRoundTx, + CosignersPubkeys: e.CosignersPubkeys, }, }, } From 244496afe1295566fdee817ba63061b1c6d33eb4 Mon Sep 17 00:00:00 2001 From: louisinger Date: Sun, 19 Jan 2025 00:01:50 +0100 Subject: [PATCH 10/21] rework client vtxo tree signer session --- client/main.go | 11 +- common/bitcointree/musig2.go | 42 ++-- common/bitcointree/musig2_test.go | 8 +- pkg/client-sdk/covenantless_client.go | 211 +++++++++++++----- .../wallet/singlekey/bitcoin_wallet.go | 49 ++++ .../wallet/singlekey/liquid_wallet.go | 5 + pkg/client-sdk/wallet/wallet.go | 2 + .../internal/core/application/covenantless.go | 6 +- server/test/e2e/covenantless/e2e_test.go | 6 +- 9 files changed, 247 insertions(+), 93 deletions(-) diff --git a/client/main.go b/client/main.go index ecd3dd84f..1e6a0166b 100644 --- a/client/main.go +++ b/client/main.go @@ -213,7 +213,7 @@ var ( notesCommand = cli.Command{ Name: "redeem-notes", Usage: "Redeem offchain notes", - Flags: []cli.Flag{notesFlag}, + Flags: []cli.Flag{notesFlag, passwordFlag}, Action: func(ctx *cli.Context) error { return redeemNotes(ctx) }, @@ -428,6 +428,15 @@ func registerNostrProfile(ctx *cli.Context) error { func redeemNotes(ctx *cli.Context) error { notes := ctx.StringSlice(notesFlag.Name) + + password, err := readPassword(ctx) + if err != nil { + return err + } + if err := arkSdkClient.Unlock(ctx.Context, string(password)); err != nil { + return err + } + txID, err := arkSdkClient.RedeemNotes(ctx.Context, notes) if err != nil { return err diff --git a/common/bitcointree/musig2.go b/common/bitcointree/musig2.go index 65c9cc09c..808844bd7 100644 --- a/common/bitcointree/musig2.go +++ b/common/bitcointree/musig2.go @@ -81,6 +81,7 @@ func DecodeSignatures(r io.Reader) (TreePartialSigs, error) { } type SignerSession interface { + Init(scriptRoot []byte, rootSharedOutputAmount int64, vtxoTree tree.VtxoTree) error GetPublicKey() string GetNonces() (TreeNonces, error) // generate tree nonces for this session SetAggregatedNonces(TreeNonces) // set the aggregated nonces @@ -190,28 +191,8 @@ func ValidateTreeSigs( }) } -func NewTreeSignerSession( - signer *btcec.PrivateKey, - roundSharedOutputAmount int64, - vtxoTree tree.VtxoTree, - scriptRoot []byte, -) (SignerSession, error) { - prevOutFetcherFactory, err := prevOutFetcherFactory(vtxoTree, roundSharedOutputAmount, scriptRoot) - if err != nil { - return nil, err - } - - txs, err := vtxoTreeToTx(vtxoTree) - if err != nil { - return nil, err - } - - return &treeSignerSession{ - secretKey: signer, - txs: txs, - scriptRoot: scriptRoot, - prevoutFetcherFactory: prevOutFetcherFactory, - }, nil +func NewTreeSignerSession(signer *btcec.PrivateKey) SignerSession { + return &treeSignerSession{secretKey: signer} } type treeSignerSession struct { @@ -223,6 +204,23 @@ type treeSignerSession struct { prevoutFetcherFactory func(*psbt.Packet) (txscript.PrevOutputFetcher, error) } +func (t *treeSignerSession) Init(scriptRoot []byte, rootSharedOutputAmount int64, vtxoTree tree.VtxoTree) error { + prevOutFetcherFactory, err := prevOutFetcherFactory(vtxoTree, rootSharedOutputAmount, scriptRoot) + if err != nil { + return err + } + + txs, err := vtxoTreeToTx(vtxoTree) + if err != nil { + return err + } + + t.scriptRoot = scriptRoot + t.txs = txs + t.prevoutFetcherFactory = prevOutFetcherFactory + return nil +} + func (t *treeSignerSession) GetPublicKey() string { return hex.EncodeToString(t.secretKey.PubKey().SerializeCompressed()) } diff --git a/common/bitcointree/musig2_test.go b/common/bitcointree/musig2_test.go index 81497deac..675da5980 100644 --- a/common/bitcointree/musig2_test.go +++ b/common/bitcointree/musig2_test.go @@ -67,14 +67,14 @@ func TestBuildAndSignVtxoTree(t *testing.T) { // Cceate signer sessions for each receivers signerSessions := make(map[*btcec.PublicKey]bitcointree.SignerSession) for _, prvkey := range tc.privKeys { - session, err := bitcointree.NewTreeSignerSession(prvkey, sharedOutputAmount, vtxoTree, sweepRoot[:]) - require.NoError(t, err) + session := bitcointree.NewTreeSignerSession(prvkey) + require.NoError(t, session.Init(sweepRoot[:], sharedOutputAmount, vtxoTree)) signerSessions[prvkey.PubKey()] = session } // ddd server's signer session - serverSession, err := bitcointree.NewTreeSignerSession(serverPrivKey, sharedOutputAmount, vtxoTree, sweepRoot[:]) - require.NoError(t, err) + serverSession := bitcointree.NewTreeSignerSession(serverPrivKey) + require.NoError(t, serverSession.Init(sweepRoot[:], sharedOutputAmount, vtxoTree)) signerSessions[serverPrivKey.PubKey()] = serverSession // generate nonces from all signers diff --git a/pkg/client-sdk/covenantless_client.go b/pkg/client-sdk/covenantless_client.go index 3b93751c7..95967e4bf 100644 --- a/pkg/client-sdk/covenantless_client.go +++ b/pkg/client-sdk/covenantless_client.go @@ -9,6 +9,7 @@ import ( "fmt" "math" "sort" + "strconv" "strings" "sync" "time" @@ -32,13 +33,26 @@ import ( "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/lightningnetwork/lnd/lnwallet/chainfee" log "github.com/sirupsen/logrus" + "golang.org/x/exp/slices" ) // Musig2SignOptions is only available for covenantless clients // it allows to customize the vtxo signing process type Musig2SignOptions struct { - CustomSignerPrivKeys []*secp256k1.PrivateKey + ExtraSignerSessions []bitcointree.SignerSession SigningType *tree.SigningType + WalletSignerDisabled bool +} + +// WithoutWalletSigner disables the wallet signer +func WithoutWalletSigner(o interface{}) error { + opts, ok := o.(*Musig2SignOptions) + if !ok { + return fmt.Errorf("invalid options type") + } + + opts.WalletSignerDisabled = true + return nil } // WithSignAll sets the signing type to ALL instead of the default BRANCH @@ -53,19 +67,19 @@ func WithSignAll(o interface{}) error { return nil } -// WithCustomTreeSigner allows to use a set of custom signer for the vtxo tree signing process -func WithCustomTreeSigner(privKeys []*secp256k1.PrivateKey) Option { +// WithExtraSigner allows to use a set of custom signer for the vtxo tree signing process +func WithExtraSigner(signerSessions ...bitcointree.SignerSession) Option { return func(o interface{}) error { opts, ok := o.(*Musig2SignOptions) if !ok { return fmt.Errorf("invalid options type") } - if len(privKeys) == 0 { - return fmt.Errorf("no private keys provided") + if len(signerSessions) == 0 { + return fmt.Errorf("no signer sessions provided") } - opts.CustomSignerPrivKeys = privKeys + opts.ExtraSignerSessions = signerSessions return nil } } @@ -892,7 +906,7 @@ func (a *covenantlessArkClient) RedeemNotes(ctx context.Context, notes []string, return "", fmt.Errorf("no funds detected") } - signerPrivKeys, signerPubKeys, signingType, err := handleOptions(options) + signerSessions, signerPubKeys, signingType, err := a.handleOptions(options, nil, notes) if err != nil { return "", err } @@ -924,7 +938,7 @@ func (a *covenantlessArkClient) RedeemNotes(ctx context.Context, notes []string, log.Infof("payout registered with id: %s", requestID) roundTxID, err := a.handleRoundStream( - ctx, requestID, nil, nil, receiversOutput, signerPrivKeys, + ctx, requestID, nil, nil, receiversOutput, signerSessions, ) if err != nil { return "", err @@ -1092,7 +1106,7 @@ func (a *covenantlessArkClient) CollaborativeRedeem( }) } - signerPrivKeys, signerPubKeys, signingType, err := handleOptions(options) + signerSessions, signerPubKeys, signingType, err := a.handleOptions(options, inputs, nil) if err != nil { return "", err } @@ -1116,7 +1130,7 @@ func (a *covenantlessArkClient) CollaborativeRedeem( } roundTxID, err := a.handleRoundStream( - ctx, requestID, selectedCoins, selectedBoardingCoins, receivers, signerPrivKeys, + ctx, requestID, selectedCoins, selectedBoardingCoins, receivers, signerSessions, ) if err != nil { return "", err @@ -1546,7 +1560,7 @@ func (a *covenantlessArkClient) sendOffchain( }) } - signerPrivKeys, signerPubKeys, signingType, err := handleOptions(options) + signerSessions, signerPubKeys, signingType, err := a.handleOptions(options, inputs, []string{}) if err != nil { return "", err } @@ -1571,7 +1585,7 @@ func (a *covenantlessArkClient) sendOffchain( log.Infof("registered inputs and outputs with request id: %s", requestID) roundTxID, err := a.handleRoundStream( - ctx, requestID, selectedCoins, selectedBoardingCoins, outputs, signerPrivKeys, + ctx, requestID, selectedCoins, selectedBoardingCoins, outputs, signerSessions, ) if err != nil { return "", err @@ -1658,7 +1672,7 @@ func (a *covenantlessArkClient) handleRoundStream( vtxosToSign []client.TapscriptsVtxo, boardingUtxos []types.Utxo, receivers []client.Output, - signerPrivKeys []*secp256k1.PrivateKey, + signerSessions []bitcointree.SignerSession, ) (string, error) { round, err := a.client.GetRound(ctx, "") if err != nil { @@ -1680,8 +1694,6 @@ func (a *covenantlessArkClient) handleRoundStream( close() }() - var signerSessions []bitcointree.SignerSession - const ( start = iota roundSigningStarted @@ -1717,10 +1729,9 @@ func (a *covenantlessArkClient) handleRoundStream( continue } log.Info("a round signing started") - signerSessions, err = a.handleRoundSigningStarted( - ctx, signerPrivKeys, event.(client.RoundSigningStartedEvent), - ) - if err != nil { + if err := a.handleRoundSigningStarted( + ctx, signerSessions, event.(client.RoundSigningStartedEvent), + ); err != nil { return "", err } step++ @@ -1772,8 +1783,8 @@ func (a *covenantlessArkClient) handleRoundStream( } func (a *covenantlessArkClient) handleRoundSigningStarted( - ctx context.Context, signerPrivKeys []*secp256k1.PrivateKey, event client.RoundSigningStartedEvent, -) ([]bitcointree.SignerSession, error) { + ctx context.Context, signerSessions []bitcointree.SignerSession, event client.RoundSigningStartedEvent, +) error { sweepClosure := tree.CSVMultisigClosure{ MultisigClosure: tree.MultisigClosure{PubKeys: []*secp256k1.PublicKey{a.ServerPubKey}}, Locktime: a.RoundLifetime, @@ -1781,12 +1792,12 @@ func (a *covenantlessArkClient) handleRoundSigningStarted( script, err := sweepClosure.Script() if err != nil { - return nil, err + return err } roundTx, err := psbt.NewFromRawBytes(strings.NewReader(event.UnsignedRoundTx), true) if err != nil { - return nil, err + return err } sharedOutput := roundTx.UnsignedTx.TxOut[0] @@ -1796,33 +1807,43 @@ func (a *covenantlessArkClient) handleRoundSigningStarted( sweepTapTree := txscript.AssembleTaprootScriptTree(sweepTapLeaf) root := sweepTapTree.RootNode.TapHash() - signerSessions := make([]bitcointree.SignerSession, 0, len(signerPrivKeys)) - - for _, privKey := range signerPrivKeys { - var session bitcointree.SignerSession - session, err = bitcointree.NewTreeSignerSession( - privKey, sharedOutputValue, event.UnsignedTree, root.CloneBytes(), - ) - if err != nil { - return nil, err + generateAndSendNonces := func(session bitcointree.SignerSession) error { + if err := session.Init(root.CloneBytes(), sharedOutputValue, event.UnsignedTree); err != nil { + return err } - signerSessions = append(signerSessions, session) - nonces, err := session.GetNonces() if err != nil { - return nil, err + return err } - myPubkey := hex.EncodeToString(privKey.PubKey().SerializeCompressed()) + return a.arkClient.client.SubmitTreeNonces(ctx, event.ID, session.GetPublicKey(), nonces) + } + + errChan := make(chan error, len(signerSessions)) + waitGroup := sync.WaitGroup{} + waitGroup.Add(len(signerSessions)) - err = a.arkClient.client.SubmitTreeNonces(ctx, event.ID, myPubkey, nonces) + for _, session := range signerSessions { + go func(session bitcointree.SignerSession) { + defer waitGroup.Done() + if err := generateAndSendNonces(session); err != nil { + errChan <- err + } + }(session) + } + + waitGroup.Wait() + + close(errChan) + + for err := range errChan { if err != nil { - return nil, err + return err } } - return signerSessions, nil + return nil } func (a *covenantlessArkClient) handleRoundSigningNoncesGenerated( @@ -1834,7 +1855,7 @@ func (a *covenantlessArkClient) handleRoundSigningNoncesGenerated( return fmt.Errorf("tree signer session not set") } - for _, session := range signerSessions { + sign := func(session bitcointree.SignerSession) error { session.SetAggregatedNonces(event.Nonces) sigs, err := session.Sign() @@ -1842,12 +1863,32 @@ func (a *covenantlessArkClient) handleRoundSigningNoncesGenerated( return err } - if err := a.arkClient.client.SubmitTreeSignatures( + return a.arkClient.client.SubmitTreeSignatures( ctx, event.ID, session.GetPublicKey(), sigs, - ); err != nil { + ) + } + + errChan := make(chan error, len(signerSessions)) + waitGroup := sync.WaitGroup{} + waitGroup.Add(len(signerSessions)) + + for _, session := range signerSessions { + go func(session bitcointree.SignerSession) { + defer waitGroup.Done() + if err := sign(session); err != nil { + errChan <- err + } + }(session) + } + + waitGroup.Wait() + close(errChan) + + for err := range errChan { + if err != nil { return err } } @@ -2784,16 +2825,7 @@ func buildRedeemTx( return bitcointree.BuildRedeemTx(ins, outs) } -func handleOptions(options *Musig2SignOptions) ([]*secp256k1.PrivateKey, []string, tree.SigningType, error) { - signerPrivKeys := make([]*secp256k1.PrivateKey, 0) - signerPubKeys := make([]string, 0) - if len(options.CustomSignerPrivKeys) > 0 { - for _, privKey := range options.CustomSignerPrivKeys { - signerPrivKeys = append(signerPrivKeys, privKey) - signerPubKeys = append(signerPubKeys, hex.EncodeToString(privKey.PubKey().SerializeCompressed())) - } - } - +func (a *covenantlessArkClient) handleOptions(options *Musig2SignOptions, inputs []client.Input, notesInputs []string) ([]bitcointree.SignerSession, []string, tree.SigningType, error) { var signingType tree.SigningType if options.SigningType != nil { signingType = *options.SigningType @@ -2801,15 +2833,76 @@ func handleOptions(options *Musig2SignOptions) ([]*secp256k1.PrivateKey, []strin signingType = tree.SignBranch } - // if no custom signer priv keys are provided, we generate a new ephemeral key - if len(signerPubKeys) == 0 { - ephemeralKey, err := secp256k1.GeneratePrivateKey() + sessions := make([]bitcointree.SignerSession, 0) + sessions = append(sessions, options.ExtraSignerSessions...) + + if !options.WalletSignerDisabled { + outpoints := make([]client.Outpoint, 0, len(inputs)) + for _, input := range inputs { + outpoints = append(outpoints, input.Outpoint) + } + + signerSession, err := a.wallet.NewVtxoTreeSigner( + context.Background(), + inputsToDerivationPath(outpoints, notesInputs), + ) if err != nil { - return nil, nil, tree.SignBranch, err + return nil, nil, signingType, err } - signerPrivKeys = append(signerPrivKeys, ephemeralKey) - signerPubKeys = append(signerPubKeys, hex.EncodeToString(ephemeralKey.PubKey().SerializeCompressed())) + sessions = append(sessions, signerSession) + } + + if len(sessions) == 0 { + return nil, nil, signingType, fmt.Errorf("no signer sessions") + } + + signerPubKeys := make([]string, 0) + for _, session := range sessions { + signerPubKeys = append(signerPubKeys, session.GetPublicKey()) + } + + return sessions, signerPubKeys, signingType, nil +} + +func inputsToDerivationPath(inputs []client.Outpoint, notesInputs []string) string { + // sort arknotes + slices.SortStableFunc(notesInputs, func(i, j string) int { + return strings.Compare(i, j) + }) + + // sort outpoints + slices.SortStableFunc(inputs, func(i, j client.Outpoint) int { + txidCmp := strings.Compare(i.Txid, j.Txid) + if txidCmp != 0 { + return txidCmp + } + return int(i.VOut - j.VOut) + }) + + // serialize outpoints and arknotes + + var buf bytes.Buffer + + for _, input := range inputs { + buf.WriteString(input.Txid) + buf.WriteString(strconv.Itoa(int(input.VOut))) + } + + for _, note := range notesInputs { + buf.WriteString(note) + } + + // hash the serialized data + hash := sha256.Sum256(buf.Bytes()) + + // convert hash to bip32 derivation path + // split the 32-byte hash into 8 uint32 values (4 bytes each) + path := "m" + for i := 0; i < 8; i++ { + // Convert 4 bytes to uint32 using big-endian encoding + segment := binary.BigEndian.Uint32(hash[i*4 : (i+1)*4]) + path += fmt.Sprintf("/%d'", segment) } - return signerPrivKeys, signerPubKeys, signingType, nil + return path } diff --git a/pkg/client-sdk/wallet/singlekey/bitcoin_wallet.go b/pkg/client-sdk/wallet/singlekey/bitcoin_wallet.go index e6b64a888..afaec9bc1 100644 --- a/pkg/client-sdk/wallet/singlekey/bitcoin_wallet.go +++ b/pkg/client-sdk/wallet/singlekey/bitcoin_wallet.go @@ -20,6 +20,8 @@ import ( "github.com/btcsuite/btcd/btcutil/psbt" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" + "github.com/decred/dcrd/dcrec/secp256k1/v4" + "github.com/vulpemventures/go-bip32" ) type bitcoinWallet struct { @@ -283,6 +285,53 @@ func (s *bitcoinWallet) SignTransaction( return ptx.B64Encode() } +func (w *bitcoinWallet) NewVtxoTreeSigner( + ctx context.Context, derivationPath string, +) (bitcointree.SignerSession, error) { + if w.IsLocked() { + return nil, fmt.Errorf("wallet is locked") + } + + if len(derivationPath) == 0 { + return nil, fmt.Errorf("derivation path is required") + } + + // convert private key to BIP32 master key format + // TODO UNSAFE ? + privKeyBytes := w.privateKey.Serialize() + masterKey, err := bip32.NewMasterKey(privKeyBytes) + if err != nil { + return nil, fmt.Errorf("failed to create master key: %w", err) + } + + paths := strings.Split(strings.TrimPrefix(derivationPath, "m/"), "/") + currentKey := masterKey + + for _, pathComponent := range paths { + index := uint32(0) + isHardened := strings.HasSuffix(pathComponent, "'") + if isHardened { + pathComponent = strings.TrimSuffix(pathComponent, "'") + } + + if _, err := fmt.Sscanf(pathComponent, "%d", &index); err != nil { + return nil, fmt.Errorf("invalid path component %s: %w", pathComponent, err) + } + + if isHardened { + index += bip32.FirstHardenedChild + } + + currentKey, err = currentKey.NewChildKey(index) + if err != nil { + return nil, fmt.Errorf("failed to derive child key: %w", err) + } + } + + derivedPrivKey := secp256k1.PrivKeyFromBytes(currentKey.Key) + return bitcointree.NewTreeSignerSession(derivedPrivKey), nil +} + func (w *bitcoinWallet) SignMessage( ctx context.Context, message []byte, ) (string, error) { diff --git a/pkg/client-sdk/wallet/singlekey/liquid_wallet.go b/pkg/client-sdk/wallet/singlekey/liquid_wallet.go index 99cc44332..3a23967ee 100644 --- a/pkg/client-sdk/wallet/singlekey/liquid_wallet.go +++ b/pkg/client-sdk/wallet/singlekey/liquid_wallet.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/ark-network/ark/common" + "github.com/ark-network/ark/common/bitcointree" "github.com/ark-network/ark/common/tree" "github.com/ark-network/ark/pkg/client-sdk/explorer" "github.com/ark-network/ark/pkg/client-sdk/internal/utils" @@ -325,6 +326,10 @@ func (w *liquidWallet) SignMessage( return hex.EncodeToString(sig.Serialize()), nil } +func (w *liquidWallet) NewVtxoTreeSigner(context.Context, string) (bitcointree.SignerSession, error) { + return nil, fmt.Errorf("not implemented") +} + func (w *liquidWallet) getAddress( ctx context.Context, ) ( diff --git a/pkg/client-sdk/wallet/wallet.go b/pkg/client-sdk/wallet/wallet.go index f50772a9d..0ff03fb21 100644 --- a/pkg/client-sdk/wallet/wallet.go +++ b/pkg/client-sdk/wallet/wallet.go @@ -3,6 +3,7 @@ package wallet import ( "context" + "github.com/ark-network/ark/common/bitcointree" "github.com/ark-network/ark/pkg/client-sdk/explorer" ) @@ -39,4 +40,5 @@ type WalletService interface { ctx context.Context, message []byte, ) (signature string, err error) Dump(ctx context.Context) (seed string, err error) + NewVtxoTreeSigner(ctx context.Context, derivationPath string) (bitcointree.SignerSession, error) } diff --git a/server/internal/core/application/covenantless.go b/server/internal/core/application/covenantless.go index 94d48fdbf..993a96cd5 100644 --- a/server/internal/core/application/covenantless.go +++ b/server/internal/core/application/covenantless.go @@ -1143,10 +1143,8 @@ func (s *covenantlessService) startFinalization() { return } - serverSignerSession, err := bitcointree.NewTreeSignerSession( - s.serverSigningKey, sharedOutputAmount, vtxoTree, root.CloneBytes(), - ) - if err != nil { + serverSignerSession := bitcointree.NewTreeSignerSession(s.serverSigningKey) + if err := serverSignerSession.Init(root.CloneBytes(), sharedOutputAmount, vtxoTree); err != nil { round.Fail(fmt.Errorf("failed to create tree signer session: %s", err)) log.WithError(err).Warn("failed to create tree signer session") return diff --git a/server/test/e2e/covenantless/e2e_test.go b/server/test/e2e/covenantless/e2e_test.go index 2b067f062..ff7729689 100644 --- a/server/test/e2e/covenantless/e2e_test.go +++ b/server/test/e2e/covenantless/e2e_test.go @@ -619,7 +619,7 @@ func TestRedeemNotes(t *testing.T) { var balanceBefore utils.ArkBalance require.NoError(t, json.Unmarshal([]byte(balanceBeforeStr), &balanceBefore)) - _, err = runClarkCommand("redeem-notes", "--notes", note) + _, err = runClarkCommand("redeem-notes", "--notes", note, "--password", utils.Password) require.NoError(t, err) time.Sleep(2 * time.Second) @@ -632,7 +632,7 @@ func TestRedeemNotes(t *testing.T) { require.Greater(t, balanceAfter.Offchain.Total, balanceBefore.Offchain.Total) - _, err = runClarkCommand("redeem-notes", "--notes", note) + _, err = runClarkCommand("redeem-notes", "--notes", note, "--password", utils.Password) require.Error(t, err) } @@ -1030,7 +1030,7 @@ func TestSweep(t *testing.T) { require.NotEmpty(t, note) // redeem the note - _, err = runClarkCommand("redeem-notes", "--notes", note) + _, err = runClarkCommand("redeem-notes", "--notes", note, "--password", utils.Password) require.NoError(t, err) } From 59a53d86b387038d5e3eae4e52c8945f64295cae Mon Sep 17 00:00:00 2001 From: louisinger Date: Sun, 19 Jan 2025 00:19:42 +0100 Subject: [PATCH 11/21] go work sync --- pkg/client-sdk/go.mod | 5 ++++- pkg/client-sdk/go.sum | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pkg/client-sdk/go.mod b/pkg/client-sdk/go.mod index b8825e43b..d872b07ea 100644 --- a/pkg/client-sdk/go.mod +++ b/pkg/client-sdk/go.mod @@ -24,12 +24,16 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/stretchr/testify v1.9.0 github.com/timshannon/badgerhold/v4 v4.0.3 + github.com/vulpemventures/go-bip32 v0.0.0-20200624192635-867c159da4d7 github.com/vulpemventures/go-elements v0.5.4 golang.org/x/crypto v0.32.0 + golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 google.golang.org/grpc v1.65.0 ) require ( + github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect github.com/aead/siphash v1.0.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect @@ -89,7 +93,6 @@ require ( go.opentelemetry.io/otel/metric v1.30.0 // indirect go.opentelemetry.io/otel/sdk v1.28.0 // indirect go.opentelemetry.io/otel/trace v1.30.0 // indirect - golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect golang.org/x/net v0.34.0 // indirect golang.org/x/sync v0.10.0 // indirect golang.org/x/sys v0.29.0 // indirect diff --git a/pkg/client-sdk/go.sum b/pkg/client-sdk/go.sum index 6ce2ea47e..17578711e 100644 --- a/pkg/client-sdk/go.sum +++ b/pkg/client-sdk/go.sum @@ -1,5 +1,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= @@ -45,6 +47,7 @@ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= @@ -273,6 +276,7 @@ github.com/timshannon/badgerhold/v4 v4.0.3/go.mod h1:IkZIr0kcZLMdD7YJfW/G6epb6ZX github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/vulpemventures/fastsha256 v0.0.0-20160815193821-637e65642941 h1:CTcw80hz/Sw8hqlKX5ZYvBUF5gAHSHwdjXxRf/cjDcI= github.com/vulpemventures/fastsha256 v0.0.0-20160815193821-637e65642941/go.mod h1:GXBJykxW2kUcktGdsgyay7uwwWvkljASfljNcT0mbh8= +github.com/vulpemventures/go-bip32 v0.0.0-20200624192635-867c159da4d7 h1:X7DtNv+YWy76kELMZB/xVkIJ7YNp2vpgMFVsDcQA40U= github.com/vulpemventures/go-elements v0.5.4 h1:l94xoa9aYPPWiOB7Pmi08rKYvdk/n/sQIbLkQfEAASc= github.com/vulpemventures/go-elements v0.5.4/go.mod h1:Tvhb+rZWv3lxoI5CdK03J3V+e2QVr/7UAnCYILxFSq4= github.com/vulpemventures/go-secp256k1-zkp v1.1.6 h1:BmsrmXRLUibwa75Qkk8yELjpzCzlAjYFGLiLiOdq7Xo= @@ -444,3 +448,4 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= From aa35ab2b5033bf89859eca5ee9e474a6144393f1 Mon Sep 17 00:00:00 2001 From: louisinger Date: Wed, 22 Jan 2025 09:19:13 +0100 Subject: [PATCH 12/21] signingAll boolean in API --- .../swagger/ark/v1/service.swagger.json | 5 +- api-spec/protobuf/ark/v1/service.proto | 2 +- api-spec/protobuf/gen/ark/v1/service.pb.go | 445 +++++++++--------- pkg/client-sdk/client/grpc/client.go | 2 +- pkg/client-sdk/client/rest/client.go | 2 +- .../client/rest/service/models/v1_musig2.go | 4 +- .../interface/grpc/handlers/arkservice.go | 6 +- 7 files changed, 234 insertions(+), 232 deletions(-) diff --git a/api-spec/openapi/swagger/ark/v1/service.swagger.json b/api-spec/openapi/swagger/ark/v1/service.swagger.json index 118d37e45..cc79c1e9d 100644 --- a/api-spec/openapi/swagger/ark/v1/service.swagger.json +++ b/api-spec/openapi/swagger/ark/v1/service.swagger.json @@ -603,9 +603,8 @@ "type": "string" } }, - "signingType": { - "type": "integer", - "format": "int64" + "signingAll": { + "type": "boolean" } } }, diff --git a/api-spec/protobuf/ark/v1/service.proto b/api-spec/protobuf/ark/v1/service.proto index 029ec70ec..d4fa5d1ce 100755 --- a/api-spec/protobuf/ark/v1/service.proto +++ b/api-spec/protobuf/ark/v1/service.proto @@ -128,7 +128,7 @@ message RegisterInputsForNextRoundResponse { message Musig2 { repeated string cosigners_public_keys = 1; - uint32 signing_type = 2; + bool signing_all = 2; } message RegisterOutputsForNextRoundRequest { diff --git a/api-spec/protobuf/gen/ark/v1/service.pb.go b/api-spec/protobuf/gen/ark/v1/service.pb.go index 46e6664f4..601ba04bf 100644 --- a/api-spec/protobuf/gen/ark/v1/service.pb.go +++ b/api-spec/protobuf/gen/ark/v1/service.pb.go @@ -422,7 +422,7 @@ type Musig2 struct { unknownFields protoimpl.UnknownFields CosignersPublicKeys []string `protobuf:"bytes,1,rep,name=cosigners_public_keys,json=cosignersPublicKeys,proto3" json:"cosigners_public_keys,omitempty"` - SigningType uint32 `protobuf:"varint,2,opt,name=signing_type,json=signingType,proto3" json:"signing_type,omitempty"` + SigningAll bool `protobuf:"varint,2,opt,name=signing_all,json=signingAll,proto3" json:"signing_all,omitempty"` } func (x *Musig2) Reset() { @@ -464,11 +464,11 @@ func (x *Musig2) GetCosignersPublicKeys() []string { return nil } -func (x *Musig2) GetSigningType() uint32 { +func (x *Musig2) GetSigningAll() bool { if x != nil { - return x.SigningType + return x.SigningAll } - return 0 + return false } type RegisterOutputsForNextRoundRequest struct { @@ -1568,234 +1568,233 @@ var file_ark_v1_service_proto_rawDesc = []byte{ 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x22, 0x5f, 0x0a, 0x06, 0x4d, 0x75, 0x73, 0x69, 0x67, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x22, 0x5d, 0x0a, 0x06, 0x4d, 0x75, 0x73, 0x69, 0x67, 0x32, 0x12, 0x32, 0x0a, 0x15, 0x63, 0x6f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x13, 0x63, 0x6f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x50, 0x75, 0x62, 0x6c, 0x69, - 0x63, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, - 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x73, 0x69, 0x67, - 0x6e, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x22, 0xa5, 0x01, 0x0a, 0x22, 0x52, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, - 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x28, - 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x0e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x52, - 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x12, 0x2b, 0x0a, 0x06, 0x6d, 0x75, 0x73, 0x69, - 0x67, 0x32, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, - 0x31, 0x2e, 0x4d, 0x75, 0x73, 0x69, 0x67, 0x32, 0x48, 0x00, 0x52, 0x06, 0x6d, 0x75, 0x73, 0x69, - 0x67, 0x32, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x6d, 0x75, 0x73, 0x69, 0x67, 0x32, - 0x22, 0x25, 0x0a, 0x23, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, - 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6d, 0x0a, 0x17, 0x53, 0x75, 0x62, 0x6d, 0x69, - 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x16, 0x0a, - 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, - 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x6e, 0x6f, - 0x6e, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x72, 0x65, 0x65, - 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x22, 0x1a, 0x0a, 0x18, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, - 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x79, 0x0a, 0x1b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, - 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, - 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, - 0x62, 0x6b, 0x65, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, - 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x22, 0x1e, 0x0a, - 0x1c, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x8e, 0x01, - 0x0a, 0x1d, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, - 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x2c, 0x0a, 0x12, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x66, 0x6f, 0x72, 0x66, 0x65, 0x69, - 0x74, 0x5f, 0x74, 0x78, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x73, 0x69, 0x67, - 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x2b, 0x0a, - 0x0f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, - 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x88, 0x01, 0x01, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x73, - 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x22, 0x20, - 0x0a, 0x1e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, - 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x17, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, - 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xa7, 0x03, 0x0a, 0x16, 0x47, 0x65, - 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x12, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x66, 0x69, - 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, - 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x48, 0x00, 0x52, 0x11, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x0a, 0x0f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x66, - 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, + 0x63, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, + 0x5f, 0x61, 0x6c, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x73, 0x69, 0x67, 0x6e, + 0x69, 0x6e, 0x67, 0x41, 0x6c, 0x6c, 0x22, 0xa5, 0x01, 0x0a, 0x22, 0x52, 0x65, 0x67, 0x69, 0x73, + 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, + 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, + 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x07, + 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, + 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x52, 0x07, 0x6f, + 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x12, 0x2b, 0x0a, 0x06, 0x6d, 0x75, 0x73, 0x69, 0x67, 0x32, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, + 0x4d, 0x75, 0x73, 0x69, 0x67, 0x32, 0x48, 0x00, 0x52, 0x06, 0x6d, 0x75, 0x73, 0x69, 0x67, 0x32, + 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x6d, 0x75, 0x73, 0x69, 0x67, 0x32, 0x22, 0x25, + 0x0a, 0x23, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, + 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6d, 0x0a, 0x17, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, + 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x19, 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, + 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, + 0x6b, 0x65, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, + 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x72, 0x65, 0x65, 0x4e, 0x6f, + 0x6e, 0x63, 0x65, 0x73, 0x22, 0x1a, 0x0a, 0x18, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, + 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x79, 0x0a, 0x1b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x19, 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, + 0x62, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, + 0x65, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x72, 0x65, + 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x22, 0x1e, 0x0a, 0x1c, 0x53, + 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x8e, 0x01, 0x0a, 0x1d, + 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, + 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, + 0x12, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x66, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x5f, + 0x74, 0x78, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x73, 0x69, 0x67, 0x6e, 0x65, + 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x2b, 0x0a, 0x0f, 0x73, + 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x52, 0x6f, + 0x75, 0x6e, 0x64, 0x54, 0x78, 0x88, 0x01, 0x01, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x73, 0x69, 0x67, + 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x22, 0x20, 0x0a, 0x1e, + 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, + 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, + 0x0a, 0x15, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xa7, 0x03, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x12, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x66, 0x69, 0x6e, 0x61, + 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, - 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0e, 0x72, - 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x38, 0x0a, - 0x0c, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, - 0x6e, 0x64, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0b, 0x72, 0x6f, 0x75, 0x6e, - 0x64, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x40, 0x0a, 0x0d, 0x72, 0x6f, 0x75, 0x6e, 0x64, - 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, - 0x6e, 0x69, 0x6e, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x72, 0x6f, 0x75, - 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x6f, 0x0a, 0x1e, 0x72, 0x6f, 0x75, - 0x6e, 0x64, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, - 0x73, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x28, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, - 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x47, 0x65, 0x6e, - 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1b, 0x72, - 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4e, 0x6f, 0x6e, 0x63, 0x65, - 0x73, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x22, 0x2c, 0x0a, 0x0b, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, - 0x64, 0x22, 0x0e, 0x0a, 0x0c, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x34, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, - 0x6d, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, - 0x64, 0x65, 0x65, 0x6d, 0x5f, 0x74, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, - 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x22, 0x42, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, - 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x64, 0x65, - 0x65, 0x6d, 0x5f, 0x74, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x69, 0x67, - 0x6e, 0x65, 0x64, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x22, 0x1e, 0x0a, 0x1c, 0x47, - 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, - 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x8c, 0x01, 0x0a, 0x1d, - 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, - 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x61, - 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, - 0x33, 0x0a, 0x06, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, - 0x64, 0x65, 0x65, 0x6d, 0x42, 0x04, 0x0a, 0x02, 0x74, 0x78, 0x22, 0x75, 0x0a, 0x18, 0x53, 0x65, - 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x5f, - 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0e, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, - 0x30, 0x0a, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, - 0x78, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x05, 0x76, 0x74, 0x78, 0x6f, - 0x73, 0x22, 0x1b, 0x0a, 0x19, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, - 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4f, - 0x0a, 0x1b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, - 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, - 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, + 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, + 0x52, 0x11, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x0a, 0x0f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x66, 0x69, 0x6e, + 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, + 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x7a, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0e, 0x72, 0x6f, 0x75, + 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x38, 0x0a, 0x0c, 0x72, + 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x13, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, + 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0b, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x46, + 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x40, 0x0a, 0x0d, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, + 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, + 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, + 0x6e, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x72, 0x6f, 0x75, 0x6e, 0x64, + 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x6f, 0x0a, 0x1e, 0x72, 0x6f, 0x75, 0x6e, 0x64, + 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x5f, + 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x28, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, + 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x47, 0x65, 0x6e, 0x65, 0x72, + 0x61, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1b, 0x72, 0x6f, 0x75, + 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x47, + 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x22, 0x2c, 0x0a, 0x0b, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x22, + 0x0e, 0x0a, 0x0c, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x34, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, + 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x64, 0x65, + 0x65, 0x6d, 0x5f, 0x74, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x64, + 0x65, 0x65, 0x6d, 0x54, 0x78, 0x22, 0x42, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, + 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x28, 0x0a, 0x10, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, + 0x5f, 0x74, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x69, 0x67, 0x6e, 0x65, + 0x64, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x22, 0x1e, 0x0a, 0x1c, 0x47, 0x65, 0x74, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x8c, 0x01, 0x0a, 0x1d, 0x47, 0x65, + 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x72, + 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x61, 0x72, 0x6b, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x33, 0x0a, + 0x06, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x64, 0x65, + 0x65, 0x6d, 0x42, 0x04, 0x0a, 0x02, 0x74, 0x78, 0x22, 0x75, 0x0a, 0x18, 0x53, 0x65, 0x74, 0x4e, + 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x5f, 0x72, 0x65, + 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6e, + 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x30, 0x0a, + 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x22, - 0x1e, 0x0a, 0x1c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, - 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, - 0xd2, 0x0c, 0x0a, 0x0a, 0x41, 0x72, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4c, - 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x61, 0x72, 0x6b, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x17, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x74, 0x0a, 0x12, - 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x12, 0x21, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, - 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x11, 0x3a, 0x01, 0x2a, 0x22, 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, - 0x6e, 0x67, 0x12, 0x98, 0x01, 0x0a, 0x1a, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, - 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, - 0x64, 0x12, 0x29, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, - 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x61, - 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, - 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, - 0x3a, 0x01, 0x2a, 0x22, 0x18, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x72, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x9c, 0x01, - 0x0a, 0x1b, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, - 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2a, 0x2e, - 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, - 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x61, 0x72, 0x6b, 0x2e, - 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, + 0x1b, 0x0a, 0x19, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, + 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4f, 0x0a, 0x1b, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, + 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x05, 0x76, + 0x74, 0x78, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x72, 0x6b, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, 0x4f, 0x75, + 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x1e, 0x0a, + 0x1c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, + 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xd2, 0x0c, + 0x0a, 0x0a, 0x41, 0x72, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x07, + 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x17, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, + 0x12, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x74, 0x0a, 0x12, 0x47, 0x65, + 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x12, 0x21, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, + 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, + 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x3a, + 0x01, 0x2a, 0x22, 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, + 0x12, 0x98, 0x01, 0x0a, 0x1a, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, + 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, + 0x29, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, + 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, + 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x61, 0x72, 0x6b, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x3a, 0x01, - 0x2a, 0x22, 0x19, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x72, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x12, 0x7d, 0x0a, 0x10, - 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, - 0x12, 0x1f, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, - 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x20, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, - 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, 0x2a, 0x22, 0x1b, - 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x2f, 0x73, - 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x8d, 0x01, 0x0a, 0x14, - 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x73, 0x12, 0x23, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x3a, 0x01, + 0x2a, 0x22, 0x18, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x72, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x9c, 0x01, 0x0a, 0x1b, + 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, + 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2a, 0x2e, 0x61, 0x72, + 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, + 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, + 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x3a, 0x01, 0x2a, 0x22, + 0x19, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, + 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x12, 0x7d, 0x0a, 0x10, 0x53, 0x75, + 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x1f, + 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, + 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x20, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, + 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, 0x2a, 0x22, 0x1b, 0x2f, 0x76, + 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x2f, 0x73, 0x75, 0x62, + 0x6d, 0x69, 0x74, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x8d, 0x01, 0x0a, 0x14, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, - 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x3a, 0x01, 0x2a, 0x22, 0x1f, 0x2f, 0x76, 0x31, 0x2f, - 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, - 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x8e, 0x01, 0x0a, 0x16, - 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, - 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x25, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, - 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, - 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, - 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, - 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x3a, 0x01, 0x2a, - 0x22, 0x1a, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x73, 0x75, 0x62, 0x6d, - 0x69, 0x74, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x65, 0x0a, 0x0e, - 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1d, - 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, - 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x12, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x0c, 0x12, 0x0a, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x73, 0x30, 0x01, 0x12, 0x56, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x13, 0x2e, 0x61, 0x72, - 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x14, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, - 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x70, 0x69, 0x6e, 0x67, 0x2f, 0x7b, - 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x69, 0x0a, 0x0e, 0x53, - 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x12, 0x1d, 0x2e, - 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, - 0x65, 0x65, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, - 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, - 0x65, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x12, 0x3a, 0x01, 0x2a, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x64, - 0x65, 0x65, 0x6d, 0x2d, 0x74, 0x78, 0x12, 0x80, 0x01, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x12, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, - 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x30, 0x01, 0x12, 0x73, 0x0a, 0x11, 0x53, 0x65, 0x74, - 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x20, + 0x65, 0x73, 0x12, 0x23, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, + 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x3a, 0x01, 0x2a, 0x22, 0x1f, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, + 0x75, 0x6e, 0x64, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x8e, 0x01, 0x0a, 0x16, 0x53, 0x75, + 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, + 0x74, 0x54, 0x78, 0x73, 0x12, 0x25, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, + 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, + 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x61, 0x72, + 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, + 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x3a, 0x01, 0x2a, 0x22, 0x1a, + 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, + 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x65, 0x0a, 0x0e, 0x47, 0x65, + 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1d, 0x2e, 0x61, + 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x72, + 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x12, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x0c, 0x12, 0x0a, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x30, + 0x01, 0x12, 0x56, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x13, 0x2e, 0x61, 0x72, 0x6b, 0x2e, + 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, + 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x76, + 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x70, 0x69, 0x6e, 0x67, 0x2f, 0x7b, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x69, 0x0a, 0x0e, 0x53, 0x75, 0x62, + 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x12, 0x1d, 0x2e, 0x61, 0x72, + 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, + 0x6d, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x72, 0x6b, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, + 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x12, 0x3a, 0x01, 0x2a, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x64, 0x65, 0x65, + 0x6d, 0x2d, 0x74, 0x78, 0x12, 0x80, 0x01, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x24, + 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, + 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x30, 0x01, 0x12, 0x73, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x4e, 0x6f, + 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x20, 0x2e, 0x61, + 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, + 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, - 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x21, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, - 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x22, 0x0e, - 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78, 0x6f, 0x2f, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x12, 0x83, - 0x01, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, - 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, - 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x61, - 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, - 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x3a, 0x01, 0x2a, 0x22, 0x15, 0x2f, - 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78, 0x6f, 0x2f, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x2f, 0x64, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x42, 0x92, 0x01, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x72, 0x6b, - 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x50, 0x01, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x61, 0x72, 0x6b, 0x2d, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x61, 0x72, 0x6b, 0x2f, - 0x61, 0x70, 0x69, 0x2d, 0x73, 0x70, 0x65, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x61, 0x72, 0x6b, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x72, 0x6b, - 0x76, 0x31, 0xa2, 0x02, 0x03, 0x41, 0x58, 0x58, 0xaa, 0x02, 0x06, 0x41, 0x72, 0x6b, 0x2e, 0x56, - 0x31, 0xca, 0x02, 0x06, 0x41, 0x72, 0x6b, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x12, 0x41, 0x72, 0x6b, - 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, - 0x02, 0x07, 0x41, 0x72, 0x6b, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x22, 0x0e, 0x2f, 0x76, + 0x31, 0x2f, 0x76, 0x74, 0x78, 0x6f, 0x2f, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x12, 0x83, 0x01, 0x0a, + 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, + 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, + 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x61, 0x72, 0x6b, + 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, + 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x3a, 0x01, 0x2a, 0x22, 0x15, 0x2f, 0x76, 0x31, + 0x2f, 0x76, 0x74, 0x78, 0x6f, 0x2f, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x2f, 0x64, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x42, 0x92, 0x01, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, + 0x31, 0x42, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, + 0x01, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, + 0x6b, 0x2d, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x61, 0x72, 0x6b, 0x2f, 0x61, 0x70, + 0x69, 0x2d, 0x73, 0x70, 0x65, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, + 0x67, 0x65, 0x6e, 0x2f, 0x61, 0x72, 0x6b, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x72, 0x6b, 0x76, 0x31, + 0xa2, 0x02, 0x03, 0x41, 0x58, 0x58, 0xaa, 0x02, 0x06, 0x41, 0x72, 0x6b, 0x2e, 0x56, 0x31, 0xca, + 0x02, 0x06, 0x41, 0x72, 0x6b, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x12, 0x41, 0x72, 0x6b, 0x5c, 0x56, + 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x07, + 0x41, 0x72, 0x6b, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/client-sdk/client/grpc/client.go b/pkg/client-sdk/client/grpc/client.go index bc85138c8..6331b996a 100644 --- a/pkg/client-sdk/client/grpc/client.go +++ b/pkg/client-sdk/client/grpc/client.go @@ -126,7 +126,7 @@ func (a *grpcClient) RegisterOutputsForNextRound( if musig2 != nil { req.Musig2 = &arkv1.Musig2{ CosignersPublicKeys: musig2.CosignersPublicKeys, - SigningType: uint32(musig2.SigningType), + SigningAll: musig2.SigningType == tree.SignAll, } } _, err := a.svc.RegisterOutputsForNextRound(ctx, req) diff --git a/pkg/client-sdk/client/rest/client.go b/pkg/client-sdk/client/rest/client.go index 5b500e40b..b376e3d61 100644 --- a/pkg/client-sdk/client/rest/client.go +++ b/pkg/client-sdk/client/rest/client.go @@ -173,7 +173,7 @@ func (a *restClient) RegisterOutputsForNextRound( if musig2 != nil { body.Musig2 = &models.V1Musig2{ CosignersPublicKeys: musig2.CosignersPublicKeys, - SigningType: int64(musig2.SigningType), + SigningAll: musig2.SigningType == tree.SignAll, } } _, err := a.svc.ArkServiceRegisterOutputsForNextRound( diff --git a/pkg/client-sdk/client/rest/service/models/v1_musig2.go b/pkg/client-sdk/client/rest/service/models/v1_musig2.go index 90df1329b..98e0c3416 100644 --- a/pkg/client-sdk/client/rest/service/models/v1_musig2.go +++ b/pkg/client-sdk/client/rest/service/models/v1_musig2.go @@ -20,8 +20,8 @@ type V1Musig2 struct { // cosigners public keys CosignersPublicKeys []string `json:"cosignersPublicKeys"` - // signing type - SigningType int64 `json:"signingType,omitempty"` + // signing all + SigningAll bool `json:"signingAll,omitempty"` } // Validate validates this v1 musig2 diff --git a/server/internal/interface/grpc/handlers/arkservice.go b/server/internal/interface/grpc/handlers/arkservice.go index 4fc947f4d..0b7452069 100644 --- a/server/internal/interface/grpc/handlers/arkservice.go +++ b/server/internal/interface/grpc/handlers/arkservice.go @@ -167,9 +167,13 @@ func (h *handler) RegisterOutputsForNextRound( musig2Data := req.GetMusig2() var musig2 *tree.Musig2 if musig2Data != nil { + signingType := tree.SignBranch + if musig2Data.SigningAll { + signingType = tree.SignAll + } musig2 = &tree.Musig2{ CosignersPublicKeys: musig2Data.GetCosignersPublicKeys(), - SigningType: tree.SigningType(musig2Data.GetSigningType()), + SigningType: signingType, } } From 46cf2cd1c9b43f55af55ae4f888f56e4b15bc400 Mon Sep 17 00:00:00 2001 From: louisinger Date: Wed, 22 Jan 2025 15:31:52 +0100 Subject: [PATCH 13/21] fix matrix of bytes encoding --- common/bitcointree/musig2.go | 26 ++++- common/bitcointree/musig2_test.go | 27 ++++++ server/test/e2e/covenantless/e2e_test.go | 118 ++++++++++++++++++++--- 3 files changed, 152 insertions(+), 19 deletions(-) diff --git a/common/bitcointree/musig2.go b/common/bitcointree/musig2.go index 808844bd7..b9154d96c 100644 --- a/common/bitcointree/musig2.go +++ b/common/bitcointree/musig2.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "io" + "reflect" "runtime" "strings" "sync" @@ -686,15 +687,25 @@ func encodeMatrix[T writable](matrix [][]T) ([]byte, error) { // For each row, write its length and then its elements for _, row := range matrix { - // Write row length + // for each row, write its length if err := binary.Write(&buf, binary.LittleEndian, uint32(len(row))); err != nil { return nil, err } - // Write row data + // for each cell, write | bytes for _, cell := range row { - if err := cell.Encode(&buf); err != nil { + notNil := true + if reflect.ValueOf(cell).IsNil() { + notNil = false + } + if err := binary.Write(&buf, binary.LittleEndian, notNil); err != nil { return nil, err } + + if notNil { + if err := cell.Encode(&buf); err != nil { + return nil, err + } + } } } @@ -723,6 +734,15 @@ func decodeMatrix[T readable](factory func() T, data io.Reader) ([][]T, error) { row := make([]T, 0, colCount) // Read row data for j := uint32(0); j < colCount; j++ { + // check if the cell is nil + var notNil bool + if err := binary.Read(data, binary.LittleEndian, ¬Nil); err != nil { + return nil, err + } + if !notNil { + row = append(row, *new(T)) // append a new nil cell + continue + } cell := factory() if err := cell.Decode(data); err != nil { return nil, err diff --git a/common/bitcointree/musig2_test.go b/common/bitcointree/musig2_test.go index 675da5980..b0de7514b 100644 --- a/common/bitcointree/musig2_test.go +++ b/common/bitcointree/musig2_test.go @@ -1,6 +1,7 @@ package bitcointree_test import ( + "bytes" "encoding/hex" "fmt" "testing" @@ -81,6 +82,17 @@ func TestBuildAndSignVtxoTree(t *testing.T) { for pubkey, session := range signerSessions { nonces, err := session.GetNonces() require.NoError(t, err) + var encodedNonces bytes.Buffer + err = nonces.Encode(&encodedNonces) + require.NoError(t, err) + decodedNonces, err := bitcointree.DecodeNonces(&encodedNonces) + require.NoError(t, err) + for i, nonceRow := range nonces { + for j, nonce := range nonceRow { + require.Equal(t, nonce, decodedNonces[i][j]) + } + } + serverCoordinator.AddNonce(pubkey, nonces) } @@ -96,6 +108,21 @@ func TestBuildAndSignVtxoTree(t *testing.T) { for pubkey, session := range signerSessions { sig, err := session.Sign() require.NoError(t, err) + var encodedSig bytes.Buffer + err = sig.Encode(&encodedSig) + require.NoError(t, err) + decodedSig, err := bitcointree.DecodeSignatures(&encodedSig) + require.NoError(t, err) + for i, sigRow := range sig { + for j, sig := range sigRow { + if sig == nil { + require.Nil(t, decodedSig[i][j]) + } else { + require.Equal(t, sig.S, decodedSig[i][j].S) + } + } + } + serverCoordinator.AddSig(pubkey, sig) } diff --git a/server/test/e2e/covenantless/e2e_test.go b/server/test/e2e/covenantless/e2e_test.go index ff7729689..494701415 100644 --- a/server/test/e2e/covenantless/e2e_test.go +++ b/server/test/e2e/covenantless/e2e_test.go @@ -11,6 +11,7 @@ import ( "net/http" "os" "strings" + "sync" "testing" "time" @@ -81,40 +82,125 @@ func TestMain(m *testing.M) { os.Exit(code) } -func TestSendOffchain(t *testing.T) { - var receive utils.ArkReceive - receiveStr, err := runClarkCommand("receive") +func TestSettleInSameRound(t *testing.T) { + ctx := context.Background() + alice, grpcAlice := setupArkSDK(t) + defer grpcAlice.Close() + + bob, grpcBob := setupArkSDK(t) + defer grpcBob.Close() + + _, aliceBoardingAddress, err := alice.Receive(ctx) require.NoError(t, err) - err = json.Unmarshal([]byte(receiveStr), &receive) + _, bobBoardingAddress, err := bob.Receive(ctx) require.NoError(t, err) - _, err = utils.RunCommand("nigiri", "faucet", receive.Boarding) + _, err = utils.RunCommand("nigiri", "faucet", aliceBoardingAddress) + require.NoError(t, err) + + _, err = utils.RunCommand("nigiri", "faucet", bobBoardingAddress) require.NoError(t, err) time.Sleep(5 * time.Second) - _, err = runClarkCommand("settle", "--password", utils.Password) + aliceOffchainAddr, _, err := alice.Receive(ctx) require.NoError(t, err) - time.Sleep(3 * time.Second) + bobOffchainAddr, _, err := bob.Receive(ctx) + require.NoError(t, err) - _, err = runClarkCommand("send", "--amount", "10000", "--to", receive.Offchain, "--password", utils.Password) + // Alice sends to Bob + _, err = alice.SendOffChain(ctx, false, []arksdk.Receiver{arksdk.NewBitcoinReceiver(bobOffchainAddr, 5000)}) require.NoError(t, err) - var balance utils.ArkBalance - balanceStr, err := runClarkCommand("balance") + // Bob sends to Alice + _, err = bob.SendOffChain(ctx, false, []arksdk.Receiver{arksdk.NewBitcoinReceiver(aliceOffchainAddr, 3000)}) require.NoError(t, err) - require.NoError(t, json.Unmarshal([]byte(balanceStr), &balance)) - require.NotZero(t, balance.Offchain.Total) - _, err = runClarkCommand("settle", "--password", utils.Password) + time.Sleep(2 * time.Second) + + var wg sync.WaitGroup + wg.Add(2) + + var aliceRoundID, bobRoundID string + var aliceErr, bobErr error + + go func() { + defer wg.Done() + aliceRoundID, aliceErr = alice.Settle(ctx) + }() + + go func() { + defer wg.Done() + bobRoundID, bobErr = bob.Settle(ctx) + }() + + wg.Wait() + + require.NoError(t, aliceErr) + require.NoError(t, bobErr) + require.NotEmpty(t, aliceRoundID) + require.NotEmpty(t, bobRoundID) + require.Equal(t, aliceRoundID, bobRoundID) + + time.Sleep(5 * time.Second) + + aliceVtxos, _, err := alice.ListVtxos(ctx) require.NoError(t, err) + require.NotEmpty(t, aliceVtxos) - balanceStr, err = runClarkCommand("balance") + bobVtxos, _, err := bob.ListVtxos(ctx) require.NoError(t, err) - require.NoError(t, json.Unmarshal([]byte(balanceStr), &balance)) - require.NotZero(t, balance.Offchain.Total) + require.NotEmpty(t, bobVtxos) + + wg.Add(2) + + var aliceSecondRoundID, bobSecondRoundID string + + go func() { + defer wg.Done() + aliceSecondRoundID, aliceErr = alice.Settle(ctx) + }() + + go func() { + defer wg.Done() + bobSecondRoundID, bobErr = bob.Settle(ctx) + }() + + wg.Wait() + + require.NoError(t, aliceErr) + require.NoError(t, bobErr) + require.Equal(t, aliceSecondRoundID, bobSecondRoundID, "Second settle round IDs should match") + + time.Sleep(5 * time.Second) + + aliceVtxosAfter, _, err := alice.ListVtxos(ctx) + require.NoError(t, err) + require.NotEmpty(t, aliceVtxosAfter) + + bobVtxosAfter, _, err := bob.ListVtxos(ctx) + require.NoError(t, err) + require.NotEmpty(t, bobVtxosAfter) + + var aliceNewVtxo, bobNewVtxo client.Vtxo + for _, vtxo := range aliceVtxosAfter { + if vtxo.RoundTxid == aliceSecondRoundID { + aliceNewVtxo = vtxo + break + } + } + for _, vtxo := range bobVtxosAfter { + if vtxo.RoundTxid == bobSecondRoundID { + bobNewVtxo = vtxo + break + } + } + + require.NotEmpty(t, aliceNewVtxo) + require.NotEmpty(t, bobNewVtxo) + require.Equal(t, aliceNewVtxo.RoundTxid, bobNewVtxo.RoundTxid) } func TestUnilateralExit(t *testing.T) { From d623d651dc7d5f4a0125eb55b7bbe3f1f9e02cf1 Mon Sep 17 00:00:00 2001 From: louisinger Date: Wed, 22 Jan 2025 16:01:09 +0100 Subject: [PATCH 14/21] fix e2e test --- server/test/e2e/covenantless/e2e_test.go | 32 ++++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/server/test/e2e/covenantless/e2e_test.go b/server/test/e2e/covenantless/e2e_test.go index 494701415..3432477b6 100644 --- a/server/test/e2e/covenantless/e2e_test.go +++ b/server/test/e2e/covenantless/e2e_test.go @@ -104,22 +104,6 @@ func TestSettleInSameRound(t *testing.T) { time.Sleep(5 * time.Second) - aliceOffchainAddr, _, err := alice.Receive(ctx) - require.NoError(t, err) - - bobOffchainAddr, _, err := bob.Receive(ctx) - require.NoError(t, err) - - // Alice sends to Bob - _, err = alice.SendOffChain(ctx, false, []arksdk.Receiver{arksdk.NewBitcoinReceiver(bobOffchainAddr, 5000)}) - require.NoError(t, err) - - // Bob sends to Alice - _, err = bob.SendOffChain(ctx, false, []arksdk.Receiver{arksdk.NewBitcoinReceiver(aliceOffchainAddr, 3000)}) - require.NoError(t, err) - - time.Sleep(2 * time.Second) - var wg sync.WaitGroup wg.Add(2) @@ -154,6 +138,22 @@ func TestSettleInSameRound(t *testing.T) { require.NoError(t, err) require.NotEmpty(t, bobVtxos) + aliceOffchainAddr, _, err := alice.Receive(ctx) + require.NoError(t, err) + + bobOffchainAddr, _, err := bob.Receive(ctx) + require.NoError(t, err) + + // Alice sends to Bob + _, err = alice.SendOffChain(ctx, false, []arksdk.Receiver{arksdk.NewBitcoinReceiver(bobOffchainAddr, 5000)}) + require.NoError(t, err) + + // Bob sends to Alice + _, err = bob.SendOffChain(ctx, false, []arksdk.Receiver{arksdk.NewBitcoinReceiver(aliceOffchainAddr, 3000)}) + require.NoError(t, err) + + time.Sleep(2 * time.Second) + wg.Add(2) var aliceSecondRoundID, bobSecondRoundID string From 33df7ce7fecca41e82626e672f7f58b1cc0d0e6f Mon Sep 17 00:00:00 2001 From: louisinger Date: Wed, 29 Jan 2025 13:41:02 +0100 Subject: [PATCH 15/21] rename congestion_tree.go -> vtxo_tree.go --- common/tree/{congestion_tree.go => vtxo_tree.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename common/tree/{congestion_tree.go => vtxo_tree.go} (100%) diff --git a/common/tree/congestion_tree.go b/common/tree/vtxo_tree.go similarity index 100% rename from common/tree/congestion_tree.go rename to common/tree/vtxo_tree.go From 417cfa02f57c2c1f8202fb371e0258a034bba622 Mon Sep 17 00:00:00 2001 From: Louis Singer <41042567+louisinger@users.noreply.github.com> Date: Wed, 29 Jan 2025 15:09:36 +0100 Subject: [PATCH 16/21] Update common/bitcointree/builder.go Co-authored-by: Pietralberto Mazza <18440657+altafan@users.noreply.github.com> Signed-off-by: Louis Singer <41042567+louisinger@users.noreply.github.com> --- common/bitcointree/builder.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/bitcointree/builder.go b/common/bitcointree/builder.go index b99b4627c..9ade0ae24 100644 --- a/common/bitcointree/builder.go +++ b/common/bitcointree/builder.go @@ -244,7 +244,7 @@ func createRootNode( cosignersALL := make([]*secp256k1.PublicKey, 0) for _, r := range receivers { if r.Musig2Data == nil { - return nil, fmt.Errorf("musig2 data is nil for %s", r.PubKey) + return nil, fmt.Errorf("missing musig2 data for receiver %s", r.PubKey) } if r.Musig2Data.SigningType != tree.SignAll { From 942b726681d7b6e486712bbe491cd43cabfa9678 Mon Sep 17 00:00:00 2001 From: Louis Singer <41042567+louisinger@users.noreply.github.com> Date: Wed, 29 Jan 2025 15:09:47 +0100 Subject: [PATCH 17/21] Update common/bitcointree/builder.go Co-authored-by: Pietralberto Mazza <18440657+altafan@users.noreply.github.com> Signed-off-by: Louis Singer <41042567+louisinger@users.noreply.github.com> --- common/bitcointree/builder.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/bitcointree/builder.go b/common/bitcointree/builder.go index 9ade0ae24..a4c2a2d57 100644 --- a/common/bitcointree/builder.go +++ b/common/bitcointree/builder.go @@ -252,7 +252,7 @@ func createRootNode( } if len(r.Musig2Data.CosignersPublicKeys) == 0 { - return nil, fmt.Errorf("cosigners public keys for %s are empty", r.PubKey) + return nil, fmt.Errorf("missing cosigners public keys for receiver %s", r.PubKey) } for _, cosigner := range r.Musig2Data.CosignersPublicKeys { From a028443d7fad11235da900c5697759e0d077bda9 Mon Sep 17 00:00:00 2001 From: louisinger Date: Thu, 30 Jan 2025 10:56:25 +0100 Subject: [PATCH 18/21] fix musig2_test.go --- common/bitcointree/musig2_test.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/common/bitcointree/musig2_test.go b/common/bitcointree/musig2_test.go index 9b97f27bc..2009d21b0 100644 --- a/common/bitcointree/musig2_test.go +++ b/common/bitcointree/musig2_test.go @@ -39,12 +39,13 @@ func TestBuildAndSignVtxoTree(t *testing.T) { for _, tc := range generateTestCases(t) { t.Run(tc.name, func(t *testing.T) { - _, sharedOutputAmount, err := bitcointree.CraftSharedOutput( + sharedOutputScript, sharedOutputAmount, err := bitcointree.CraftSharedOutput( tc.receivers, minRelayFee, sweepRoot[:], ) require.NoError(t, err) + require.NotNil(t, sharedOutputScript) vtxoTree, err := bitcointree.BuildVtxoTree( &wire.OutPoint{ @@ -69,13 +70,15 @@ func TestBuildAndSignVtxoTree(t *testing.T) { signerSessions := make(map[*btcec.PublicKey]bitcointree.SignerSession) for _, prvkey := range tc.privKeys { session := bitcointree.NewTreeSignerSession(prvkey) - require.NoError(t, session.Init(sweepRoot[:], sharedOutputAmount, vtxoTree)) + err := session.Init(sweepRoot[:], sharedOutputAmount, vtxoTree) + require.NoError(t, err) signerSessions[prvkey.PubKey()] = session } - // ddd server's signer session + // Create server's signer session serverSession := bitcointree.NewTreeSignerSession(serverPrivKey) - require.NoError(t, serverSession.Init(sweepRoot[:], sharedOutputAmount, vtxoTree)) + err = serverSession.Init(sweepRoot[:], sharedOutputAmount, vtxoTree) + require.NoError(t, err) signerSessions[serverPrivKey.PubKey()] = serverSession // generate nonces from all signers @@ -108,6 +111,7 @@ func TestBuildAndSignVtxoTree(t *testing.T) { for pubkey, session := range signerSessions { sig, err := session.Sign() require.NoError(t, err) + require.NotNil(t, sig) var encodedSig bytes.Buffer err = sig.Encode(&encodedSig) require.NoError(t, err) @@ -129,7 +133,7 @@ func TestBuildAndSignVtxoTree(t *testing.T) { // aggregate signatures signedTree, err := serverCoordinator.SignTree() require.NoError(t, err) - + require.NotNil(t, signedTree) // validate signatures err = bitcointree.ValidateTreeSigs( sweepRoot[:], From 640647b88132b6297480200a6aaa65d1f3ffee14 Mon Sep 17 00:00:00 2001 From: louisinger Date: Thu, 30 Jan 2025 11:01:04 +0100 Subject: [PATCH 19/21] move musig2data setter to update --- server/internal/core/application/covenant.go | 2 +- .../internal/core/application/covenantless.go | 9 +++++---- server/internal/core/application/utils.go | 17 +++-------------- 3 files changed, 9 insertions(+), 19 deletions(-) diff --git a/server/internal/core/application/covenant.go b/server/internal/core/application/covenant.go index eb211941d..e0db70fc8 100644 --- a/server/internal/core/application/covenant.go +++ b/server/internal/core/application/covenant.go @@ -364,7 +364,7 @@ func (s *covenantService) ClaimVtxos(ctx context.Context, creds string, receiver if err := request.AddReceivers(receivers); err != nil { return err } - return s.txRequests.update(*request) + return s.txRequests.update(*request, nil) } func (s *covenantService) UpdateTxRequestStatus(_ context.Context, id string) error { diff --git a/server/internal/core/application/covenantless.go b/server/internal/core/application/covenantless.go index 9cb4e8afa..a7edeadb1 100644 --- a/server/internal/core/application/covenantless.go +++ b/server/internal/core/application/covenantless.go @@ -712,6 +712,8 @@ func (s *covenantlessService) ClaimVtxos(ctx context.Context, creds string, rece } } + var data *tree.Musig2 + if hasOffChainReceiver { if musig2Data == nil { return fmt.Errorf("musig2 data is required for offchain receivers") @@ -725,15 +727,14 @@ func (s *covenantlessService) ClaimVtxos(ctx context.Context, creds string, rece } } - if err := s.txRequests.addMusig2Data(request.Id, musig2Data); err != nil { - return fmt.Errorf("failed to add musig2 data: %s", err) - } + data = musig2Data } if err := request.AddReceivers(receivers); err != nil { return err } - return s.txRequests.update(*request) + + return s.txRequests.update(*request, data) } func (s *covenantlessService) UpdateTxRequestStatus(_ context.Context, id string) error { diff --git a/server/internal/core/application/utils.go b/server/internal/core/application/utils.go index 97a3df35c..17769aa73 100644 --- a/server/internal/core/application/utils.go +++ b/server/internal/core/application/utils.go @@ -144,7 +144,7 @@ func (m *txRequestsQueue) pop(num int64) ([]domain.TxRequest, []ports.BoardingIn return requests, boardingInputs, notes, musig2Data } -func (m *txRequestsQueue) update(request domain.TxRequest) error { +func (m *txRequestsQueue) update(request domain.TxRequest, musig2Data *tree.Musig2) error { m.lock.Lock() defer m.lock.Unlock() @@ -179,20 +179,9 @@ func (m *txRequestsQueue) update(request domain.TxRequest) error { r.TxRequest = request - return nil -} - -func (m *txRequestsQueue) addMusig2Data(id string, data *tree.Musig2) error { - m.lock.Lock() - defer m.lock.Unlock() - - r, ok := m.requests[id] - if !ok { - return fmt.Errorf("tx request %s not found", id) + if musig2Data != nil { + r.musig2Data = musig2Data } - - r.musig2Data = data - m.requests[id] = r return nil } From ed8157366b8bcfd30f38c2a5eaa46880d9432da9 Mon Sep 17 00:00:00 2001 From: louisinger Date: Thu, 30 Jan 2025 11:23:03 +0100 Subject: [PATCH 20/21] fix e2e_test.go --- server/test/e2e/covenantless/e2e_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/test/e2e/covenantless/e2e_test.go b/server/test/e2e/covenantless/e2e_test.go index d2464e7c9..1c9026f2b 100644 --- a/server/test/e2e/covenantless/e2e_test.go +++ b/server/test/e2e/covenantless/e2e_test.go @@ -145,11 +145,11 @@ func TestSettleInSameRound(t *testing.T) { require.NoError(t, err) // Alice sends to Bob - _, err = alice.SendOffChain(ctx, false, []arksdk.Receiver{arksdk.NewBitcoinReceiver(bobOffchainAddr, 5000)}) + _, err = alice.SendOffChain(ctx, false, []arksdk.Receiver{arksdk.NewBitcoinReceiver(bobOffchainAddr, 5000)}, false) require.NoError(t, err) // Bob sends to Alice - _, err = bob.SendOffChain(ctx, false, []arksdk.Receiver{arksdk.NewBitcoinReceiver(aliceOffchainAddr, 3000)}) + _, err = bob.SendOffChain(ctx, false, []arksdk.Receiver{arksdk.NewBitcoinReceiver(aliceOffchainAddr, 3000)}, false) require.NoError(t, err) time.Sleep(2 * time.Second) From 17564f876c6c86fdafe3bd2f0c163e81d503100d Mon Sep 17 00:00:00 2001 From: Pietralberto Mazza <18440657+altafan@users.noreply.github.com> Date: Thu, 30 Jan 2025 13:31:12 +0100 Subject: [PATCH 21/21] Improve readability of musig2 test (#8) --- common/bitcointree/musig2.go | 4 +- common/bitcointree/musig2_test.go | 310 +++++++++++------- .../internal/core/application/covenantless.go | 4 +- 3 files changed, 188 insertions(+), 130 deletions(-) diff --git a/common/bitcointree/musig2.go b/common/bitcointree/musig2.go index b9154d96c..1be78e1fd 100644 --- a/common/bitcointree/musig2.go +++ b/common/bitcointree/musig2.go @@ -91,7 +91,7 @@ type SignerSession interface { type CoordinatorSession interface { AddNonce(*btcec.PublicKey, TreeNonces) - AddSig(*btcec.PublicKey, TreePartialSigs) + AddSignatures(*btcec.PublicKey, TreePartialSigs) AggregateNonces() (TreeNonces, error) // SignTree combines the signatures and add them to the tree's psbts SignTree() (tree.VtxoTree, error) @@ -420,7 +420,7 @@ func (t *treeCoordinatorSession) AddNonce(pubkey *btcec.PublicKey, nonce TreeNon t.nonces[hex.EncodeToString(schnorr.SerializePubKey(pubkey))] = nonce } -func (t *treeCoordinatorSession) AddSig(pubkey *btcec.PublicKey, sig TreePartialSigs) { +func (t *treeCoordinatorSession) AddSignatures(pubkey *btcec.PublicKey, sig TreePartialSigs) { t.sigs[hex.EncodeToString(schnorr.SerializePubKey(pubkey))] = sig } diff --git a/common/bitcointree/musig2_test.go b/common/bitcointree/musig2_test.go index 2009d21b0..fa6fbe8ad 100644 --- a/common/bitcointree/musig2_test.go +++ b/common/bitcointree/musig2_test.go @@ -10,10 +10,8 @@ import ( "github.com/ark-network/ark/common/bitcointree" "github.com/ark-network/ark/common/tree" "github.com/btcsuite/btcd/btcec/v2" - "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/stretchr/testify/require" ) @@ -24,10 +22,10 @@ const ( var ( vtxoTreeExpiry = common.RelativeLocktime{Type: common.LocktimeTypeBlock, Value: 144} - testTxid, _ = chainhash.NewHashFromStr("49f8664acc899be91902f8ade781b7eeb9cbe22bdd9efbc36e56195de21bcd12") - serverPrivKey, _ = secp256k1.GeneratePrivateKey() + rootInput, _ = wire.NewOutPointFromString("49f8664acc899be91902f8ade781b7eeb9cbe22bdd9efbc36e56195de21bcd12:0") + serverPrivKey, _ = btcec.NewPrivateKey() sweepScript, _ = (&tree.CSVMultisigClosure{ - MultisigClosure: tree.MultisigClosure{PubKeys: []*secp256k1.PublicKey{serverPrivKey.PubKey()}}, + MultisigClosure: tree.MultisigClosure{PubKeys: []*btcec.PublicKey{serverPrivKey.PubKey()}}, Locktime: vtxoTreeExpiry, }).Script() sweepRoot = txscript.NewBaseTapLeaf(sweepScript).TapHash() @@ -37,125 +35,214 @@ var ( func TestBuildAndSignVtxoTree(t *testing.T) { t.Parallel() - for _, tc := range generateTestCases(t) { - t.Run(tc.name, func(t *testing.T) { - sharedOutputScript, sharedOutputAmount, err := bitcointree.CraftSharedOutput( - tc.receivers, - minRelayFee, - sweepRoot[:], + testVectors, err := makeTestVectors() + require.NoError(t, err) + require.NotEmpty(t, testVectors) + + for _, v := range testVectors { + t.Run(v.name, func(t *testing.T) { + sharedOutScript, sharedOutAmount, err := bitcointree.CraftSharedOutput( + v.receivers, minRelayFee, sweepRoot[:], ) require.NoError(t, err) - require.NotNil(t, sharedOutputScript) + require.NotNil(t, sharedOutScript) + require.NotZero(t, sharedOutAmount) vtxoTree, err := bitcointree.BuildVtxoTree( - &wire.OutPoint{ - Hash: *testTxid, - Index: 0, - }, - tc.receivers, - minRelayFee, - sweepRoot[:], - vtxoTreeExpiry, + rootInput, v.receivers, minRelayFee, sweepRoot[:], vtxoTreeExpiry, ) require.NoError(t, err) + require.NotNil(t, vtxoTree) - serverCoordinator, err := bitcointree.NewTreeCoordinatorSession( - sharedOutputAmount, - vtxoTree, - sweepRoot[:], + coordinator, err := bitcointree.NewTreeCoordinatorSession( + sharedOutAmount, vtxoTree, sweepRoot[:], ) require.NoError(t, err) + require.NotNil(t, coordinator) - // Cceate signer sessions for each receivers - signerSessions := make(map[*btcec.PublicKey]bitcointree.SignerSession) - for _, prvkey := range tc.privKeys { - session := bitcointree.NewTreeSignerSession(prvkey) - err := session.Init(sweepRoot[:], sharedOutputAmount, vtxoTree) - require.NoError(t, err) - signerSessions[prvkey.PubKey()] = session - } + signers, err := makeCosigners(v.privKeys, sharedOutAmount, vtxoTree) + require.NoError(t, err) + require.NotNil(t, signers) - // Create server's signer session - serverSession := bitcointree.NewTreeSignerSession(serverPrivKey) - err = serverSession.Init(sweepRoot[:], sharedOutputAmount, vtxoTree) + err = makeAggregatedNonces(signers, coordinator, checkNoncesRoundtrip(t)) require.NoError(t, err) - signerSessions[serverPrivKey.PubKey()] = serverSession - - // generate nonces from all signers - for pubkey, session := range signerSessions { - nonces, err := session.GetNonces() - require.NoError(t, err) - var encodedNonces bytes.Buffer - err = nonces.Encode(&encodedNonces) - require.NoError(t, err) - decodedNonces, err := bitcointree.DecodeNonces(&encodedNonces) - require.NoError(t, err) - for i, nonceRow := range nonces { - for j, nonce := range nonceRow { - require.Equal(t, nonce, decodedNonces[i][j]) - } - } - serverCoordinator.AddNonce(pubkey, nonces) - } + signedTree, err := makeAggregatedSignatures(signers, coordinator, checkSigsRoundtrip(t)) + require.NoError(t, err) + require.NotNil(t, signedTree) - aggregatedNonce, err := serverCoordinator.AggregateNonces() + // validate signatures + err = bitcointree.ValidateTreeSigs(sweepRoot[:], sharedOutAmount, signedTree) require.NoError(t, err) + }) + } +} + +func checkNoncesRoundtrip(t *testing.T) func(nonces bitcointree.TreeNonces) { + return func(nonces bitcointree.TreeNonces) { + var encodedNonces bytes.Buffer + err := nonces.Encode(&encodedNonces) + require.NoError(t, err) - // set the aggregated nonces for all signers sessions - for _, session := range signerSessions { - session.SetAggregatedNonces(aggregatedNonce) + decodedNonces, err := bitcointree.DecodeNonces(&encodedNonces) + require.NoError(t, err) + for i, nonceRow := range nonces { + for j, nonce := range nonceRow { + require.Equal(t, nonce, decodedNonces[i][j]) } + } + } +} - // get signatures from all signers sessions - for pubkey, session := range signerSessions { - sig, err := session.Sign() - require.NoError(t, err) - require.NotNil(t, sig) - var encodedSig bytes.Buffer - err = sig.Encode(&encodedSig) - require.NoError(t, err) - decodedSig, err := bitcointree.DecodeSignatures(&encodedSig) - require.NoError(t, err) - for i, sigRow := range sig { - for j, sig := range sigRow { - if sig == nil { - require.Nil(t, decodedSig[i][j]) - } else { - require.Equal(t, sig.S, decodedSig[i][j].S) - } - } +func checkSigsRoundtrip(t *testing.T) func(sigs bitcointree.TreePartialSigs) { + return func(sigs bitcointree.TreePartialSigs) { + var encodedSig bytes.Buffer + err := sigs.Encode(&encodedSig) + require.NoError(t, err) + decodedSig, err := bitcointree.DecodeSignatures(&encodedSig) + require.NoError(t, err) + for i, sigRow := range sigs { + for j, sig := range sigRow { + if sig == nil { + require.Nil(t, decodedSig[i][j]) + } else { + require.Equal(t, sig.S, decodedSig[i][j].S) } - - serverCoordinator.AddSig(pubkey, sig) } + } + } +} - // aggregate signatures - signedTree, err := serverCoordinator.SignTree() - require.NoError(t, err) - require.NotNil(t, signedTree) - // validate signatures - err = bitcointree.ValidateTreeSigs( - sweepRoot[:], - sharedOutputAmount, - signedTree, - ) - require.NoError(t, err) - }) +func makeCosigners( + keys []*btcec.PrivateKey, sharedOutAmount int64, vtxoTree tree.VtxoTree, +) (map[string]bitcointree.SignerSession, error) { + signers := make(map[string]bitcointree.SignerSession) + for _, prvkey := range keys { + session := bitcointree.NewTreeSignerSession(prvkey) + if err := session.Init(sweepRoot[:], sharedOutAmount, vtxoTree); err != nil { + return nil, err + } + signers[keyToStr(prvkey)] = session + } + + // create signer session for the server itself + serverSession := bitcointree.NewTreeSignerSession(serverPrivKey) + if err := serverSession.Init(sweepRoot[:], sharedOutAmount, vtxoTree); err != nil { + return nil, err + } + signers[keyToStr(serverPrivKey)] = serverSession + return signers, nil +} + +func makeAggregatedNonces( + signers map[string]bitcointree.SignerSession, coordinator bitcointree.CoordinatorSession, + checkNoncesRoundtrip func(bitcointree.TreeNonces), +) error { + for pk, session := range signers { + buf, err := hex.DecodeString(pk) + if err != nil { + return err + } + pubkey, err := btcec.ParsePubKey(buf) + if err != nil { + return err + } + + nonces, err := session.GetNonces() + if err != nil { + return err + } + checkNoncesRoundtrip(nonces) + + coordinator.AddNonce(pubkey, nonces) + } + + aggregatedNonce, err := coordinator.AggregateNonces() + if err != nil { + return err + } + + // set the aggregated nonces for all signers sessions + for _, session := range signers { + session.SetAggregatedNonces(aggregatedNonce) + } + return nil +} + +func makeAggregatedSignatures( + signers map[string]bitcointree.SignerSession, coordinator bitcointree.CoordinatorSession, + checkSigsRoundtrip func(bitcointree.TreePartialSigs), +) (tree.VtxoTree, error) { + for pk, session := range signers { + buf, err := hex.DecodeString(pk) + if err != nil { + return nil, err + } + pubkey, err := btcec.ParsePubKey(buf) + if err != nil { + return nil, err + } + + sigs, err := session.Sign() + if err != nil { + return nil, err + } + checkSigsRoundtrip(sigs) + + coordinator.AddSignatures(pubkey, sigs) } + + // aggregate signatures + return coordinator.SignTree() } type testCase struct { name string receivers []tree.VtxoLeaf - privKeys []*secp256k1.PrivateKey + privKeys []*btcec.PrivateKey +} + +func makeTestVectors() ([]testCase, error) { + vectors := make([]testCase, 0, len(receiverCounts)) + for _, count := range receiverCounts { + receivers, privKeys, err := generateMockedReceivers(count) + if err != nil { + return nil, err + } + + // add mixed types test case if count is between 2 and 32 + if count > 1 && count < 32 { + vectors = append(vectors, testCase{ + name: fmt.Sprintf("%d receivers Mixed Signing Types", len(receivers)), + receivers: withMixedSigningTypes(receivers), + privKeys: privKeys, + }) + } + + // add SignAll test case if count is less than 32 + if count < 32 { + vectors = append(vectors, testCase{ + name: fmt.Sprintf("%d receivers SignAll", len(receivers)), + receivers: withSigningType(tree.SignAll, receivers), + privKeys: privKeys, + }) + } + + // always add SignBranch test case + vectors = append(vectors, testCase{ + name: fmt.Sprintf("%d receivers SignBranch", len(receivers)), + receivers: withSigningType(tree.SignBranch, receivers), + privKeys: privKeys, + }) + } + return vectors, nil } -func generateReceiversFixture(count int) ([]tree.VtxoLeaf, []*secp256k1.PrivateKey, error) { - receivers := make([]tree.VtxoLeaf, 0, count) - privKeys := make([]*secp256k1.PrivateKey, 0, count) - for i := 0; i < count; i++ { - prvkey, err := secp256k1.GeneratePrivateKey() +func generateMockedReceivers(num int) ([]tree.VtxoLeaf, []*btcec.PrivateKey, error) { + receivers := make([]tree.VtxoLeaf, 0, num) + privKeys := make([]*btcec.PrivateKey, 0, num) + for i := 0; i < num; i++ { + prvkey, err := btcec.NewPrivateKey() if err != nil { return nil, nil, err } @@ -196,35 +283,6 @@ func withMixedSigningTypes(receivers []tree.VtxoLeaf) []tree.VtxoLeaf { return append(first, second...) } -func generateTestCases(t *testing.T) []testCase { - testCases := make([]testCase, 0) - for _, count := range receiverCounts { - receivers, privKeys, err := generateReceiversFixture(count) - require.NoError(t, err) - // add mixed types test case if count is between 2 and 32 - if count > 1 && count < 32 { - testCases = append(testCases, testCase{ - name: fmt.Sprintf("%d receivers Mixed Signing Types", len(receivers)), - receivers: withMixedSigningTypes(receivers), - privKeys: privKeys, - }) - } - - // add SignAll test case if count is less than 32 - if count < 32 { - testCases = append(testCases, testCase{ - name: fmt.Sprintf("%d receivers SignAll", len(receivers)), - receivers: withSigningType(tree.SignAll, receivers), - privKeys: privKeys, - }) - } - - // always add SignBranch test case - testCases = append(testCases, testCase{ - name: fmt.Sprintf("%d receivers SignBranch", len(receivers)), - receivers: withSigningType(tree.SignBranch, receivers), - privKeys: privKeys, - }) - } - return testCases +func keyToStr(key *btcec.PrivateKey) string { + return hex.EncodeToString(key.PubKey().SerializeCompressed()) } diff --git a/server/internal/core/application/covenantless.go b/server/internal/core/application/covenantless.go index 2d4f72220..bd824d5b3 100644 --- a/server/internal/core/application/covenantless.go +++ b/server/internal/core/application/covenantless.go @@ -1205,7 +1205,7 @@ func (s *covenantlessService) startFinalization() { log.WithError(err).Warn("failed to sign tree") return } - coordinator.AddSig(s.serverSigningPubKey, serverTreeSigs) + coordinator.AddSignatures(s.serverSigningPubKey, serverTreeSigs) log.Debugf("tree signed by us for round %s", round.Id) @@ -1221,7 +1221,7 @@ func (s *covenantlessService) startFinalization() { case <-signingSession.sigDoneC: signaturesTimer.Stop() for pubkey, sig := range signingSession.signatures { - coordinator.AddSig(pubkey, sig) + coordinator.AddSignatures(pubkey, sig) } }