• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 13412100018

19 Feb 2025 12:05PM UTC coverage: 44.914% (-13.9%) from 58.794%
13412100018

Pull #9521

github

web-flow
Merge 861d6970e into 0e8786348
Pull Request #9521: unit: remove GOACC, use Go 1.20 native coverage functionality

101023 of 224923 relevant lines covered (44.91%)

19479.4 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/lnrpc/signrpc/signer_server.go
1
//go:build signrpc
2
// +build signrpc
3

4
package signrpc
5

6
import (
7
        "bytes"
8
        "context"
9
        "crypto/sha256"
10
        "fmt"
11
        "os"
12
        "path/filepath"
13

14
        "github.com/btcsuite/btcd/btcec/v2"
15
        "github.com/btcsuite/btcd/btcec/v2/schnorr"
16
        "github.com/btcsuite/btcd/btcec/v2/schnorr/musig2"
17
        "github.com/btcsuite/btcd/chaincfg/chainhash"
18
        "github.com/btcsuite/btcd/txscript"
19
        "github.com/btcsuite/btcd/wire"
20
        "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
21
        "github.com/lightningnetwork/lnd/input"
22
        "github.com/lightningnetwork/lnd/keychain"
23
        "github.com/lightningnetwork/lnd/lnrpc"
24
        "github.com/lightningnetwork/lnd/lnwire"
25
        "github.com/lightningnetwork/lnd/macaroons"
26
        "google.golang.org/grpc"
27
        "gopkg.in/macaroon-bakery.v2/bakery"
28
)
29

30
const (
31
        // subServerName is the name of the sub rpc server. We'll use this name
32
        // to register ourselves, and we also require that the main
33
        // SubServerConfigDispatcher instance recognize this as the name of the
34
        // config file that we need.
35
        subServerName = "SignRPC"
36

37
        // BIP0340 is the prefix for BIP0340-related tagged hashes.
38
        BIP0340 = "BIP0340"
39
)
40

41
var (
42
        // macaroonOps are the set of capabilities that our minted macaroon (if
43
        // it doesn't already exist) will have.
44
        macaroonOps = []bakery.Op{
45
                {
46
                        Entity: "signer",
47
                        Action: "generate",
48
                },
49
                {
50
                        Entity: "signer",
51
                        Action: "read",
52
                },
53
        }
54

55
        // macPermissions maps RPC calls to the permissions they require.
56
        macPermissions = map[string][]bakery.Op{
57
                "/signrpc.Signer/SignOutputRaw": {{
58
                        Entity: "signer",
59
                        Action: "generate",
60
                }},
61
                "/signrpc.Signer/ComputeInputScript": {{
62
                        Entity: "signer",
63
                        Action: "generate",
64
                }},
65
                "/signrpc.Signer/SignMessage": {{
66
                        Entity: "signer",
67
                        Action: "generate",
68
                }},
69
                "/signrpc.Signer/VerifyMessage": {{
70
                        Entity: "signer",
71
                        Action: "read",
72
                }},
73
                "/signrpc.Signer/DeriveSharedKey": {{
74
                        Entity: "signer",
75
                        Action: "generate",
76
                }},
77
                "/signrpc.Signer/MuSig2CombineKeys": {{
78
                        Entity: "signer",
79
                        Action: "read",
80
                }},
81
                "/signrpc.Signer/MuSig2CreateSession": {{
82
                        Entity: "signer",
83
                        Action: "generate",
84
                }},
85
                "/signrpc.Signer/MuSig2RegisterNonces": {{
86
                        Entity: "signer",
87
                        Action: "generate",
88
                }},
89
                "/signrpc.Signer/MuSig2Sign": {{
90
                        Entity: "signer",
91
                        Action: "generate",
92
                }},
93
                "/signrpc.Signer/MuSig2CombineSig": {{
94
                        Entity: "signer",
95
                        Action: "generate",
96
                }},
97
                "/signrpc.Signer/MuSig2Cleanup": {{
98
                        Entity: "signer",
99
                        Action: "generate",
100
                }},
101
        }
102

103
        // DefaultSignerMacFilename is the default name of the signer macaroon
104
        // that we expect to find via a file handle within the main
105
        // configuration file in this package.
106
        DefaultSignerMacFilename = "signer.macaroon"
107
)
108

109
// ServerShell is a shell struct holding a reference to the actual sub-server.
110
// It is used to register the gRPC sub-server with the root server before we
111
// have the necessary dependencies to populate the actual sub-server.
112
type ServerShell struct {
113
        SignerServer
114
}
115

116
// Server is a sub-server of the main RPC server: the signer RPC. This sub RPC
117
// server allows external callers to access the full signing capabilities of
118
// lnd. This allows callers to create custom protocols, external to lnd, even
119
// backed by multiple distinct lnd across independent failure domains.
120
type Server struct {
121
        // Required by the grpc-gateway/v2 library for forward compatibility.
122
        UnimplementedSignerServer
123

124
        cfg *Config
125
}
126

127
// A compile time check to ensure that Server fully implements the SignerServer
128
// gRPC service.
129
var _ SignerServer = (*Server)(nil)
130

131
// New returns a new instance of the signrpc Signer sub-server. We also return
132
// the set of permissions for the macaroons that we may create within this
133
// method. If the macaroons we need aren't found in the filepath, then we'll
134
// create them on start up. If we're unable to locate, or create the macaroons
135
// we need, then we'll return with an error.
136
func New(cfg *Config) (*Server, lnrpc.MacaroonPerms, error) {
×
137
        // If the path of the signer macaroon wasn't generated, then we'll
×
138
        // assume that it's found at the default network directory.
×
139
        if cfg.SignerMacPath == "" {
×
140
                cfg.SignerMacPath = filepath.Join(
×
141
                        cfg.NetworkDir, DefaultSignerMacFilename,
×
142
                )
×
143
        }
×
144

145
        // Now that we know the full path of the signer macaroon, we can check
146
        // to see if we need to create it or not. If stateless_init is set
147
        // then we don't write the macaroons.
148
        macFilePath := cfg.SignerMacPath
×
149
        if cfg.MacService != nil && !cfg.MacService.StatelessInit &&
×
150
                !lnrpc.FileExists(macFilePath) {
×
151

×
152
                log.Infof("Making macaroons for Signer RPC Server at: %v",
×
153
                        macFilePath)
×
154

×
155
                // At this point, we know that the signer macaroon doesn't yet,
×
156
                // exist, so we need to create it with the help of the main
×
157
                // macaroon service.
×
158
                signerMac, err := cfg.MacService.NewMacaroon(
×
159
                        context.Background(), macaroons.DefaultRootKeyID,
×
160
                        macaroonOps...,
×
161
                )
×
162
                if err != nil {
×
163
                        return nil, nil, err
×
164
                }
×
165
                signerMacBytes, err := signerMac.M().MarshalBinary()
×
166
                if err != nil {
×
167
                        return nil, nil, err
×
168
                }
×
169
                err = os.WriteFile(macFilePath, signerMacBytes, 0644)
×
170
                if err != nil {
×
171
                        _ = os.Remove(macFilePath)
×
172
                        return nil, nil, err
×
173
                }
×
174
        }
175

176
        signerServer := &Server{
×
177
                cfg: cfg,
×
178
        }
×
179

×
180
        return signerServer, macPermissions, nil
×
181
}
182

183
// Start launches any helper goroutines required for the rpcServer to function.
184
//
185
// NOTE: This is part of the lnrpc.SubServer interface.
186
func (s *Server) Start() error {
×
187
        return nil
×
188
}
×
189

