mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-03-28 10:41:57 +01:00
Merge pull request #6495 from guggero/musig2-session-cleanup
MuSig2: Add session cleanup RPC
This commit is contained in:
commit
48695dd801
docs/release-notes
input
lnrpc/signrpc
signer.pb.gosigner.pb.gw.gosigner.pb.json.gosigner.protosigner.swagger.jsonsigner.yamlsigner_grpc.pb.gosigner_server.go
lntest
lnwallet
watchtower/wtmock
@ -224,6 +224,10 @@ from occurring that would result in an erroneous force close.](https://github.co
|
||||
* [Clarify comment](https://github.com/lightningnetwork/lnd/pull/6481) on
|
||||
`chainnotifier.RegisterConfirmationsNtfn`.
|
||||
|
||||
* [The experimental MuSig2 API now also has a `MuSig2Cleanup` RPC that allows
|
||||
the in-memory state to be cleaned up early if a session isn't expected to
|
||||
succeed anymore](https://github.com/lightningnetwork/lnd/pull/6495).
|
||||
|
||||
## RPC Server
|
||||
|
||||
* [Add value to the field
|
||||
|
@ -58,6 +58,9 @@ type MuSig2Signer interface {
|
||||
// returned.
|
||||
MuSig2CombineSig(MuSig2SessionID,
|
||||
[]*musig2.PartialSignature) (*schnorr.Signature, bool, error)
|
||||
|
||||
// MuSig2Cleanup removes a session from memory to free up resources.
|
||||
MuSig2Cleanup(MuSig2SessionID) error
|
||||
}
|
||||
|
||||
// MuSig2SessionInfo is a struct for keeping track of a signing session
|
||||
|
@ -178,6 +178,11 @@ func (m *MockSigner) MuSig2CombineSig(MuSig2SessionID,
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
// MuSig2Cleanup removes a session from memory to free up resources.
|
||||
func (m *MockSigner) MuSig2Cleanup(MuSig2SessionID) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// findKey searches through all stored private keys and returns one
|
||||
// corresponding to the hashed pubkey if it can be found. The public key may
|
||||
// either correspond directly to the private key or to the private key with a
|
||||
|
@ -1743,6 +1743,93 @@ func (x *MuSig2CombineSigResponse) GetFinalSignature() []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
type MuSig2CleanupRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
//
|
||||
//The unique ID of the signing session that should be removed/cleaned up.
|
||||
SessionId []byte `protobuf:"bytes,1,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"`
|
||||
}
|
||||
|
||||
func (x *MuSig2CleanupRequest) Reset() {
|
||||
*x = MuSig2CleanupRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_signrpc_signer_proto_msgTypes[26]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *MuSig2CleanupRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*MuSig2CleanupRequest) ProtoMessage() {}
|
||||
|
||||
func (x *MuSig2CleanupRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_signrpc_signer_proto_msgTypes[26]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use MuSig2CleanupRequest.ProtoReflect.Descriptor instead.
|
||||
func (*MuSig2CleanupRequest) Descriptor() ([]byte, []int) {
|
||||
return file_signrpc_signer_proto_rawDescGZIP(), []int{26}
|
||||
}
|
||||
|
||||
func (x *MuSig2CleanupRequest) GetSessionId() []byte {
|
||||
if x != nil {
|
||||
return x.SessionId
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type MuSig2CleanupResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
}
|
||||
|
||||
func (x *MuSig2CleanupResponse) Reset() {
|
||||
*x = MuSig2CleanupResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_signrpc_signer_proto_msgTypes[27]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *MuSig2CleanupResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*MuSig2CleanupResponse) ProtoMessage() {}
|
||||
|
||||
func (x *MuSig2CleanupResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_signrpc_signer_proto_msgTypes[27]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use MuSig2CleanupResponse.ProtoReflect.Descriptor instead.
|
||||
func (*MuSig2CleanupResponse) Descriptor() ([]byte, []int) {
|
||||
return file_signrpc_signer_proto_rawDescGZIP(), []int{27}
|
||||
}
|
||||
|
||||
var File_signrpc_signer_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_signrpc_signer_proto_rawDesc = []byte{
|
||||
@ -1937,7 +2024,12 @@ var file_signrpc_signer_proto_rawDesc = []byte{
|
||||
0x52, 0x11, 0x68, 0x61, 0x76, 0x65, 0x41, 0x6c, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75,
|
||||
0x72, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x69, 0x67,
|
||||
0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x66, 0x69,
|
||||
0x6e, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x32, 0x8b, 0x06, 0x0a,
|
||||
0x6e, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x35, 0x0a, 0x14,
|
||||
0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f,
|
||||
0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x49, 0x64, 0x22, 0x17, 0x0a, 0x15, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x6c, 0x65,
|
||||
0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xdb, 0x06, 0x0a,
|
||||
0x06, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12, 0x34, 0x0a, 0x0d, 0x53, 0x69, 0x67, 0x6e, 0x4f,
|
||||
0x75, 0x74, 0x70, 0x75, 0x74, 0x52, 0x61, 0x77, 0x12, 0x10, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72,
|
||||
0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x11, 0x2e, 0x73, 0x69, 0x67,
|
||||
@ -1986,7 +2078,12 @@ var file_signrpc_signer_proto_rawDesc = []byte{
|
||||
0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x53, 0x69, 0x67,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70,
|
||||
0x63, 0x2e, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x53,
|
||||
0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x69,
|
||||
0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x4d, 0x75,
|
||||
0x53, 0x69, 0x67, 0x32, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x12, 0x1d, 0x2e, 0x73, 0x69,
|
||||
0x67, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x6c, 0x65, 0x61,
|
||||
0x6e, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x73, 0x69, 0x67,
|
||||
0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x75, 0x53, 0x69, 0x67, 0x32, 0x43, 0x6c, 0x65, 0x61, 0x6e,
|
||||
0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x69,
|
||||
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69,
|
||||
0x6e, 0x67, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x6c, 0x6e, 0x64, 0x2f, 0x6c, 0x6e,
|
||||
0x72, 0x70, 0x63, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
||||
@ -2005,7 +2102,7 @@ func file_signrpc_signer_proto_rawDescGZIP() []byte {
|
||||
return file_signrpc_signer_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_signrpc_signer_proto_msgTypes = make([]protoimpl.MessageInfo, 26)
|
||||
var file_signrpc_signer_proto_msgTypes = make([]protoimpl.MessageInfo, 28)
|
||||
var file_signrpc_signer_proto_goTypes = []interface{}{
|
||||
(*KeyLocator)(nil), // 0: signrpc.KeyLocator
|
||||
(*KeyDescriptor)(nil), // 1: signrpc.KeyDescriptor
|
||||
@ -2033,6 +2130,8 @@ var file_signrpc_signer_proto_goTypes = []interface{}{
|
||||
(*MuSig2SignResponse)(nil), // 23: signrpc.MuSig2SignResponse
|
||||
(*MuSig2CombineSigRequest)(nil), // 24: signrpc.MuSig2CombineSigRequest
|
||||
(*MuSig2CombineSigResponse)(nil), // 25: signrpc.MuSig2CombineSigResponse
|
||||
(*MuSig2CleanupRequest)(nil), // 26: signrpc.MuSig2CleanupRequest
|
||||
(*MuSig2CleanupResponse)(nil), // 27: signrpc.MuSig2CleanupResponse
|
||||
}
|
||||
var file_signrpc_signer_proto_depIdxs = []int32{
|
||||
0, // 0: signrpc.KeyDescriptor.key_loc:type_name -> signrpc.KeyLocator
|
||||
@ -2059,18 +2158,20 @@ var file_signrpc_signer_proto_depIdxs = []int32{
|
||||
20, // 21: signrpc.Signer.MuSig2RegisterNonces:input_type -> signrpc.MuSig2RegisterNoncesRequest
|
||||
22, // 22: signrpc.Signer.MuSig2Sign:input_type -> signrpc.MuSig2SignRequest
|
||||
24, // 23: signrpc.Signer.MuSig2CombineSig:input_type -> signrpc.MuSig2CombineSigRequest
|
||||
5, // 24: signrpc.Signer.SignOutputRaw:output_type -> signrpc.SignResp
|
||||
7, // 25: signrpc.Signer.ComputeInputScript:output_type -> signrpc.InputScriptResp
|
||||
9, // 26: signrpc.Signer.SignMessage:output_type -> signrpc.SignMessageResp
|
||||
11, // 27: signrpc.Signer.VerifyMessage:output_type -> signrpc.VerifyMessageResp
|
||||
13, // 28: signrpc.Signer.DeriveSharedKey:output_type -> signrpc.SharedKeyResponse
|
||||
17, // 29: signrpc.Signer.MuSig2CombineKeys:output_type -> signrpc.MuSig2CombineKeysResponse
|
||||
19, // 30: signrpc.Signer.MuSig2CreateSession:output_type -> signrpc.MuSig2SessionResponse
|
||||
21, // 31: signrpc.Signer.MuSig2RegisterNonces:output_type -> signrpc.MuSig2RegisterNoncesResponse
|
||||
23, // 32: signrpc.Signer.MuSig2Sign:output_type -> signrpc.MuSig2SignResponse
|
||||
25, // 33: signrpc.Signer.MuSig2CombineSig:output_type -> signrpc.MuSig2CombineSigResponse
|
||||
24, // [24:34] is the sub-list for method output_type
|
||||
14, // [14:24] is the sub-list for method input_type
|
||||
26, // 24: signrpc.Signer.MuSig2Cleanup:input_type -> signrpc.MuSig2CleanupRequest
|
||||
5, // 25: signrpc.Signer.SignOutputRaw:output_type -> signrpc.SignResp
|
||||
7, // 26: signrpc.Signer.ComputeInputScript:output_type -> signrpc.InputScriptResp
|
||||
9, // 27: signrpc.Signer.SignMessage:output_type -> signrpc.SignMessageResp
|
||||
11, // 28: signrpc.Signer.VerifyMessage:output_type -> signrpc.VerifyMessageResp
|
||||
13, // 29: signrpc.Signer.DeriveSharedKey:output_type -> signrpc.SharedKeyResponse
|
||||
17, // 30: signrpc.Signer.MuSig2CombineKeys:output_type -> signrpc.MuSig2CombineKeysResponse
|
||||
19, // 31: signrpc.Signer.MuSig2CreateSession:output_type -> signrpc.MuSig2SessionResponse
|
||||
21, // 32: signrpc.Signer.MuSig2RegisterNonces:output_type -> signrpc.MuSig2RegisterNoncesResponse
|
||||
23, // 33: signrpc.Signer.MuSig2Sign:output_type -> signrpc.MuSig2SignResponse
|
||||
25, // 34: signrpc.Signer.MuSig2CombineSig:output_type -> signrpc.MuSig2CombineSigResponse
|
||||
27, // 35: signrpc.Signer.MuSig2Cleanup:output_type -> signrpc.MuSig2CleanupResponse
|
||||
25, // [25:36] is the sub-list for method output_type
|
||||
14, // [14:25] is the sub-list for method input_type
|
||||
14, // [14:14] is the sub-list for extension type_name
|
||||
14, // [14:14] is the sub-list for extension extendee
|
||||
0, // [0:14] is the sub-list for field type_name
|
||||
@ -2394,6 +2495,30 @@ func file_signrpc_signer_proto_init() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_signrpc_signer_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*MuSig2CleanupRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_signrpc_signer_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*MuSig2CleanupResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
@ -2401,7 +2526,7 @@ func file_signrpc_signer_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_signrpc_signer_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 26,
|
||||
NumMessages: 28,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
|
@ -371,6 +371,40 @@ func local_request_Signer_MuSig2CombineSig_0(ctx context.Context, marshaler runt
|
||||
|
||||
}
|
||||
|
||||
func request_Signer_MuSig2Cleanup_0(ctx context.Context, marshaler runtime.Marshaler, client SignerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq MuSig2CleanupRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.MuSig2Cleanup(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Signer_MuSig2Cleanup_0(ctx context.Context, marshaler runtime.Marshaler, server SignerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq MuSig2CleanupRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.MuSig2Cleanup(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
// RegisterSignerHandlerServer registers the http handlers for service Signer to "mux".
|
||||
// UnaryRPC :call SignerServer directly.
|
||||
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
|
||||
@ -607,6 +641,29 @@ func RegisterSignerHandlerServer(ctx context.Context, mux *runtime.ServeMux, ser
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_Signer_MuSig2Cleanup_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/signrpc.Signer/MuSig2Cleanup", runtime.WithHTTPPathPattern("/v2/signer/musig2/cleanup"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Signer_MuSig2Cleanup_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Signer_MuSig2Cleanup_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -848,6 +905,26 @@ func RegisterSignerHandlerClient(ctx context.Context, mux *runtime.ServeMux, cli
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_Signer_MuSig2Cleanup_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/signrpc.Signer/MuSig2Cleanup", runtime.WithHTTPPathPattern("/v2/signer/musig2/cleanup"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Signer_MuSig2Cleanup_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Signer_MuSig2Cleanup_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -871,6 +948,8 @@ var (
|
||||
pattern_Signer_MuSig2Sign_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v2", "signer", "musig2", "sign"}, ""))
|
||||
|
||||
pattern_Signer_MuSig2CombineSig_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v2", "signer", "musig2", "combinesig"}, ""))
|
||||
|
||||
pattern_Signer_MuSig2Cleanup_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v2", "signer", "musig2", "cleanup"}, ""))
|
||||
)
|
||||
|
||||
var (
|
||||
@ -893,4 +972,6 @@ var (
|
||||
forward_Signer_MuSig2Sign_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Signer_MuSig2CombineSig_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Signer_MuSig2Cleanup_0 = runtime.ForwardResponseMessage
|
||||
)
|
||||
|
@ -272,4 +272,29 @@ func RegisterSignerJSONCallbacks(registry map[string]func(ctx context.Context,
|
||||
}
|
||||
callback(string(respBytes), nil)
|
||||
}
|
||||
|
||||
registry["signrpc.Signer.MuSig2Cleanup"] = func(ctx context.Context,
|
||||
conn *grpc.ClientConn, reqJSON string, callback func(string, error)) {
|
||||
|
||||
req := &MuSig2CleanupRequest{}
|
||||
err := marshaler.Unmarshal([]byte(reqJSON), req)
|
||||
if err != nil {
|
||||
callback("", err)
|
||||
return
|
||||
}
|
||||
|
||||
client := NewSignerClient(conn)
|
||||
resp, err := client.MuSig2Cleanup(ctx, req)
|
||||
if err != nil {
|
||||
callback("", err)
|
||||
return
|
||||
}
|
||||
|
||||
respBytes, err := marshaler.Marshal(resp)
|
||||
if err != nil {
|
||||
callback("", err)
|
||||
return
|
||||
}
|
||||
callback(string(respBytes), nil)
|
||||
}
|
||||
}
|
||||
|
@ -132,6 +132,17 @@ service Signer {
|
||||
*/
|
||||
rpc MuSig2CombineSig (MuSig2CombineSigRequest)
|
||||
returns (MuSig2CombineSigResponse);
|
||||
|
||||
/*
|
||||
MuSig2Cleanup (experimental!) allows a caller to clean up a session early in
|
||||
cases where it's obvious that the signing session won't succeed and the
|
||||
resources can be released.
|
||||
|
||||
NOTE: The MuSig2 BIP is not final yet and therefore this API must be
|
||||
considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
||||
releases. Backward compatibility is not guaranteed!
|
||||
*/
|
||||
rpc MuSig2Cleanup (MuSig2CleanupRequest) returns (MuSig2CleanupResponse);
|
||||
}
|
||||
|
||||
message KeyLocator {
|
||||
@ -552,4 +563,14 @@ message MuSig2CombineSigResponse {
|
||||
The final, full signature that is valid for the combined public key.
|
||||
*/
|
||||
bytes final_signature = 2;
|
||||
}
|
||||
|
||||
message MuSig2CleanupRequest {
|
||||
/*
|
||||
The unique ID of the signing session that should be removed/cleaned up.
|
||||
*/
|
||||
bytes session_id = 1;
|
||||
}
|
||||
|
||||
message MuSig2CleanupResponse {
|
||||
}
|
@ -50,6 +50,40 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v2/signer/musig2/cleanup": {
|
||||
"post": {
|
||||
"summary": "MuSig2Cleanup (experimental!) allows a caller to clean up a session early in\ncases where it's obvious that the signing session won't succeed and the\nresources can be released.",
|
||||
"description": "NOTE: The MuSig2 BIP is not final yet and therefore this API must be\nconsidered to be HIGHLY EXPERIMENTAL and subject to change in upcoming\nreleases. Backward compatibility is not guaranteed!",
|
||||
"operationId": "Signer_MuSig2Cleanup",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/signrpcMuSig2CleanupResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/signrpcMuSig2CleanupRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Signer"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v2/signer/musig2/combinekeys": {
|
||||
"post": {
|
||||
"summary": "MuSig2CombineKeys (experimental!) is a stateless helper RPC that can be used\nto calculate the combined MuSig2 public key from a list of all participating\nsigners' public keys. This RPC is completely stateless and deterministic and\ndoes not create any signing session. It can be used to determine the Taproot\npublic key that should be put in an on-chain output once all public keys are\nknown. A signing session is only needed later when that output should be\n_spent_ again.",
|
||||
@ -446,6 +480,19 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"signrpcMuSig2CleanupRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"session_id": {
|
||||
"type": "string",
|
||||
"format": "byte",
|
||||
"description": "The unique ID of the signing session that should be removed/cleaned up."
|
||||
}
|
||||
}
|
||||
},
|
||||
"signrpcMuSig2CleanupResponse": {
|
||||
"type": "object"
|
||||
},
|
||||
"signrpcMuSig2CombineKeysRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -33,3 +33,6 @@ http:
|
||||
- selector: signrpc.Signer.MuSig2CombineSig
|
||||
post: "/v2/signer/musig2/combinesig"
|
||||
body: "*"
|
||||
- selector: signrpc.Signer.MuSig2Cleanup
|
||||
post: "/v2/signer/musig2/cleanup"
|
||||
body: "*"
|
||||
|
@ -120,6 +120,15 @@ type SignerClient interface {
|
||||
//considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
||||
//releases. Backward compatibility is not guaranteed!
|
||||
MuSig2CombineSig(ctx context.Context, in *MuSig2CombineSigRequest, opts ...grpc.CallOption) (*MuSig2CombineSigResponse, error)
|
||||
//
|
||||
//MuSig2Cleanup (experimental!) allows a caller to clean up a session early in
|
||||
//cases where it's obvious that the signing session won't succeed and the
|
||||
//resources can be released.
|
||||
//
|
||||
//NOTE: The MuSig2 BIP is not final yet and therefore this API must be
|
||||
//considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
||||
//releases. Backward compatibility is not guaranteed!
|
||||
MuSig2Cleanup(ctx context.Context, in *MuSig2CleanupRequest, opts ...grpc.CallOption) (*MuSig2CleanupResponse, error)
|
||||
}
|
||||
|
||||
type signerClient struct {
|
||||
@ -220,6 +229,15 @@ func (c *signerClient) MuSig2CombineSig(ctx context.Context, in *MuSig2CombineSi
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *signerClient) MuSig2Cleanup(ctx context.Context, in *MuSig2CleanupRequest, opts ...grpc.CallOption) (*MuSig2CleanupResponse, error) {
|
||||
out := new(MuSig2CleanupResponse)
|
||||
err := c.cc.Invoke(ctx, "/signrpc.Signer/MuSig2Cleanup", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// SignerServer is the server API for Signer service.
|
||||
// All implementations must embed UnimplementedSignerServer
|
||||
// for forward compatibility
|
||||
@ -326,6 +344,15 @@ type SignerServer interface {
|
||||
//considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
||||
//releases. Backward compatibility is not guaranteed!
|
||||
MuSig2CombineSig(context.Context, *MuSig2CombineSigRequest) (*MuSig2CombineSigResponse, error)
|
||||
//
|
||||
//MuSig2Cleanup (experimental!) allows a caller to clean up a session early in
|
||||
//cases where it's obvious that the signing session won't succeed and the
|
||||
//resources can be released.
|
||||
//
|
||||
//NOTE: The MuSig2 BIP is not final yet and therefore this API must be
|
||||
//considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming
|
||||
//releases. Backward compatibility is not guaranteed!
|
||||
MuSig2Cleanup(context.Context, *MuSig2CleanupRequest) (*MuSig2CleanupResponse, error)
|
||||
mustEmbedUnimplementedSignerServer()
|
||||
}
|
||||
|
||||
@ -363,6 +390,9 @@ func (UnimplementedSignerServer) MuSig2Sign(context.Context, *MuSig2SignRequest)
|
||||
func (UnimplementedSignerServer) MuSig2CombineSig(context.Context, *MuSig2CombineSigRequest) (*MuSig2CombineSigResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method MuSig2CombineSig not implemented")
|
||||
}
|
||||
func (UnimplementedSignerServer) MuSig2Cleanup(context.Context, *MuSig2CleanupRequest) (*MuSig2CleanupResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method MuSig2Cleanup not implemented")
|
||||
}
|
||||
func (UnimplementedSignerServer) mustEmbedUnimplementedSignerServer() {}
|
||||
|
||||
// UnsafeSignerServer may be embedded to opt out of forward compatibility for this service.
|
||||
@ -556,6 +586,24 @@ func _Signer_MuSig2CombineSig_Handler(srv interface{}, ctx context.Context, dec
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Signer_MuSig2Cleanup_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(MuSig2CleanupRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SignerServer).MuSig2Cleanup(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/signrpc.Signer/MuSig2Cleanup",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SignerServer).MuSig2Cleanup(ctx, req.(*MuSig2CleanupRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// Signer_ServiceDesc is the grpc.ServiceDesc for Signer service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
@ -603,6 +651,10 @@ var Signer_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "MuSig2CombineSig",
|
||||
Handler: _Signer_MuSig2CombineSig_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "MuSig2Cleanup",
|
||||
Handler: _Signer_MuSig2Cleanup_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "signrpc/signer.proto",
|
||||
|
@ -92,6 +92,10 @@ var (
|
||||
Entity: "signer",
|
||||
Action: "generate",
|
||||
}},
|
||||
"/signrpc.Signer/MuSig2Cleanup": {{
|
||||
Entity: "signer",
|
||||
Action: "generate",
|
||||
}},
|
||||
}
|
||||
|
||||
// DefaultSignerMacFilename is the default name of the signer macaroon
|
||||
@ -940,6 +944,24 @@ func (s *Server) MuSig2CombineSig(_ context.Context,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// MuSig2Cleanup removes a session from memory to free up resources.
|
||||
func (s *Server) MuSig2Cleanup(_ context.Context,
|
||||
in *MuSig2CleanupRequest) (*MuSig2CleanupResponse, error) {
|
||||
|
||||
// Check session ID length.
|
||||
sessionID, err := parseMuSig2SessionID(in.SessionId)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing session ID: %v", err)
|
||||
}
|
||||
|
||||
err = s.cfg.Signer.MuSig2Cleanup(sessionID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error cleaning up session: %v", err)
|
||||
}
|
||||
|
||||
return &MuSig2CleanupResponse{}, nil
|
||||
}
|
||||
|
||||
// parseRawKeyBytes checks that the provided raw public key is valid and returns
|
||||
// the public key. A nil public key is returned if the length of the rawKeyBytes
|
||||
// is zero.
|
||||
|
@ -906,11 +906,29 @@ func testTaprootMuSig2CombinedLeafKeySpend(ctxt context.Context, t *harnessTest,
|
||||
ctxt, &signrpc.MuSig2SignRequest{
|
||||
SessionId: sessResp3.SessionId,
|
||||
MessageDigest: sigHash,
|
||||
Cleanup: true,
|
||||
},
|
||||
)
|
||||
require.NoError(t.t, err)
|
||||
|
||||
// We manually clean up session 3, just to make sure that works as well.
|
||||
_, err = alice.SignerClient.MuSig2Cleanup(
|
||||
ctxt, &signrpc.MuSig2CleanupRequest{
|
||||
SessionId: sessResp3.SessionId,
|
||||
},
|
||||
)
|
||||
require.NoError(t.t, err)
|
||||
|
||||
// A second call to that cleaned up session should now fail with a
|
||||
// specific error.
|
||||
_, err = alice.SignerClient.MuSig2Sign(
|
||||
ctxt, &signrpc.MuSig2SignRequest{
|
||||
SessionId: sessResp3.SessionId,
|
||||
MessageDigest: sigHash,
|
||||
},
|
||||
)
|
||||
require.Error(t.t, err)
|
||||
require.Contains(t.t, err.Error(), "not found")
|
||||
|
||||
// Luckily only one of the signers needs to combine the signature, so
|
||||
// let's do that now.
|
||||
combineReq1, err := alice.SignerClient.MuSig2CombineSig(
|
||||
|
@ -94,6 +94,11 @@ func (d *DummySigner) MuSig2CombineSig(input.MuSig2SessionID,
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
// MuSig2Cleanup removes a session from memory to free up resources.
|
||||
func (d *DummySigner) MuSig2Cleanup(input.MuSig2SessionID) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SingleSigner is an implementation of the Signer interface that signs
|
||||
// everything with a single private key.
|
||||
type SingleSigner struct {
|
||||
@ -227,3 +232,8 @@ func (s *SingleSigner) MuSig2CombineSig(input.MuSig2SessionID,
|
||||
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
// MuSig2Cleanup removes a session from memory to free up resources.
|
||||
func (s *SingleSigner) MuSig2Cleanup(input.MuSig2SessionID) error {
|
||||
return nil
|
||||
}
|
||||
|
@ -704,6 +704,24 @@ func (b *BtcWallet) MuSig2CombineSig(sessionID input.MuSig2SessionID,
|
||||
return finalSig, session.HaveAllSigs, nil
|
||||
}
|
||||
|
||||
// MuSig2Cleanup removes a session from memory to free up resources.
|
||||
func (b *BtcWallet) MuSig2Cleanup(sessionID input.MuSig2SessionID) error {
|
||||
// We hold the lock during the whole operation, we don't want any
|
||||
// interference with calls that might come through in parallel for the
|
||||
// same session.
|
||||
b.musig2SessionsMtx.Lock()
|
||||
defer b.musig2SessionsMtx.Unlock()
|
||||
|
||||
_, ok := b.musig2Sessions[sessionID]
|
||||
if !ok {
|
||||
return fmt.Errorf("session with ID %x not found", sessionID[:])
|
||||
}
|
||||
|
||||
delete(b.musig2Sessions, sessionID)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// A compile time check to ensure that BtcWallet implements the Signer
|
||||
// interface.
|
||||
var _ input.Signer = (*BtcWallet)(nil)
|
||||
|
@ -33,7 +33,9 @@ import (
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/macaroons"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/status"
|
||||
"gopkg.in/macaroon.v2"
|
||||
)
|
||||
|
||||
@ -199,12 +201,9 @@ func (r *RPCKeyRing) SignPsbt(packet *psbt.Packet) error {
|
||||
FundedPsbt: buf.Bytes(),
|
||||
})
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error signing PSBT in remote signer "+
|
||||
considerShutdown(err)
|
||||
return fmt.Errorf("error signing PSBT in remote signer "+
|
||||
"instance: %v", err)
|
||||
|
||||
// Log as critical as we should shut down if there is no signer.
|
||||
log.Criticalf("RPC signer error: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
signedPacket, err := psbt.NewFromRawBytes(
|
||||
@ -410,12 +409,9 @@ func (r *RPCKeyRing) ECDH(keyDesc keychain.KeyDescriptor,
|
||||
|
||||
resp, err := r.signerClient.DeriveSharedKey(ctxt, req)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error deriving shared key in remote signer "+
|
||||
"instance: %v", err)
|
||||
|
||||
// Log as critical as we should shut down if there is no signer.
|
||||
log.Criticalf("RPC signer error: %v", err)
|
||||
return key, err
|
||||
considerShutdown(err)
|
||||
return key, fmt.Errorf("error deriving shared key in remote "+
|
||||
"signer instance: %v", err)
|
||||
}
|
||||
|
||||
copy(key[:], resp.SharedKey)
|
||||
@ -443,12 +439,9 @@ func (r *RPCKeyRing) SignMessage(keyLoc keychain.KeyLocator,
|
||||
DoubleHash: doubleHash,
|
||||
})
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error signing message in remote signer "+
|
||||
"instance: %v", err)
|
||||
|
||||
// Log as critical as we should shut down if there is no signer.
|
||||
log.Criticalf("RPC signer error: %v", err)
|
||||
return nil, err
|
||||
considerShutdown(err)
|
||||
return nil, fmt.Errorf("error signing message in remote "+
|
||||
"signer instance: %v", err)
|
||||
}
|
||||
|
||||
wireSig, err := lnwire.NewSigFromRawSignature(resp.Signature)
|
||||
@ -484,12 +477,9 @@ func (r *RPCKeyRing) SignMessageCompact(keyLoc keychain.KeyLocator,
|
||||
CompactSig: true,
|
||||
})
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error signing message in remote signer "+
|
||||
"instance: %v", err)
|
||||
|
||||
// Log as critical as we should shut down if there is no signer.
|
||||
log.Criticalf("RPC signer error: %v", err)
|
||||
return nil, err
|
||||
considerShutdown(err)
|
||||
return nil, fmt.Errorf("error signing message in remote "+
|
||||
"signer instance: %v", err)
|
||||
}
|
||||
|
||||
// The signature in the response is zbase32 encoded, so we need to
|
||||
@ -622,12 +612,9 @@ func (r *RPCKeyRing) MuSig2CreateSession(keyLoc keychain.KeyLocator,
|
||||
|
||||
resp, err := r.signerClient.MuSig2CreateSession(ctxt, req)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error creating MuSig2 session in remote "+
|
||||
"signer instance: %v", err)
|
||||
|
||||
// Log as critical as we should shut down if there is no signer.
|
||||
log.Criticalf("RPC signer error: %v", err)
|
||||
return nil, err
|
||||
considerShutdown(err)
|
||||
return nil, fmt.Errorf("error creating MuSig2 session in "+
|
||||
"remote signer instance: %v", err)
|
||||
}
|
||||
|
||||
// De-Serialize all the info back into our native struct.
|
||||
@ -678,12 +665,9 @@ func (r *RPCKeyRing) MuSig2RegisterNonces(sessionID input.MuSig2SessionID,
|
||||
|
||||
resp, err := r.signerClient.MuSig2RegisterNonces(ctxt, req)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error registering MuSig2 nonces in remote "+
|
||||
"signer instance: %v", err)
|
||||
|
||||
// Log as critical as we should shut down if there is no signer.
|
||||
log.Criticalf("RPC signer error: %v", err)
|
||||
return false, err
|
||||
considerShutdown(err)
|
||||
return false, fmt.Errorf("error registering MuSig2 nonces in "+
|
||||
"remote signer instance: %v", err)
|
||||
}
|
||||
|
||||
return resp.HaveAllNonces, nil
|
||||
@ -712,12 +696,9 @@ func (r *RPCKeyRing) MuSig2Sign(sessionID input.MuSig2SessionID,
|
||||
|
||||
resp, err := r.signerClient.MuSig2Sign(ctxt, req)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error signing MuSig2 session in remote "+
|
||||
"signer instance: %v", err)
|
||||
|
||||
// Log as critical as we should shut down if there is no signer.
|
||||
log.Criticalf("RPC signer error: %v", err)
|
||||
return nil, err
|
||||
considerShutdown(err)
|
||||
return nil, fmt.Errorf("error signing MuSig2 session in "+
|
||||
"remote signer instance: %v", err)
|
||||
}
|
||||
|
||||
partialSig, err := input.DeserializePartialSignature(
|
||||
@ -759,12 +740,9 @@ func (r *RPCKeyRing) MuSig2CombineSig(sessionID input.MuSig2SessionID,
|
||||
|
||||
resp, err := r.signerClient.MuSig2CombineSig(ctxt, req)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error combining MuSig2 signatures in remote "+
|
||||
"signer instance: %v", err)
|
||||
|
||||
// Log as critical as we should shut down if there is no signer.
|
||||
log.Criticalf("RPC signer error: %v", err)
|
||||
return nil, false, err
|
||||
considerShutdown(err)
|
||||
return nil, false, fmt.Errorf("error combining MuSig2 "+
|
||||
"signatures in remote signer instance: %v", err)
|
||||
}
|
||||
|
||||
// The final signature is only available when we have all the other
|
||||
@ -782,6 +760,25 @@ func (r *RPCKeyRing) MuSig2CombineSig(sessionID input.MuSig2SessionID,
|
||||
return finalSig, resp.HaveAllSignatures, nil
|
||||
}
|
||||
|
||||
// MuSig2Cleanup removes a session from memory to free up resources.
|
||||
func (r *RPCKeyRing) MuSig2Cleanup(sessionID input.MuSig2SessionID) error {
|
||||
req := &signrpc.MuSig2CleanupRequest{
|
||||
SessionId: sessionID[:],
|
||||
}
|
||||
|
||||
ctxt, cancel := context.WithTimeout(context.Background(), r.rpcTimeout)
|
||||
defer cancel()
|
||||
|
||||
_, err := r.signerClient.MuSig2Cleanup(ctxt, req)
|
||||
if err != nil {
|
||||
considerShutdown(err)
|
||||
return fmt.Errorf("error cleaning up MuSig2 session in remote "+
|
||||
"signer instance: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// remoteSign signs the input specified in signDesc of the given transaction tx
|
||||
// using the remote signing instance.
|
||||
func (r *RPCKeyRing) remoteSign(tx *wire.MsgTx, signDesc *input.SignDescriptor,
|
||||
@ -982,12 +979,9 @@ func (r *RPCKeyRing) remoteSign(tx *wire.MsgTx, signDesc *input.SignDescriptor,
|
||||
ctxt, &walletrpc.SignPsbtRequest{FundedPsbt: buf.Bytes()},
|
||||
)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error signing PSBT in remote signer "+
|
||||
considerShutdown(err)
|
||||
return nil, fmt.Errorf("error signing PSBT in remote signer "+
|
||||
"instance: %v", err)
|
||||
|
||||
// Log as critical as we should shut down if there is no signer.
|
||||
log.Criticalf("RPC signer error: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
signedPacket, err := psbt.NewFromRawBytes(
|
||||
@ -1114,3 +1108,26 @@ func packetFromTx(original *wire.MsgTx) (*psbt.Packet, error) {
|
||||
|
||||
return packet, nil
|
||||
}
|
||||
|
||||
// considerShutdown inspects the error and issues a shutdown (through logging
|
||||
// a critical error, which will cause the logger to issue a clean shutdown
|
||||
// request) if the error looks like a connection or general availability error
|
||||
// and not some application specific problem.
|
||||
func considerShutdown(err error) {
|
||||
statusErr, isStatusErr := status.FromError(err)
|
||||
switch {
|
||||
// The context attached to the client request has timed out. This can be
|
||||
// due to not being able to reach the signing server, or it's taking too
|
||||
// long to respond. In either case, request a shutdown.
|
||||
case err == context.DeadlineExceeded:
|
||||
fallthrough
|
||||
|
||||
// The signing server's context timed out before the client's due to
|
||||
// clock skew, request a shutdown anyway.
|
||||
case isStatusErr && statusErr.Code() == codes.DeadlineExceeded:
|
||||
log.Critical("RPC signing timed out: %v", err)
|
||||
|
||||
case isStatusErr && statusErr.Code() == codes.Unavailable:
|
||||
log.Critical("RPC signing server not available: %v", err)
|
||||
}
|
||||
}
|
||||
|
@ -108,6 +108,11 @@ func (s *MockSigner) MuSig2CombineSig(input.MuSig2SessionID,
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
// MuSig2Cleanup removes a session from memory to free up resources.
|
||||
func (s *MockSigner) MuSig2Cleanup(input.MuSig2SessionID) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddPrivKey records the passed privKey in the MockSigner's registry of keys it
|
||||
// can sign with in the future. A unique key locator is returned, allowing the
|
||||
// caller to sign with this key when presented via an input.SignDescriptor.
|
||||
|
Loading…
x
Reference in New Issue
Block a user