190
// Stop signals any active goroutines for a graceful closure.
191
//
192
// NOTE: This is part of the lnrpc.SubServer interface.
193
func (s *Server) Stop() error {
×
194
        return nil
×
195
}
×
196

197
// Name returns a unique string representation of the sub-server. This can be
198
// used to identify the sub-server and also de-duplicate them.
199
//
200
// NOTE: This is part of the lnrpc.SubServer interface.
201
func (s *Server) Name() string {
×
202
        return subServerName
×
203
}
×
204

205
// RegisterWithRootServer will be called by the root gRPC server to direct a
206
// sub RPC server to register itself with the main gRPC root server. Until this
207
// is called, each sub-server won't be able to have
208
// requests routed towards it.
209
//
210
// NOTE: This is part of the lnrpc.GrpcHandler interface.
211
func (r *ServerShell) RegisterWithRootServer(grpcServer *grpc.Server) error {
×
212
        // We make sure that we register it with the main gRPC server to ensure
×
213
        // all our methods are routed properly.
×
214
        RegisterSignerServer(grpcServer, r)
×
215

×
216
        log.Debugf("Signer RPC server successfully registered with root gRPC " +
×
217
                "server")
×
218

×
219
        return nil
×
220
}
×
221

222
// RegisterWithRestServer will be called by the root REST mux to direct a sub
223
// RPC server to register itself with the main REST mux server. Until this is
224
// called, each sub-server won't be able to have requests routed towards it.
225
//
226
// NOTE: This is part of the lnrpc.GrpcHandler interface.
227
func (r *ServerShell) RegisterWithRestServer(ctx context.Context,
228
        mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error {
×
229

×
230
        // We make sure that we register it with the main REST server to ensure
×
231
        // all our methods are routed properly.
×
232
        err := RegisterSignerHandlerFromEndpoint(ctx, mux, dest, opts)
×
233
        if err != nil {
×
234
                log.Errorf("Could not register Signer REST server "+
×
235
                        "with root REST server: %v", err)
×
236
                return err
×
237
        }
×
238

239
        log.Debugf("Signer REST server successfully registered with " +
×
240
                "root REST server")
×
241
        return nil
×
242
}
243

244
// CreateSubServer populates the subserver's dependencies using the passed
245
// SubServerConfigDispatcher. This method should fully initialize the
246
// sub-server instance, making it ready for action. It returns the macaroon
247
// permissions that the sub-server wishes to pass on to the root server for all
248
// methods routed towards it.
249
//
250
// NOTE: This is part of the lnrpc.GrpcHandler interface.
251
func (r *ServerShell) CreateSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (
252
        lnrpc.SubServer, lnrpc.MacaroonPerms, error) {
×
253

×
254
        subServer, macPermissions, err := createNewSubServer(configRegistry)
×
255
        if err != nil {
×
256
                return nil, nil, err
×
257
        }
×
258

259
        r.SignerServer = subServer
×
260
        return subServer, macPermissions, nil
×
261
}
262

263
// SignOutputRaw generates a signature for the passed transaction according to
264
// the data within the passed SignReq. If we're unable to find the keys that
265
// correspond to the KeyLocators in the SignReq then we'll return an error.
266
// Additionally, if the user doesn't provide the set of required parameters, or
267
// provides an invalid transaction, then we'll return with an error.
268
//
269
// NOTE: The resulting signature should be void of a sighash byte.
270
func (s *Server) SignOutputRaw(_ context.Context, in *SignReq) (*SignResp,
271
        error) {
×
272

×
273
        switch {
×
274
        // If the client doesn't specify a transaction, then there's nothing to
275
        // sign, so we'll exit early.
276
        case len(in.RawTxBytes) == 0:
×
277
                return nil, fmt.Errorf("a transaction to sign MUST be " +
×
278
                        "passed in")
×
279

280
        // If the client doesn't tell us *how* to sign the transaction, then we
281
        // can't sign anything, so we'll exit early.
282
        case len(in.SignDescs) == 0:
×
283
                return nil, fmt.Errorf("at least one SignDescs MUST be " +
×
284
                        "passed in")
×
285
        }
286

287
        // Now that we know we have an actual transaction to decode, we'll
288
        // deserialize it into something that we can properly utilize.
289
        var (
×
290
                txToSign wire.MsgTx
×
291
                err      error
×
292
        )
×
293
        txReader := bytes.NewReader(in.RawTxBytes)
×
294
        if err := txToSign.Deserialize(txReader); err != nil {
×
295
                return nil, fmt.Errorf("unable to decode tx: %w", err)
×
296
        }
×
297

298
        var (
×
299
                sigHashCache      = input.NewTxSigHashesV0Only(&txToSign)
×
300
                prevOutputFetcher = txscript.NewMultiPrevOutFetcher(nil)
×
301
        )
×
302

×
303
        // If we're spending one or more SegWit v1 (Taproot) inputs, then we
×
304
        // need the full UTXO information available.
×
305
        if len(in.PrevOutputs) > 0 {
×
306
                if len(in.PrevOutputs) != len(txToSign.TxIn) {
×
307
                        return nil, fmt.Errorf("provided previous outputs " +
×
308
                                "doesn't match number of transaction inputs")
×
309
                }
×
310

311
                // Add all previous inputs to our sighash prev out fetcher so we
312
                // can calculate the sighash correctly.
313
                for idx, txIn := range txToSign.TxIn {
×
314
                        prevOutputFetcher.AddPrevOut(
×
315
                                txIn.PreviousOutPoint, &wire.TxOut{
×
316
                                        Value:    in.PrevOutputs[idx].Value,
×
317
                                        PkScript: in.PrevOutputs[idx].PkScript,
×
318
                                },
×
319
                        )
×
320
                }
×
321
                sigHashCache = txscript.NewTxSigHashes(
×
322
                        &txToSign, prevOutputFetcher,
×
323
                )
×
324
        }
325

326
        log.Debugf("Generating sigs for %v inputs: ", len(in.SignDescs))
×
327

×
328
        // With the transaction deserialized, we'll now convert sign descs so
×
329
        // we can feed it into the actual signer.
×
330
        signDescs := make([]*input.SignDescriptor, 0, len(in.SignDescs))
×
331
        for _, signDesc := range in.SignDescs {
×
332
                keyDesc := signDesc.KeyDesc
×
333

×
334
                // The caller can either specify the key using the raw pubkey,
×
335
                // or the description of the key. We'll still attempt to parse
×
336
                // both if both were provided however, to ensure the underlying
×
337
                // SignOutputRaw has as much information as possible.
×
338
                var (
×
339
                        targetPubKey *btcec.PublicKey
×
340
                        keyLoc       keychain.KeyLocator
×
341
                )
×
342

×
343
                // If this method doesn't return nil, then we know that user is
×
344
                // attempting to include a raw serialized pub key.
×
345
                if keyDesc.GetRawKeyBytes() != nil {
×
346
                        targetPubKey, err = parseRawKeyBytes(
×
347
                                keyDesc.GetRawKeyBytes(),
×
348
                        )
×
349
                        if err != nil {
×
350
                                return nil, err
×
351
                        }
×
352
                }
353

354
                // Similarly, if they specified a key locator, then we'll parse
355
                // that as well.
356
                if keyDesc.GetKeyLoc() != nil {
×
357
                        protoLoc := keyDesc.GetKeyLoc()
×
358
                        keyLoc = keychain.KeyLocator{
×
359
                                Family: keychain.KeyFamily(
×
360
                                        protoLoc.KeyFamily,
×
361
                                ),
×
362
                                Index: uint32(protoLoc.KeyIndex),
×
363
                        }
×
364
                }
×
365

366
                // Check what sign method was selected by the user so, we know
367
                // exactly what we're expecting and can prevent some of the more
368
                // obvious usage errors.
369
                signMethod, err := UnmarshalSignMethod(signDesc.SignMethod)
×
370
                if err != nil {
×
371
                        return nil, fmt.Errorf("unable to unmarshal sign "+
×
372
                                "method: %v", err)
×
373
                }
×
374
                if !signMethod.PkScriptCompatible(signDesc.Output.PkScript) {
×
375
                        return nil, fmt.Errorf("selected sign method %v is "+
×
376
                                "not compatible with given pk script %x",
×
377
                                signMethod, signDesc.Output.PkScript)
×
378
                }
×
379

380
                // Perform input validation according to the sign method. Not
381
                // all methods require the same fields to be provided.
382
                switch signMethod {
×
383
                case input.WitnessV0SignMethod:
×
384
                        // If a witness script isn't passed, then we can't
×
385
                        // proceed, as in the p2wsh case, we can't properly
×
386
                        // generate the sighash. A P2WKH doesn't need a witness
×
387
                        // script. But SignOutputRaw still needs to know the PK
×
388
                        // script that was used for the output. We'll send it in
×
389
                        // the WitnessScript field, the SignOutputRaw RPC will
×
390
                        // know what to do with it when creating the sighash.
×
391
                        if len(signDesc.WitnessScript) == 0 {
×
392
                                return nil, fmt.Errorf("witness script MUST " +
×
393
                                        "be specified for segwit v0 sign " +
×
394
                                        "method")
×
395
                        }
×
396

397
                case input.TaprootKeySpendBIP0086SignMethod:
×
398
                        if len(signDesc.TapTweak) > 0 {
×
399
                                return nil, fmt.Errorf("tap tweak must be " +
×
400
                                        "empty for BIP0086 key spend")
×
401
                        }
×
402

403
                case input.TaprootKeySpendSignMethod:
×
404
                        if len(signDesc.TapTweak) != sha256.Size {
×
405
                                return nil, fmt.Errorf("tap tweak must be " +
×
406
                                        "specified for key spend with root " +
×
407
                                        "hash")
×
408
                        }
×
409

410
                case input.TaprootScriptSpendSignMethod:
×
411
                        if len(signDesc.WitnessScript) == 0 {
×
412
                                return nil, fmt.Errorf("witness script MUST " +
×
413
                                        "be specified for taproot script " +
×
414
                                        "spend method")
×
415
                        }
×
416
                }
417

418
                // If the users provided a double tweak, then we'll need to
419
                // parse that out now to ensure their input is properly signed.
420
                var tweakPrivKey *btcec.PrivateKey
×
421
                if len(signDesc.DoubleTweak) != 0 {
×
422
                        tweakPrivKey, _ = btcec.PrivKeyFromBytes(
×
423
                                signDesc.DoubleTweak,
×
424
                        )
×
425
                }
×
426

427
                // Finally, with verification and parsing complete, we can
428
                // construct the final sign descriptor to generate the proper
429
                // signature for this input.
430
                signDescs = append(signDescs, &input.SignDescriptor{
×
431
                        KeyDesc: keychain.KeyDescriptor{
×
432
                                KeyLocator: keyLoc,
×
433
                                PubKey:     targetPubKey,
×
434
                        },
×
435
                        SingleTweak:   signDesc.SingleTweak,
×
436
                        DoubleTweak:   tweakPrivKey,
×
437
                        TapTweak:      signDesc.TapTweak,
×
438
                        WitnessScript: signDesc.WitnessScript,
×
439
                        SignMethod:    signMethod,
×
440
                        Output: &wire.TxOut{
×
441
                                Value:    signDesc.Output.Value,
×
442
                                PkScript: signDesc.Output.PkScript,
×
443
                        },
×
444
                        HashType:          txscript.SigHashType(signDesc.Sighash),
×
445
                        SigHashes:         sigHashCache,
×
446
                        InputIndex:        int(signDesc.InputIndex),
×
447
                        PrevOutputFetcher: prevOutputFetcher,
×
448
                })
×
449

×
450
                // Are we trying to sign for a Taproot output? Then we need all
×
451
                // previous outputs being declared, otherwise we'd run into a
×
452
                // panic later on.
×
453
                if txscript.IsPayToTaproot(signDesc.Output.PkScript) {
×
454
                        for idx, txIn := range txToSign.TxIn {
×
455
                                utxo := prevOutputFetcher.FetchPrevOutput(
×
456
                                        txIn.PreviousOutPoint,
×
457
                                )
×
458
                                if utxo == nil {
×
459
                                        return nil, fmt.Errorf("error signing "+
×
460
                                                "taproot output, transaction "+
×
461
                                                "input %d is missing its "+
×
462
                                                "previous outpoint information",
×
463
                                                idx)
×
464
                                }
×
465
                        }
466
                }
467
        }
468

469
        // Now that we've mapped all the proper sign descriptors, we can
470
        // request signatures for each of them, passing in the transaction to
471
        // be signed.
472
        numSigs := len(in.SignDescs)
×
473
        resp := &SignResp{
×
474
                RawSigs: make([][]byte, numSigs),
×
475
        }
×
476
        for i, signDesc := range signDescs {
×
477
                sig, err := s.cfg.Signer.SignOutputRaw(&txToSign, signDesc)
×
478
                if err != nil {
×
479
                        log.Errorf("unable to generate sig for input "+
×
480
                                "#%v: %v", i, err)
×
481

×
482
                        return nil, err
×
483
                }
×
484

485
                resp.RawSigs[i] = sig.Serialize()
×
486
        }
487

488
        return resp, nil
×
489
}
490

491
// ComputeInputScript generates a complete InputIndex for the passed
492
// transaction with the signature as defined within the passed SignDescriptor.
493
// This method should be capable of generating the proper input script for both
494
// regular p2wkh/p2tr outputs and p2wkh outputs nested within a regular p2sh
495
// output.
496
//
497
// Note that when using this method to sign inputs belonging to the wallet, the
498
// only items of the SignDescriptor that need to be populated are pkScript in
499
// the TxOut field, the value in that same field, and finally the input index.
500
func (s *Server) ComputeInputScript(ctx context.Context,
501
        in *SignReq) (*InputScriptResp, error) {
×
502

×
503
        switch {
×
504
        // If the client doesn't specify a transaction, then there's nothing to
505
        // sign, so we'll exit early.
506
        case len(in.RawTxBytes) == 0:
×
507
                return nil, fmt.Errorf("a transaction to sign MUST be " +
×
508
                        "passed in")
×
509

510
        // If the client doesn't tell us *how* to sign the transaction, then we
511
        // can't sign anything, so we'll exit early.
512
        case len(in.SignDescs) == 0:
×
513
                return nil, fmt.Errorf("at least one SignDescs MUST be " +
×
514
                        "passed in")
×
515
        }
516

517
        // Now that we know we have an actual transaction to decode, we'll
518
        // deserialize it into something that we can properly utilize.
519
        var txToSign wire.MsgTx
×
520
        txReader := bytes.NewReader(in.RawTxBytes)
×
521
        if err := txToSign.Deserialize(txReader); err != nil {
×
522
                return nil, fmt.Errorf("unable to decode tx: %w", err)
×
523
        }
×
524

525
        var (
×
526
                sigHashCache      = input.NewTxSigHashesV0Only(&txToSign)
×
527
                prevOutputFetcher = txscript.NewMultiPrevOutFetcher(nil)
×
528
        )
×
529

×
530
        // If we're spending one or more SegWit v1 (Taproot) inputs, then we
×
531
        // need the full UTXO information available.
×
532
        if len(in.PrevOutputs) > 0 {
×
533
                if len(in.PrevOutputs) != len(txToSign.TxIn) {
×
534
                        return nil, fmt.Errorf("provided previous outputs " +
×
535
                                "doesn't match number of transaction inputs")
×
536
                }
×
537

538
                // Add all previous inputs to our sighash prev out fetcher so we
539
                // can calculate the sighash correctly.
540
                for idx, txIn := range txToSign.TxIn {
×
541
                        prevOutputFetcher.AddPrevOut(
×
542
                                txIn.PreviousOutPoint, &wire.TxOut{
×
543
                                        Value:    in.PrevOutputs[idx].Value,
×
544
                                        PkScript: in.PrevOutputs[idx].PkScript,
×
545
                                },
×
546
                        )
×
547
                }
×
548
                sigHashCache = txscript.NewTxSigHashes(
×
549
                        &txToSign, prevOutputFetcher,
×
550
                )
×
551
        }
552

553
        signDescs := make([]*input.SignDescriptor, 0, len(in.SignDescs))
×
554
        for _, signDesc := range in.SignDescs {
×
555
                // For this method, the only fields that we care about are the
×
556
                // hash type, and the information concerning the output as we
×
557
                // only know how to provide full witnesses for outputs that we
×
558
                // solely control.
×
559
                signDescs = append(signDescs, &input.SignDescriptor{
×
560
                        Output: &wire.TxOut{
×
561
                                Value:    signDesc.Output.Value,
×
562
                                PkScript: signDesc.Output.PkScript,
×
563
                        },
×
564
                        HashType:          txscript.SigHashType(signDesc.Sighash),
×
565
                        SigHashes:         sigHashCache,
×
566
                        PrevOutputFetcher: prevOutputFetcher,
×
567
                        InputIndex:        int(signDesc.InputIndex),
×
568
                })
×
569
        }
×
570

571
        // With all of our signDescs assembled, we can now generate a valid
572
        // input script for each of them, and collate the responses to return
573
        // back to the caller.
574
        numWitnesses := len(in.SignDescs)
×
575
        resp := &InputScriptResp{
×
576
                InputScripts: make([]*InputScript, numWitnesses),
×
577
        }
×
578
        for i, signDesc := range signDescs {
×
579
                inputScript, err := s.cfg.Signer.ComputeInputScript(
×
580
                        &txToSign, signDesc,
×
581
                )
×
582
                if err != nil {
×
583
                        return nil, err
×
584
                }
×
585

586
                resp.InputScripts[i] = &InputScript{
×
587
                        Witness:   inputScript.Witness,
×
588
                        SigScript: inputScript.SigScript,
×
589
                }
×
590
        }
591

592
        return resp, nil
×
593
}
594

595
// SignMessage signs a message with the key specified in the key locator. The
596
// returned signature is fixed-size LN wire format encoded.
597
func (s *Server) SignMessage(_ context.Context,
598
        in *SignMessageReq) (*SignMessageResp, error) {
×
599

×
600
        if in.Msg == nil {
×
601
                return nil, fmt.Errorf("a message to sign MUST be passed in")
×
602
        }
×
603
        if in.KeyLoc == nil {
×
604
                return nil, fmt.Errorf("a key locator MUST be passed in")
×
605
        }
×
606
        if in.SchnorrSig && in.CompactSig {
×
607
                return nil, fmt.Errorf("compact format can not be used for " +
×
608
                        "Schnorr signatures")
×
609
        }
×
610
        if !in.SchnorrSig && len(in.Tag) > 0 {
×
611
                return nil, fmt.Errorf("tag can only be used when the " +
×
612
                        "Schnorr signature option is set")
×
613
        }
×
614
        if bytes.HasPrefix(in.Tag, []byte(BIP0340)) {
×
615
                return nil, fmt.Errorf("tag cannot have BIP0340 prefix")
×
616
        }
×
617
        if bytes.HasPrefix(in.Tag, chainhash.TagTapSighash) {
×
618
                return nil, fmt.Errorf("tag cannot be TapSighash")
×
619
        }
×
620
        if in.DoubleHash && len(in.Tag) > 0 {
×
621
                return nil, fmt.Errorf("double hash and tag can't be set at " +
×
622
                        "the same time")
×
623
        }
×
624

625
        // Describe the private key we'll be using for signing.
626
        keyLocator := keychain.KeyLocator{
×
627
                Family: keychain.KeyFamily(in.KeyLoc.KeyFamily),
×
628
                Index:  uint32(in.KeyLoc.KeyIndex),
×
629
        }
×
630

×
631
        // Use the schnorr signature algorithm to sign the message.
×
632
        if in.SchnorrSig {
×
633
                sig, err := s.cfg.KeyRing.SignMessageSchnorr(
×
634
                        keyLocator, in.Msg, in.DoubleHash,
×
635
                        in.SchnorrSigTapTweak, in.Tag,
×
636
                )
×
637
                if err != nil {
×
638
                        return nil, fmt.Errorf("can't sign the hash: %w", err)
×
639
                }
×
640

641
                sigParsed, err := schnorr.ParseSignature(sig.Serialize())
×
642
                if err != nil {
×
643
                        return nil, fmt.Errorf("can't parse Schnorr "+
×
644
                                "signature: %v", err)
×
645
                }
×
646

647
                return &SignMessageResp{
×
648
                        Signature: sigParsed.Serialize(),
×
649
                }, nil
×
650
        }
651

652
        // To allow a watch-only wallet to forward the SignMessageCompact to an
653
        // endpoint that doesn't add the message prefix, we allow this RPC to
654
        // also return the compact signature format instead of adding a flag to
655
        // the lnrpc.SignMessage call that removes the message prefix.
656
        if in.CompactSig {
×
657
                sigBytes, err := s.cfg.KeyRing.SignMessageCompact(
×
658
                        keyLocator, in.Msg, in.DoubleHash,
×
659
                )
×
660
                if err != nil {
×
661
                        return nil, fmt.Errorf("can't sign the hash: %w", err)
×
662
                }
×
663

664
                return &SignMessageResp{
×
665
                        Signature: sigBytes,
×
666
                }, nil
×
667
        }
668

669
        // Create the raw ECDSA signature first and convert it to the final wire
670
        // format after.
671
        sig, err := s.cfg.KeyRing.SignMessage(
×
672
                keyLocator, in.Msg, in.DoubleHash,
×
673
        )
×
674
        if err != nil {
×
675
                return nil, fmt.Errorf("can't sign the hash: %w", err)
×
676
        }
×
677
        wireSig, err := lnwire.NewSigFromSignature(sig)
×
678
        if err != nil {
×
679
                return nil, fmt.Errorf("can't convert to wire format: %w", err)
×
680
        }
×
681
        return &SignMessageResp{
×
682
                Signature: wireSig.ToSignatureBytes(),
×
683
        }, nil
×
684
}
685

686
// VerifyMessage verifies a signature over a message using the public key
687
// provided. The signature must be fixed-size LN wire format encoded.
688
func (s *Server) VerifyMessage(_ context.Context,
689
        in *VerifyMessageReq) (*VerifyMessageResp, error) {
×
690

×
691
        if in.Msg == nil {
×
692
                return nil, fmt.Errorf("a message to verify MUST be passed in")
×
693
        }
×
694
        if in.Signature == nil {
×
695
                return nil, fmt.Errorf("a signature to verify MUST be passed " +
×
696
                        "in")
×
697
        }
×
698
        if in.Pubkey == nil {
×
699
                return nil, fmt.Errorf("a pubkey to verify MUST be passed in")
×
700
        }
×
701
        if !in.IsSchnorrSig && len(in.Tag) > 0 {
×
702
                return nil, fmt.Errorf("tag can only be used when the " +
×
703
                        "Schnorr signature option is set")
×
704
        }
×
705

706
        // We allow for Schnorr signatures to be verified.
707
        if in.IsSchnorrSig {
×
708
                // We expect the public key to be in the BIP-340 32-byte format
×
709
                // for Schnorr signatures.
×
710
                pubkey, err := schnorr.ParsePubKey(in.Pubkey)
×
711
                if err != nil {
×
712
                        return nil, fmt.Errorf("unable to parse pubkey: %w",
×
713
                                err)
×
714
                }
×
715

716
                sigParsed, err := schnorr.ParseSignature(in.Signature)
×
717
                if err != nil {
×
718
                        return nil, fmt.Errorf("can't parse Schnorr "+
×
719
                                "signature: %w", err)
×
720
                }
×
721

722
                var digest []byte
×
723
                if len(in.Tag) == 0 {
×
724
                        digest = chainhash.HashB(in.Msg)
×
725
                } else {
×
726
                        taggedHash := chainhash.TaggedHash(in.Tag, in.Msg)
×
727
                        digest = taggedHash[:]
×
728
                }
×
729
                valid := sigParsed.Verify(digest, pubkey)
×
730

×
731
                return &VerifyMessageResp{
×
732
                        Valid: valid,
×
733
                }, nil
×
734
        }
735

736
        pubkey, err := btcec.ParsePubKey(in.Pubkey)
×
737
        if err != nil {
×
738
                return nil, fmt.Errorf("unable to parse pubkey: %w", err)
×
739
        }
×
740

741
        // The signature must be fixed-size LN wire format encoded.
742
        wireSig, err := lnwire.NewSigFromECDSARawSignature(in.Signature)
×
743
        if err != nil {
×
744
                return nil, fmt.Errorf("failed to decode signature: %w", err)
×
745
        }
×
746
        sig, err := wireSig.ToSignature()
×
747
        if err != nil {
×
748
                return nil, fmt.Errorf("failed to convert from wire format: %w",
×
749
                        err)
×
750
        }
×
751

752
        // The signature is over the sha256 hash of the message.
753
        digest := chainhash.HashB(in.Msg)
×
754
        valid := sig.Verify(digest, pubkey)
×
755
        return &VerifyMessageResp{
×
756
                Valid: valid,
×
757
        }, nil
×
758
}
759

760
// DeriveSharedKey returns a shared secret key by performing Diffie-Hellman key
761
// derivation between the ephemeral public key in the request and the node's
762
// key specified in the key_desc parameter. Either a key locator or a raw public
763
// key is expected in the key_desc, if neither is supplied, defaults to the
764
// node's identity private key. The old key_loc parameter in the request
765
// shouldn't be used anymore.
766
// The resulting shared public key is serialized in the compressed format and
767
// hashed with sha256, resulting in the final key length of 256bit.
768
func (s *Server) DeriveSharedKey(_ context.Context, in *SharedKeyRequest) (
769
        *SharedKeyResponse, error) {
×
770

×
771
        // Check that EphemeralPubkey is valid.
×
772
        ephemeralPubkey, err := parseRawKeyBytes(in.EphemeralPubkey)
×
773
        if err != nil {
×
774
                return nil, fmt.Errorf("error in ephemeral pubkey: %w", err)
×
775
        }
×
776
        if ephemeralPubkey == nil {
×
777
                return nil, fmt.Errorf("must provide ephemeral pubkey")
×
778
        }
×
779

780
        // Check for backward compatibility. The caller either specifies the old
781
        // key_loc field, or the new key_desc field, but not both.
782
        if in.KeyDesc != nil && in.KeyLoc != nil {
×
783
                return nil, fmt.Errorf("use either key_desc or key_loc")
×
784
        }
×
785

786
        // When key_desc is used, the key_desc.key_loc is expected as the caller
787
        // needs to specify the KeyFamily.
788
        if in.KeyDesc != nil && in.KeyDesc.KeyLoc == nil {
×
789
                return nil, fmt.Errorf("when setting key_desc the field " +
×
790
                        "key_desc.key_loc must also be set")
×
791
        }
×
792

793
        // We extract two params, rawKeyBytes and keyLoc. Notice their initial
794
        // values will be overwritten if not using the deprecated RPC param.
795
        var rawKeyBytes []byte
×
796
        keyLoc := in.KeyLoc
×
797
        if in.KeyDesc != nil {
×
798
                keyLoc = in.KeyDesc.GetKeyLoc()
×
799
                rawKeyBytes = in.KeyDesc.GetRawKeyBytes()
×
800
        }
×
801

802
        // When no keyLoc is supplied, defaults to the node's identity private
803
        // key.
804
        if keyLoc == nil {
×
805
                keyLoc = &KeyLocator{
×
806
                        KeyFamily: int32(keychain.KeyFamilyNodeKey),
×
807
                        KeyIndex:  0,
×
808
                }
×
809
        }
×
810

811
        // Check the caller is using either the key index or the raw public key
812
        // to perform the ECDH, we can't have both.
813
        if rawKeyBytes != nil && keyLoc.KeyIndex != 0 {
×
814
                return nil, fmt.Errorf("use either raw_key_bytes or key_index")
×
815
        }
×
816

817
        // Check the raw public key is valid. Notice that if the rawKeyBytes is
818
        // empty, the parseRawKeyBytes won't return an error, a nil
819
        // *btcec.PublicKey is returned instead.
820
        pk, err := parseRawKeyBytes(rawKeyBytes)
×
821
        if err != nil {
×
822
                return nil, fmt.Errorf("error in raw pubkey: %w", err)
×
823
        }
×
824

825
        // Create a key descriptor. When the KeyIndex is not specified, it uses
826
        // the empty value 0, and when the raw public key is not specified, the
827
        // pk is nil.
828
        keyDescriptor := keychain.KeyDescriptor{
×
829
                KeyLocator: keychain.KeyLocator{
×
830
                        Family: keychain.KeyFamily(keyLoc.KeyFamily),
×
831
                        Index:  uint32(keyLoc.KeyIndex),
×
832
                },
×
833
                PubKey: pk,
×
834
        }
×
835

×
836
        // Derive the shared key using ECDH and hashing the serialized
×
837
        // compressed shared point.
×
838
        sharedKeyHash, err := s.cfg.KeyRing.ECDH(keyDescriptor, ephemeralPubkey)
×
839
        if err != nil {
×
840
                err := fmt.Errorf("unable to derive shared key: %w", err)
×
841
                log.Error(err)
×
842
                return nil, err
×
843
        }
×
844

845
        return &SharedKeyResponse{SharedKey: sharedKeyHash[:]}, nil
×
846
}
847

848
// MuSig2CombineKeys combines the given set of public keys into a single
849
// combined MuSig2 combined public key, applying the given tweaks.
850
func (s *Server) MuSig2CombineKeys(_ context.Context,
851
        in *MuSig2CombineKeysRequest) (*MuSig2CombineKeysResponse, error) {
×
852

×
853
        // Check the now mandatory version first. We made the version mandatory,
×
854
        // so we don't get unexpected/undefined behavior for old clients that
×
855
        // don't specify the version. Since this API is still declared to be
×
856
        // experimental this should be the approach that leads to the least
×
857
        // amount of unexpected behavior.
×
858
        version, err := UnmarshalMuSig2Version(in.Version)
×
859
        if err != nil {
×
860
                return nil, fmt.Errorf("error parsing version: %w", err)
×
861
        }
×
862

863
        // Parse the public keys of all signing participants. This must also
864
        // include our own, local key.
865
        allSignerPubKeys, err := input.MuSig2ParsePubKeys(
×
866
                version, in.AllSignerPubkeys,
×
867
        )
×
868
        if err != nil {
×
869
                return nil, fmt.Errorf("error parsing all signer public "+
×
870
                        "keys: %w", err)
×
871
        }
×
872

873
        // Are there any tweaks to apply to the combined public key?
874
        tweaks, err := UnmarshalTweaks(in.Tweaks, in.TaprootTweak)
×
875
        if err != nil {
×
876
                return nil, fmt.Errorf("error unmarshaling tweak options: %w",
×
877
                        err)
×
878
        }
×
879

880
        // Combine the keys now without creating a session in memory.
881
        combinedKey, err := input.MuSig2CombineKeys(
×
882
                version, allSignerPubKeys, true, tweaks,
×
883
        )
×
884
        if err != nil {
×
885
                return nil, fmt.Errorf("error combining keys: %w", err)
×
886
        }
×
887

888
        var internalKeyBytes []byte
×
889
        if combinedKey.PreTweakedKey != nil {
×
890
                internalKeyBytes = schnorr.SerializePubKey(
×
891
                        combinedKey.PreTweakedKey,
×
892
                )
×
893
        }
×
894

895
        return &MuSig2CombineKeysResponse{
×
896
                CombinedKey: schnorr.SerializePubKey(
×
897
                        combinedKey.FinalKey,
×
898
                ),
×
899
                TaprootInternalKey: internalKeyBytes,
×
900
                Version:            in.Version,
×
901
        }, nil
×
902
}
903

904
// secNonceToPubNonce takes our two secret nonces, and produces their two
905
// corresponding EC points, serialized in compressed format.
906
//
907
// NOTE: This was copied from btcsuite/btcec/musig2/nonces.go.
908
func secNonceToPubNonce(secNonce [musig2.SecNonceSize]byte,
909
) [musig2.PubNonceSize]byte {
×
910

×
911
        var k1Mod, k2Mod btcec.ModNScalar
×
912
        k1Mod.SetByteSlice(secNonce[:btcec.PrivKeyBytesLen])
×
913
        k2Mod.SetByteSlice(secNonce[btcec.PrivKeyBytesLen:])
×
914

×
915
        var r1, r2 btcec.JacobianPoint
×
916
        btcec.ScalarBaseMultNonConst(&k1Mod, &r1)
×
917
        btcec.ScalarBaseMultNonConst(&k2Mod, &r2)
×
918

×
919
        // Next, we'll convert the key in jacobian format to a normal public
×
920
        // key expressed in affine coordinates.
×
921
        r1.ToAffine()
×
922
        r2.ToAffine()
×
923
        r1Pub := btcec.NewPublicKey(&r1.X, &r1.Y)
×
924
        r2Pub := btcec.NewPublicKey(&r2.X, &r2.Y)
×
925

×
926
        var pubNonce [musig2.PubNonceSize]byte
×
927

×
928
        // The public nonces are serialized as: R1 || R2, where both keys are
×
929
        // serialized in compressed format.
×
930
        copy(pubNonce[:], r1Pub.SerializeCompressed())
×
931
        copy(
×
932
                pubNonce[btcec.PubKeyBytesLenCompressed:],
×
933
                r2Pub.SerializeCompressed(),
×
934
        )
×
935

×
936
        return pubNonce
×
937
}
×
938

939
// MuSig2CreateSession creates a new MuSig2 signing session using the local
940
// key identified by the key locator. The complete list of all public keys of
941
// all signing parties must be provided, including the public key of the local
942
// signing key. If nonces of other parties are already known, they can be
943
// submitted as well to reduce the number of RPC calls necessary later on.
944
func (s *Server) MuSig2CreateSession(_ context.Context,
945
        in *MuSig2SessionRequest) (*MuSig2SessionResponse, error) {
×
946

×
947
        // Check the now mandatory version first. We made the version mandatory,
×
948
        // so we don't get unexpected/undefined behavior for old clients that
×
949
        // don't specify the version. Since this API is still declared to be
×
950
        // experimental this should be the approach that leads to the least
×
951
        // amount of unexpected behavior.
×
952
        version, err := UnmarshalMuSig2Version(in.Version)
×
953
        if err != nil {
×
954
                return nil, fmt.Errorf("error parsing version: %w", err)
×
955
        }
×
956

957
        // A key locator is always mandatory.
958
        if in.KeyLoc == nil {
×
959
                return nil, fmt.Errorf("missing key_loc")
×
960
        }
×
961
        keyLoc := keychain.KeyLocator{
×
962
                Family: keychain.KeyFamily(in.KeyLoc.KeyFamily),
×
963
                Index:  uint32(in.KeyLoc.KeyIndex),
×
964
        }
×
965

×
966
        // Parse the public keys of all signing participants. This must also
×
967
        // include our own, local key.
×
968
        allSignerPubKeys, err := input.MuSig2ParsePubKeys(
×
969
                version, in.AllSignerPubkeys,
×
970
        )
×
971
        if err != nil {
×
972
                return nil, fmt.Errorf("error parsing all signer public "+
×
973
                        "keys: %w", err)
×
974
        }
×
975

976
        // We participate a nonce ourselves, so we can't have more nonces than
977
        // the total number of participants minus ourselves.
978
        maxNonces := len(in.AllSignerPubkeys) - 1
×
979
        if len(in.OtherSignerPublicNonces) > maxNonces {
×
980
                return nil, fmt.Errorf("too many other signer public nonces, "+
×
981
                        "got %d but expected a maximum of %d",
×
982
                        len(in.OtherSignerPublicNonces), maxNonces)
×
983
        }
×
984

985
        var localNonces *musig2.Nonces
×
986

×
987
        // If the pre generated local nonces were specified, then check to make
×
988
        // sure they're the correct size and format.
×
989
        nonceLen := len(in.PregeneratedLocalNonce)
×
990
        switch {
×
991
        case nonceLen != 0 && nonceLen != musig2.SecNonceSize:
×
992
                return nil, fmt.Errorf("local nonces must be %v bytes, "+
×
993
                        "instead was %v", musig2.SecNonceSize, nonceLen)
×
994

995
        case nonceLen == musig2.SecNonceSize:
×
996
                var secNonce [musig2.SecNonceSize]byte
×
997
                copy(secNonce[:], in.PregeneratedLocalNonce)
×
998

×
999
                localNonces = &musig2.Nonces{
×
1000
                        SecNonce: secNonce,
×
1001
                        PubNonce: secNonceToPubNonce(secNonce),
×
1002
                }
×
1003
        }
1004

1005
        // Parse all other nonces we might already know.
1006
        otherSignerNonces, err := parseMuSig2PublicNonces(
×
1007
                in.OtherSignerPublicNonces, true,
×
1008
        )
×
1009
        if err != nil {
×
1010
                return nil, fmt.Errorf("error parsing other nonces: %w", err)
×
1011
        }
×
1012

1013
        // Are there any tweaks to apply to the combined public key?
1014
        tweaks, err := UnmarshalTweaks(in.Tweaks, in.TaprootTweak)
×
1015
        if err != nil {
×
1016
                return nil, fmt.Errorf("error unmarshaling tweak options: %w",
×
1017
                        err)
×
1018
        }
×
1019

1020
        // Register the session with the internal wallet/signer now.
1021
        session, err := s.cfg.Signer.MuSig2CreateSession(
×
1022
                version, keyLoc, allSignerPubKeys, tweaks, otherSignerNonces,
×
1023
                localNonces,
×
1024
        )
×
1025
        if err != nil {
×
1026
                return nil, fmt.Errorf("error registering session: %w", err)
×
1027
        }
×
1028

1029
        var internalKeyBytes []byte
×
1030
        if session.TaprootTweak {
×
1031
                internalKeyBytes = schnorr.SerializePubKey(
×
1032
                        session.TaprootInternalKey,
×
1033
                )
×
1034
        }
×
1035

1036
        return &MuSig2SessionResponse{
×
1037
                SessionId: session.SessionID[:],
×
1038
                CombinedKey: schnorr.SerializePubKey(
×
1039
                        session.CombinedKey,
×
1040
                ),
×
1041
                TaprootInternalKey: internalKeyBytes,
×
1042
                LocalPublicNonces:  session.PublicNonce[:],
×
1043
                HaveAllNonces:      session.HaveAllNonces,
×
1044
                Version:            in.Version,
×
1045
        }, nil
×
1046
}
1047

1048
// MuSig2RegisterNonces registers one or more public nonces of other signing
1049
// participants for a session identified by its ID.
1050
func (s *Server) MuSig2RegisterNonces(_ context.Context,
1051
        in *MuSig2RegisterNoncesRequest) (*MuSig2RegisterNoncesResponse, error) {
×
1052

×
1053
        // Check session ID length.
×
1054
        sessionID, err := parseMuSig2SessionID(in.SessionId)
×
1055
        if err != nil {
×
1056
                return nil, fmt.Errorf("error parsing session ID: %w", err)
×
1057
        }
×
1058

1059
        // Parse the other signing participants' nonces. We can't validate the
1060
        // number of nonces here because we don't have access to the session in
1061
        // this context. But the signer will be able to make sure we don't
1062
        // register more nonces than there are signers (which would mean
1063
        // something is wrong in the signing setup). But we want at least a
1064
        // single nonce for each call.
1065
        otherSignerNonces, err := parseMuSig2PublicNonces(
×
1066
                in.OtherSignerPublicNonces, false,
×
1067
        )
×
1068
        if err != nil {
×
1069
                return nil, fmt.Errorf("error parsing other nonces: %w", err)
×
1070
        }
×
1071

1072
        // Register the nonces now.
1073
        haveAllNonces, err := s.cfg.Signer.MuSig2RegisterNonces(
×
1074
                sessionID, otherSignerNonces,
×
1075
        )
×
1076
        if err != nil {
×
1077
                return nil, fmt.Errorf("error registering nonces: %w", err)
×
1078
        }
×
1079

1080
        return &MuSig2RegisterNoncesResponse{HaveAllNonces: haveAllNonces}, nil
×
1081
}
1082

1083
// MuSig2Sign creates a partial signature using the local signing key that was
1084
// specified when the session was created. This can only be called when all
1085
// public nonces of all participants are known and have been registered with
1086
// the session. If this node isn't responsible for combining all the partial
1087
// signatures, then the cleanup flag should be set, indicating that the session
1088
// can be removed from memory once the signature was produced.
1089
func (s *Server) MuSig2Sign(_ context.Context,
1090
        in *MuSig2SignRequest) (*MuSig2SignResponse, error) {
×
1091

×
1092
        // Check session ID length.
×
1093
        sessionID, err := parseMuSig2SessionID(in.SessionId)
×
1094
        if err != nil {
×
1095
                return nil, fmt.Errorf("error parsing session ID: %w", err)
×
1096
        }
×
1097

1098
        // Schnorr signatures only work reliably if the message is 32 bytes.
1099
        msg := [sha256.Size]byte{}
×
1100
        if len(in.MessageDigest) != sha256.Size {
×
1101
                return nil, fmt.Errorf("invalid message digest size, got %d "+
×
1102
                        "but expected %d", len(in.MessageDigest), sha256.Size)
×
1103
        }
×
1104
        copy(msg[:], in.MessageDigest)
×
1105

×
1106
        // Create our own partial signature with the local signing key.
×
1107
        partialSig, err := s.cfg.Signer.MuSig2Sign(sessionID, msg, in.Cleanup)
×
1108
        if err != nil {
×
1109
                return nil, fmt.Errorf("error signing: %w", err)
×
1110
        }
×
1111

1112
        serializedPartialSig, err := input.SerializePartialSignature(partialSig)
×
1113
        if err != nil {
×
1114
                return nil, fmt.Errorf("error serializing sig: %w", err)
×
1115
        }
×
1116

1117
        return &MuSig2SignResponse{
×
1118
                LocalPartialSignature: serializedPartialSig[:],
×
1119
        }, nil
×
1120
}
1121

1122
// MuSig2CombineSig combines the given partial signature(s) with the local one,
1123
// if it already exists. Once a partial signature of all participants is
1124
// registered, the final signature will be combined and returned.
1125
func (s *Server) MuSig2CombineSig(_ context.Context,
1126
        in *MuSig2CombineSigRequest) (*MuSig2CombineSigResponse, error) {
×
1127

×
1128
        // Check session ID length.
×
1129
        sessionID, err := parseMuSig2SessionID(in.SessionId)
×
1130
        if err != nil {
×
1131
                return nil, fmt.Errorf("error parsing session ID: %w", err)
×
1132
        }
×
1133

1134
        // Parse all other signatures. This can be called multiple times, so we
1135
        // can't really sanity check how many we already have vs. how many the
1136
        // user supplied in this call.
1137
        partialSigs, err := parseMuSig2PartialSignatures(
×
1138
                in.OtherPartialSignatures,
×
1139
        )
×
1140
        if err != nil {
×
1141
                return nil, fmt.Errorf("error parsing partial signatures: %w",
×
1142
                        err)
×
1143
        }
×
1144

1145
        // Combine the signatures now, potentially getting the final, full
1146
        // signature if we've already got all partial ones.
1147
        finalSig, haveAllSigs, err := s.cfg.Signer.MuSig2CombineSig(
×
1148
                sessionID, partialSigs,
×
1149
        )
×
1150
        if err != nil {
×
1151
                return nil, fmt.Errorf("error combining signatures: %w", err)
×
1152
        }
×
1153

1154
        resp := &MuSig2CombineSigResponse{
×
1155
                HaveAllSignatures: haveAllSigs,
×
1156
        }
×
1157

×
1158
        if haveAllSigs {
×
1159
                resp.FinalSignature = finalSig.Serialize()
×
1160
        }
×
1161

1162
        return resp, err
×
1163
}
1164

1165
// MuSig2Cleanup removes a session from memory to free up resources.
1166
func (s *Server) MuSig2Cleanup(_ context.Context,
1167
        in *MuSig2CleanupRequest) (*MuSig2CleanupResponse, error) {
×
1168

×
1169
        // Check session ID length.
×
1170
        sessionID, err := parseMuSig2SessionID(in.SessionId)
×
1171
        if err != nil {
×
1172
                return nil, fmt.Errorf("error parsing session ID: %w", err)
×
1173
        }
×
1174

1175
        err = s.cfg.Signer.MuSig2Cleanup(sessionID)
×
1176
        if err != nil {
×
1177
                return nil, fmt.Errorf("error cleaning up session: %w", err)
×
1178
        }
×
1179

1180
        return &MuSig2CleanupResponse{}, nil
×
1181
}
1182

1183
// parseRawKeyBytes checks that the provided raw public key is valid and returns
1184
// the public key. A nil public key is returned if the length of the rawKeyBytes
1185
// is zero.
1186
func parseRawKeyBytes(rawKeyBytes []byte) (*btcec.PublicKey, error) {
×
1187
        switch {
×
1188
        case len(rawKeyBytes) == 33:
×
1189
                // If a proper raw key was provided, then we'll attempt
×
1190
                // to decode and parse it.
×
1191
                return btcec.ParsePubKey(rawKeyBytes)
×
1192

1193
        case len(rawKeyBytes) == 0:
×
1194
                // No key is provided, return nil.
×
1195
                return nil, nil
×
1196

1197
        default:
×
1198
                // If the user provided a raw key, but it's of the
×
1199
                // wrong length, then we'll return with an error.
×
1200
                return nil, fmt.Errorf("pubkey must be " +
×
1201
                        "serialized in compressed format if " +
×
1202
                        "specified")
×
1203
        }
1204
}
1205

1206
// parseMuSig2SessionID parses a MuSig2 session ID from a raw byte slice.
1207
func parseMuSig2SessionID(rawID []byte) (input.MuSig2SessionID, error) {
×
1208
        sessionID := input.MuSig2SessionID{}
×
1209

×
1210
        // The session ID must be exact in its length.
×
1211
        if len(rawID) != sha256.Size {
×
1212
                return sessionID, fmt.Errorf("invalid session ID size, got "+
×
1213
                        "%d but expected %d", len(rawID), sha256.Size)
×
1214
        }
×
1215
        copy(sessionID[:], rawID)
×
1216

×
1217
        return sessionID, nil
×
1218
}
1219

1220
// parseMuSig2PublicNonces sanity checks and parses the other signers' public
1221
// nonces.
1222
func parseMuSig2PublicNonces(pubNonces [][]byte,
1223
        emptyAllowed bool) ([][musig2.PubNonceSize]byte, error) {
×
1224

×
1225
        // For some calls the nonces are optional while for others it doesn't
×
1226
        // make any sense to not specify them (for example for the explicit
×
1227
        // nonce registration call there should be at least one nonce).
×
1228
        if !emptyAllowed && len(pubNonces) == 0 {
×
1229
                return nil, fmt.Errorf("at least one other signer public " +
×
1230
                        "nonce is required")
×
1231
        }
×
1232

1233
        // Parse all other nonces. This can be called multiple times, so we
1234
        // can't really sanity check how many we already have vs. how many the
1235
        // user supplied in this call.
1236
        otherSignerNonces := make([][musig2.PubNonceSize]byte, len(pubNonces))
×
1237
        for idx, otherNonceBytes := range pubNonces {
×
1238
                if len(otherNonceBytes) != musig2.PubNonceSize {
×
1239
                        return nil, fmt.Errorf("invalid public nonce at "+
×
1240
                                "index %d: invalid length, got %d but "+
×
1241
                                "expected %d", idx, len(otherNonceBytes),
×
1242
                                musig2.PubNonceSize)
×
1243
                }
×
1244
                copy(otherSignerNonces[idx][:], otherNonceBytes)
×
1245
        }
1246

1247
        return otherSignerNonces, nil
×
1248
}
1249

1250
// parseMuSig2PartialSignatures sanity checks and parses the other signers'
1251
// partial signatures.
1252
func parseMuSig2PartialSignatures(
1253
        partialSignatures [][]byte) ([]*musig2.PartialSignature, error) {
×
1254

×
1255
        // We always want at least one partial signature.
×
1256
        if len(partialSignatures) == 0 {
×
1257
                return nil, fmt.Errorf("at least one partial signature is " +
×
1258
                        "required")
×
1259
        }
×
1260

1261
        parsedPartialSigs := make(
×
1262
                []*musig2.PartialSignature, len(partialSignatures),
×
1263
        )
×
1264
        for idx, otherPartialSigBytes := range partialSignatures {
×
1265
                sig, err := input.DeserializePartialSignature(
×
1266
                        otherPartialSigBytes,
×
1267
                )
×
1268
                if err != nil {
×
1269
                        return nil, fmt.Errorf("invalid partial signature at "+
×
1270
                                "index %d: %v", idx, err)
×
1271
                }
×
1272

1273
                parsedPartialSigs[idx] = sig
×
1274
        }
1275

1276
        return parsedPartialSigs, nil
×
1277
}
1278

1279
// UnmarshalTweaks parses the RPC tweak descriptions into their native
1280
// counterpart.
1281
func UnmarshalTweaks(rpcTweaks []*TweakDesc,
1282
        taprootTweak *TaprootTweakDesc) (*input.MuSig2Tweaks, error) {
×
1283

×
1284
        // Parse the generic tweaks first.
×
1285
        tweaks := &input.MuSig2Tweaks{
×
1286
                GenericTweaks: make([]musig2.KeyTweakDesc, len(rpcTweaks)),
×
1287
        }
×
1288
        for idx, rpcTweak := range rpcTweaks {
×
1289
                if len(rpcTweak.Tweak) == 0 {
×
1290
                        return nil, fmt.Errorf("tweak cannot be empty")
×
1291
                }
×
1292

1293
                copy(tweaks.GenericTweaks[idx].Tweak[:], rpcTweak.Tweak)
×
1294
                tweaks.GenericTweaks[idx].IsXOnly = rpcTweak.IsXOnly
×
1295
        }
1296

1297
        // Now parse the taproot specific tweak.
1298
        if taprootTweak != nil {
×
1299
                if taprootTweak.KeySpendOnly {
×
1300
                        tweaks.TaprootBIP0086Tweak = true
×
1301
                } else {
×
1302
                        if len(taprootTweak.ScriptRoot) == 0 {
×
1303
                                return nil, fmt.Errorf("script root cannot " +
×
1304
                                        "be empty for non-keyspend")
×
1305
                        }
×
1306

1307
                        tweaks.TaprootTweak = taprootTweak.ScriptRoot
×
1308
                }
1309
        }
1310

1311
        return tweaks, nil
×
1312
}
1313

1314
// UnmarshalSignMethod parses the RPC sign method into the native counterpart.
1315
func UnmarshalSignMethod(rpcSignMethod SignMethod) (input.SignMethod, error) {
×
1316
        switch rpcSignMethod {
×
1317
        case SignMethod_SIGN_METHOD_WITNESS_V0:
×
1318
                return input.WitnessV0SignMethod, nil
×
1319

1320
        case SignMethod_SIGN_METHOD_TAPROOT_KEY_SPEND_BIP0086:
×
1321
                return input.TaprootKeySpendBIP0086SignMethod, nil
×
1322

1323
        case SignMethod_SIGN_METHOD_TAPROOT_KEY_SPEND:
×
1324
                return input.TaprootKeySpendSignMethod, nil
×
1325

1326
        case SignMethod_SIGN_METHOD_TAPROOT_SCRIPT_SPEND:
×
1327
                return input.TaprootScriptSpendSignMethod, nil
×
1328

1329
        default:
×
1330
                return 0, fmt.Errorf("unknown RPC sign method <%d>",
×
1331
                        rpcSignMethod)
×
1332
        }
1333
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc