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

lightningnetwork / lnd / 14000719599

21 Mar 2025 08:54PM UTC coverage: 58.717% (-10.3%) from 68.989%
14000719599

Pull #8754

github

web-flow
Merge 29f363f18 into 5235f3b24
Pull Request #8754: Add `Outbound` Remote Signer implementation

1562 of 2088 new or added lines in 41 files covered. (74.81%)

28126 existing lines in 464 files now uncovered.

97953 of 166822 relevant lines covered (58.72%)

1.82 hits per line

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

73.01
/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
        "sync/atomic"
14

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

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

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

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

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

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

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

117
// Server is a sub-server of the main RPC server: the signer RPC. This sub RPC
118
// server allows external callers to access the full signing capabilities of
119
// lnd. This allows callers to create custom protocols, external to lnd, even
120
// backed by multiple distinct lnd across independent failure domains.
121
type Server struct {
122
        injected int32 // To be used atomically.
123

124
        // Required by the grpc-gateway/v2 library for forward compatibility.
125
        UnimplementedSignerServer
126

127
        cfg *Config
128
}
129

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

134
// New returns a new instance of the signrpc Signer sub-server. We also return
135
// the set of permissions for the macaroons that we may create within this
136
// method. If the macaroons we need aren't found in the filepath, then we'll
137
// create them on start up. If we're unable to locate, or create the macaroons
138
// we need, then we'll return with an error.
139
func New() (*Server, lnrpc.MacaroonPerms, error) {
3✔
140
        return &Server{cfg: &Config{}}, macPermissions, nil
3✔
141
}
3✔
142

143
// Stop signals any active goroutines for a graceful closure.
144
//
145
// NOTE: This is part of the lnrpc.SubServer interface.
146
func (s *Server) Stop() error {
3✔
147
        return nil
3✔
148
}
3✔
149

150
// InjectDependencies populates the sub-server's dependencies. If the
151
// finalizeDependencies boolean is true, then the sub-server will finalize its
152
// dependencies and return an error if any required dependencies are missing.
153
//
154
// NOTE: This is part of the lnrpc.SubServer interface.
155
func (s *Server) InjectDependencies(
156
        configRegistry lnrpc.SubServerConfigDispatcher,
157
        finalizeDependencies bool) error {
3✔
158

3✔
159
        if finalizeDependencies && atomic.AddInt32(&s.injected, 1) != 1 {
3✔
NEW
160
                return lnrpc.ErrDependenciesFinalized
×
NEW
161
        }
×
162

163
        cfg, err := getConfig(configRegistry, finalizeDependencies)
3✔
164
        if err != nil {
3✔
NEW
165
                return err
×
NEW
166
        }
×
167

168
        if finalizeDependencies {
6✔
169
                s.cfg = cfg
3✔
170

3✔
171
                return nil
3✔
172
        }
3✔
173

174
        // If the path of the signer macaroon wasn't generated, then we'll
175
        // assume that it's found at the default network directory.
UNCOV
176
        if cfg.SignerMacPath == "" {
×
UNCOV
177
                cfg.SignerMacPath = filepath.Join(
×
UNCOV
178
                        cfg.NetworkDir, DefaultSignerMacFilename,
×
UNCOV
179
                )
×
UNCOV
180
        }
×
181

182
        // Now that we know the full path of the signer macaroon, we can check
183
        // to see if we need to create it or not. If stateless_init is set
184
        // then we don't write the macaroons.
UNCOV
185
        macFilePath := cfg.SignerMacPath
×
UNCOV
186
        if cfg.MacService != nil && !cfg.MacService.StatelessInit &&
×
UNCOV
187
                !lnrpc.FileExists(macFilePath) {
×
UNCOV
188

×
UNCOV
189
                log.Infof("Making macaroons for Signer RPC Server at: %v",
×
UNCOV
190
                        macFilePath)
×
UNCOV
191

×
UNCOV
192
                // At this point, we know that the signer macaroon doesn't yet,
×
UNCOV
193
                // exist, so we need to create it with the help of the main
×
UNCOV
194
                // macaroon service.
×
UNCOV
195
                signerMac, err := cfg.MacService.NewMacaroon(
×
UNCOV
196
                        context.Background(), macaroons.DefaultRootKeyID,
×
UNCOV
197
                        macaroonOps...,
×
UNCOV
198
                )
×
UNCOV
199
                if err != nil {
×
NEW
200
                        return err
×
201
                }
×
UNCOV
202
                signerMacBytes, err := signerMac.M().MarshalBinary()
×
UNCOV
203
                if err != nil {
×
NEW
204
                        return err
×
205
                }
×
UNCOV
206
                err = os.WriteFile(macFilePath, signerMacBytes, 0644)
×
UNCOV
207
                if err != nil {
×
208
                        _ = os.Remove(macFilePath)
×
NEW
209
                        return err
×
210
                }
×
211
        }
212

NEW
213
        s.cfg = cfg
×
UNCOV
214

×
UNCOV
215
        return nil
×
216
}
217

218
// Name returns a unique string representation of the sub-server. This can be
219
// used to identify the sub-server and also de-duplicate them.
220
//
221
// NOTE: This is part of the lnrpc.SubServer interface.
222
func (s *Server) Name() string {
3✔
223
        return SubServerName
3✔
224
}
3✔
225

226
// RegisterWithRootServer will be called by the root gRPC server to direct a
227
// sub RPC server to register itself with the main gRPC root server. Until this
228
// is called, each sub-server won't be able to have
229
// requests routed towards it.
230
//
231
// NOTE: This is part of the lnrpc.GrpcHandler interface.
232
func (r *ServerShell) RegisterWithRootServer(grpcServer *grpc.Server) error {
3✔
233
        // We make sure that we register it with the main gRPC server to ensure
3✔
234
        // all our methods are routed properly.
3✔
235
        RegisterSignerServer(grpcServer, r)
3✔
236

3✔
237
        log.Debugf("Signer RPC server successfully registered with root gRPC " +
3✔
238
                "server")
3✔
239

3✔
240
        return nil
3✔
241
}
3✔
242

243
// RegisterWithRestServer will be called by the root REST mux to direct a sub
244
// RPC server to register itself with the main REST mux server. Until this is
245
// called, each sub-server won't be able to have requests routed towards it.
246
//
247
// NOTE: This is part of the lnrpc.GrpcHandler interface.
248
func (r *ServerShell) RegisterWithRestServer(ctx context.Context,
249
        mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error {
3✔
250

3✔
251
        // We make sure that we register it with the main REST server to ensure
3✔
252
        // all our methods are routed properly.
3✔
253
        err := RegisterSignerHandlerFromEndpoint(ctx, mux, dest, opts)
3✔
254
        if err != nil {
3✔
255
                log.Errorf("Could not register Signer REST server "+
×
256
                        "with root REST server: %v", err)
×
257
                return err
×
258
        }
×
259

260
        log.Debugf("Signer REST server successfully registered with " +
3✔
261
                "root REST server")
3✔
262
        return nil
3✔
263
}
264

265
// CreateSubServer creates an instance of the sub-server, and returns the
266
// macaroon permissions that the sub-server wishes to pass on to the root server
267
// for all methods routed towards it.
268
//
269
// NOTE: This is part of the lnrpc.GrpcHandler interface.
270
func (r *ServerShell) CreateSubServer() (
271
        lnrpc.SubServer, lnrpc.MacaroonPerms, error) {
3✔
272

3✔
273
        subServer, macPermissions, err := New()
3✔
274
        if err != nil {
3✔
275
                return nil, nil, err
×
276
        }
×
277

278
        r.SignerServer = subServer
3✔
279
        return subServer, macPermissions, nil
3✔
280
}
281

282
// SignOutputRaw generates a signature for the passed transaction according to
283
// the data within the passed SignReq. If we're unable to find the keys that
284
// correspond to the KeyLocators in the SignReq then we'll return an error.
285
// Additionally, if the user doesn't provide the set of required parameters, or
286
// provides an invalid transaction, then we'll return with an error.
287
//
288
// NOTE: The resulting signature should be void of a sighash byte.
289
func (s *Server) SignOutputRaw(_ context.Context, in *SignReq) (*SignResp,
290
        error) {
3✔
291

3✔
292
        switch {
3✔
293
        // If the client doesn't specify a transaction, then there's nothing to
294
        // sign, so we'll exit early.
295
        case len(in.RawTxBytes) == 0:
×
296
                return nil, fmt.Errorf("a transaction to sign MUST be " +
×
297
                        "passed in")
×
298

299
        // If the client doesn't tell us *how* to sign the transaction, then we
300
        // can't sign anything, so we'll exit early.
301
        case len(in.SignDescs) == 0:
×
302
                return nil, fmt.Errorf("at least one SignDescs MUST be " +
×
303
                        "passed in")
×
304
        }
305

306
        // Now that we know we have an actual transaction to decode, we'll
307
        // deserialize it into something that we can properly utilize.
308
        var (
3✔
309
                txToSign wire.MsgTx
3✔
310
                err      error
3✔
311
        )
3✔
312
        txReader := bytes.NewReader(in.RawTxBytes)
3✔
313
        if err := txToSign.Deserialize(txReader); err != nil {
3✔
314
                return nil, fmt.Errorf("unable to decode tx: %w", err)
×
315
        }
×
316

317
        var (
3✔
318
                sigHashCache      = input.NewTxSigHashesV0Only(&txToSign)
3✔
319
                prevOutputFetcher = txscript.NewMultiPrevOutFetcher(nil)
3✔
320
        )
3✔
321

3✔
322
        // If we're spending one or more SegWit v1 (Taproot) inputs, then we
3✔
323
        // need the full UTXO information available.
3✔
324
        if len(in.PrevOutputs) > 0 {
6✔
325
                if len(in.PrevOutputs) != len(txToSign.TxIn) {
3✔
326
                        return nil, fmt.Errorf("provided previous outputs " +
×
327
                                "doesn't match number of transaction inputs")
×
328
                }
×
329

330
                // Add all previous inputs to our sighash prev out fetcher so we
331
                // can calculate the sighash correctly.
332
                for idx, txIn := range txToSign.TxIn {
6✔
333
                        prevOutputFetcher.AddPrevOut(
3✔
334
                                txIn.PreviousOutPoint, &wire.TxOut{
3✔
335
                                        Value:    in.PrevOutputs[idx].Value,
3✔
336
                                        PkScript: in.PrevOutputs[idx].PkScript,
3✔
337
                                },
3✔
338
                        )
3✔
339
                }
3✔
340
                sigHashCache = txscript.NewTxSigHashes(
3✔
341
                        &txToSign, prevOutputFetcher,
3✔
342
                )
3✔
343
        }
344

345
        log.Debugf("Generating sigs for %v inputs: ", len(in.SignDescs))
3✔
346

3✔
347
        // With the transaction deserialized, we'll now convert sign descs so
3✔
348
        // we can feed it into the actual signer.
3✔
349
        signDescs := make([]*input.SignDescriptor, 0, len(in.SignDescs))
3✔
350
        for _, signDesc := range in.SignDescs {
6✔
351
                keyDesc := signDesc.KeyDesc
3✔
352

3✔
353
                // The caller can either specify the key using the raw pubkey,
3✔
354
                // or the description of the key. We'll still attempt to parse
3✔
355
                // both if both were provided however, to ensure the underlying
3✔
356
                // SignOutputRaw has as much information as possible.
3✔
357
                var (
3✔
358
                        targetPubKey *btcec.PublicKey
3✔
359
                        keyLoc       keychain.KeyLocator
3✔
360
                )
3✔
361

3✔
362
                // If this method doesn't return nil, then we know that user is
3✔
363
                // attempting to include a raw serialized pub key.
3✔
364
                if keyDesc.GetRawKeyBytes() != nil {
6✔
365
                        targetPubKey, err = parseRawKeyBytes(
3✔
366
                                keyDesc.GetRawKeyBytes(),
3✔
367
                        )
3✔
368
                        if err != nil {
3✔
369
                                return nil, err
×
370
                        }
×
371
                }
372

373
                // Similarly, if they specified a key locator, then we'll parse
374
                // that as well.
375
                if keyDesc.GetKeyLoc() != nil {
6✔
376
                        protoLoc := keyDesc.GetKeyLoc()
3✔
377
                        keyLoc = keychain.KeyLocator{
3✔
378
                                Family: keychain.KeyFamily(
3✔
379
                                        protoLoc.KeyFamily,
3✔
380
                                ),
3✔
381
                                Index: uint32(protoLoc.KeyIndex),
3✔
382
                        }
3✔
383
                }
3✔
384

385
                // Check what sign method was selected by the user so, we know
386
                // exactly what we're expecting and can prevent some of the more
387
                // obvious usage errors.
388
                signMethod, err := UnmarshalSignMethod(signDesc.SignMethod)
3✔
389
                if err != nil {
3✔
390
                        return nil, fmt.Errorf("unable to unmarshal sign "+
×
391
                                "method: %v", err)
×
392
                }
×
393
                if !signMethod.PkScriptCompatible(signDesc.Output.PkScript) {
6✔
394
                        return nil, fmt.Errorf("selected sign method %v is "+
3✔
395
                                "not compatible with given pk script %x",
3✔
396
                                signMethod, signDesc.Output.PkScript)
3✔
397
                }
3✔
398

399
                // Perform input validation according to the sign method. Not
400
                // all methods require the same fields to be provided.
401
                switch signMethod {
3✔
402
                case input.WitnessV0SignMethod:
3✔
403
                        // If a witness script isn't passed, then we can't
3✔
404
                        // proceed, as in the p2wsh case, we can't properly
3✔
405
                        // generate the sighash. A P2WKH doesn't need a witness
3✔
406
                        // script. But SignOutputRaw still needs to know the PK
3✔
407
                        // script that was used for the output. We'll send it in
3✔
408
                        // the WitnessScript field, the SignOutputRaw RPC will
3✔
409
                        // know what to do with it when creating the sighash.
3✔
410
                        if len(signDesc.WitnessScript) == 0 {
3✔
411
                                return nil, fmt.Errorf("witness script MUST " +
×
412
                                        "be specified for segwit v0 sign " +
×
413
                                        "method")
×
414
                        }
×
415

416
                case input.TaprootKeySpendBIP0086SignMethod:
3✔
417
                        if len(signDesc.TapTweak) > 0 {
3✔
418
                                return nil, fmt.Errorf("tap tweak must be " +
×
419
                                        "empty for BIP0086 key spend")
×
420
                        }
×
421

422
                case input.TaprootKeySpendSignMethod:
3✔
423
                        if len(signDesc.TapTweak) != sha256.Size {
3✔
424
                                return nil, fmt.Errorf("tap tweak must be " +
×
425
                                        "specified for key spend with root " +
×
426
                                        "hash")
×
427
                        }
×
428

429
                case input.TaprootScriptSpendSignMethod:
3✔
430
                        if len(signDesc.WitnessScript) == 0 {
3✔
431
                                return nil, fmt.Errorf("witness script MUST " +
×
432
                                        "be specified for taproot script " +
×
433
                                        "spend method")
×
434
                        }
×
435
                }
436

437
                // If the users provided a double tweak, then we'll need to
438
                // parse that out now to ensure their input is properly signed.
439
                var tweakPrivKey *btcec.PrivateKey
3✔
440
                if len(signDesc.DoubleTweak) != 0 {
3✔
441
                        tweakPrivKey, _ = btcec.PrivKeyFromBytes(
×
442
                                signDesc.DoubleTweak,
×
443
                        )
×
444
                }
×
445

446
                // Finally, with verification and parsing complete, we can
447
                // construct the final sign descriptor to generate the proper
448
                // signature for this input.
449
                signDescs = append(signDescs, &input.SignDescriptor{
3✔
450
                        KeyDesc: keychain.KeyDescriptor{
3✔
451
                                KeyLocator: keyLoc,
3✔
452
                                PubKey:     targetPubKey,
3✔
453
                        },
3✔
454
                        SingleTweak:   signDesc.SingleTweak,
3✔
455
                        DoubleTweak:   tweakPrivKey,
3✔
456
                        TapTweak:      signDesc.TapTweak,
3✔
457
                        WitnessScript: signDesc.WitnessScript,
3✔
458
                        SignMethod:    signMethod,
3✔
459
                        Output: &wire.TxOut{
3✔
460
                                Value:    signDesc.Output.Value,
3✔
461
                                PkScript: signDesc.Output.PkScript,
3✔
462
                        },
3✔
463
                        HashType:          txscript.SigHashType(signDesc.Sighash),
3✔
464
                        SigHashes:         sigHashCache,
3✔
465
                        InputIndex:        int(signDesc.InputIndex),
3✔
466
                        PrevOutputFetcher: prevOutputFetcher,
3✔
467
                })
3✔
468

3✔
469
                // Are we trying to sign for a Taproot output? Then we need all
3✔
470
                // previous outputs being declared, otherwise we'd run into a
3✔
471
                // panic later on.
3✔
472
                if txscript.IsPayToTaproot(signDesc.Output.PkScript) {
6✔
473
                        for idx, txIn := range txToSign.TxIn {
6✔
474
                                utxo := prevOutputFetcher.FetchPrevOutput(
3✔
475
                                        txIn.PreviousOutPoint,
3✔
476
                                )
3✔
477
                                if utxo == nil {
6✔
478
                                        return nil, fmt.Errorf("error signing "+
3✔
479
                                                "taproot output, transaction "+
3✔
480
                                                "input %d is missing its "+
3✔
481
                                                "previous outpoint information",
3✔
482
                                                idx)
3✔
483
                                }
3✔
484
                        }
485
                }
486
        }
487

488
        // Now that we've mapped all the proper sign descriptors, we can
489
        // request signatures for each of them, passing in the transaction to
490
        // be signed.
491
        numSigs := len(in.SignDescs)
3✔
492
        resp := &SignResp{
3✔
493
                RawSigs: make([][]byte, numSigs),
3✔
494
        }
3✔
495

3✔
496
        for i, signDesc := range signDescs {
6✔
497
                sig, err := s.cfg.Signer.SignOutputRaw(&txToSign, signDesc)
3✔
498
                if err != nil {
3✔
499
                        log.Errorf("unable to generate sig for input "+
×
500
                                "#%v: %v", i, err)
×
501

×
502
                        return nil, err
×
503
                }
×
504

505
                resp.RawSigs[i] = sig.Serialize()
3✔
506
        }
507

508
        return resp, nil
3✔
509
}
510

511
// ComputeInputScript generates a complete InputIndex for the passed
512
// transaction with the signature as defined within the passed SignDescriptor.
513
// This method should be capable of generating the proper input script for both
514
// regular p2wkh/p2tr outputs and p2wkh outputs nested within a regular p2sh
515
// output.
516
//
517
// Note that when using this method to sign inputs belonging to the wallet, the
518
// only items of the SignDescriptor that need to be populated are pkScript in
519
// the TxOut field, the value in that same field, and finally the input index.
520
func (s *Server) ComputeInputScript(ctx context.Context,
521
        in *SignReq) (*InputScriptResp, error) {
3✔
522

3✔
523
        switch {
3✔
524
        // If the client doesn't specify a transaction, then there's nothing to
525
        // sign, so we'll exit early.
526
        case len(in.RawTxBytes) == 0:
×
527
                return nil, fmt.Errorf("a transaction to sign MUST be " +
×
528
                        "passed in")
×
529

530
        // If the client doesn't tell us *how* to sign the transaction, then we
531
        // can't sign anything, so we'll exit early.
532
        case len(in.SignDescs) == 0:
×
533
                return nil, fmt.Errorf("at least one SignDescs MUST be " +
×
534
                        "passed in")
×
535
        }
536

537
        // Now that we know we have an actual transaction to decode, we'll
538
        // deserialize it into something that we can properly utilize.
539
        var txToSign wire.MsgTx
3✔
540
        txReader := bytes.NewReader(in.RawTxBytes)
3✔
541
        if err := txToSign.Deserialize(txReader); err != nil {
3✔
542
                return nil, fmt.Errorf("unable to decode tx: %w", err)
×
543
        }
×
544

545
        var (
3✔
546
                sigHashCache      = input.NewTxSigHashesV0Only(&txToSign)
3✔
547
                prevOutputFetcher = txscript.NewMultiPrevOutFetcher(nil)
3✔
548
        )
3✔
549

3✔
550
        // If we're spending one or more SegWit v1 (Taproot) inputs, then we
3✔
551
        // need the full UTXO information available.
3✔
552
        if len(in.PrevOutputs) > 0 {
6✔
553
                if len(in.PrevOutputs) != len(txToSign.TxIn) {
3✔
554
                        return nil, fmt.Errorf("provided previous outputs " +
×
555
                                "doesn't match number of transaction inputs")
×
556
                }
×
557

558
                // Add all previous inputs to our sighash prev out fetcher so we
559
                // can calculate the sighash correctly.
560
                for idx, txIn := range txToSign.TxIn {
6✔
561
                        prevOutputFetcher.AddPrevOut(
3✔
562
                                txIn.PreviousOutPoint, &wire.TxOut{
3✔
563
                                        Value:    in.PrevOutputs[idx].Value,
3✔
564
                                        PkScript: in.PrevOutputs[idx].PkScript,
3✔
565
                                },
3✔
566
                        )
3✔
567
                }
3✔
568
                sigHashCache = txscript.NewTxSigHashes(
3✔
569
                        &txToSign, prevOutputFetcher,
3✔
570
                )
3✔
571
        }
572

573
        signDescs := make([]*input.SignDescriptor, 0, len(in.SignDescs))
3✔
574
        for _, signDesc := range in.SignDescs {
6✔
575
                // For this method, the only fields that we care about are the
3✔
576
                // hash type, and the information concerning the output as we
3✔
577
                // only know how to provide full witnesses for outputs that we
3✔
578
                // solely control.
3✔
579
                signDescs = append(signDescs, &input.SignDescriptor{
3✔
580
                        Output: &wire.TxOut{
3✔
581
                                Value:    signDesc.Output.Value,
3✔
582
                                PkScript: signDesc.Output.PkScript,
3✔
583
                        },
3✔
584
                        HashType:          txscript.SigHashType(signDesc.Sighash),
3✔
585
                        SigHashes:         sigHashCache,
3✔
586
                        PrevOutputFetcher: prevOutputFetcher,
3✔
587
                        InputIndex:        int(signDesc.InputIndex),
3✔
588
                })
3✔
589
        }
3✔
590

591
        // With all of our signDescs assembled, we can now generate a valid
592
        // input script for each of them, and collate the responses to return
593
        // back to the caller.
594
        numWitnesses := len(in.SignDescs)
3✔
595
        resp := &InputScriptResp{
3✔
596
                InputScripts: make([]*InputScript, numWitnesses),
3✔
597
        }
3✔
598

3✔
599
        for i, signDesc := range signDescs {
6✔
600
                inputScript, err := s.cfg.Signer.ComputeInputScript(
3✔
601
                        &txToSign, signDesc,
3✔
602
                )
3✔
603
                if err != nil {
3✔
604
                        return nil, err
×
605
                }
×
606

607
                resp.InputScripts[i] = &InputScript{
3✔
608
                        Witness:   inputScript.Witness,
3✔
609
                        SigScript: inputScript.SigScript,
3✔
610
                }
3✔
611
        }
612

613
        return resp, nil
3✔
614
}
615

616
// SignMessage signs a message with the key specified in the key locator. The
617
// returned signature is fixed-size LN wire format encoded.
618
func (s *Server) SignMessage(_ context.Context,
619
        in *SignMessageReq) (*SignMessageResp, error) {
3✔
620

3✔
621
        if in.Msg == nil {
3✔
622
                return nil, fmt.Errorf("a message to sign MUST be passed in")
×
623
        }
×
624
        if in.KeyLoc == nil {
3✔
625
                return nil, fmt.Errorf("a key locator MUST be passed in")
×
626
        }
×
627
        if in.SchnorrSig && in.CompactSig {
3✔
628
                return nil, fmt.Errorf("compact format can not be used for " +
×
629
                        "Schnorr signatures")
×
630
        }
×
631
        if !in.SchnorrSig && len(in.Tag) > 0 {
6✔
632
                return nil, fmt.Errorf("tag can only be used when the " +
3✔
633
                        "Schnorr signature option is set")
3✔
634
        }
3✔
635
        if bytes.HasPrefix(in.Tag, []byte(BIP0340)) {
6✔
636
                return nil, fmt.Errorf("tag cannot have BIP0340 prefix")
3✔
637
        }
3✔
638
        if bytes.HasPrefix(in.Tag, chainhash.TagTapSighash) {
6✔
639
                return nil, fmt.Errorf("tag cannot be TapSighash")
3✔
640
        }
3✔
641
        if in.DoubleHash && len(in.Tag) > 0 {
3✔
642
                return nil, fmt.Errorf("double hash and tag can't be set at " +
×
643
                        "the same time")
×
644
        }
×
645

646
        // Describe the private key we'll be using for signing.
647
        keyLocator := keychain.KeyLocator{
3✔
648
                Family: keychain.KeyFamily(in.KeyLoc.KeyFamily),
3✔
649
                Index:  uint32(in.KeyLoc.KeyIndex),
3✔
650
        }
3✔
651

3✔
652
        // Use the schnorr signature algorithm to sign the message.
3✔
653
        if in.SchnorrSig {
6✔
654
                sig, err := s.cfg.KeyRing.SignMessageSchnorr(
3✔
655
                        keyLocator, in.Msg, in.DoubleHash,
3✔
656
                        in.SchnorrSigTapTweak, in.Tag,
3✔
657
                )
3✔
658
                if err != nil {
3✔
659
                        return nil, fmt.Errorf("can't sign the hash: %w", err)
×
660
                }
×
661

662
                sigParsed, err := schnorr.ParseSignature(sig.Serialize())
3✔
663
                if err != nil {
3✔
664
                        return nil, fmt.Errorf("can't parse Schnorr "+
×
665
                                "signature: %v", err)
×
666
                }
×
667

668
                return &SignMessageResp{
3✔
669
                        Signature: sigParsed.Serialize(),
3✔
670
                }, nil
3✔
671
        }
672

673
        // To allow a watch-only wallet to forward the SignMessageCompact to an
674
        // endpoint that doesn't add the message prefix, we allow this RPC to
675
        // also return the compact signature format instead of adding a flag to
676
        // the lnrpc.SignMessage call that removes the message prefix.
677
        if in.CompactSig {
6✔
678
                sigBytes, err := s.cfg.KeyRing.SignMessageCompact(
3✔
679
                        keyLocator, in.Msg, in.DoubleHash,
3✔
680
                )
3✔
681
                if err != nil {
3✔
682
                        return nil, fmt.Errorf("can't sign the hash: %w", err)
×
683
                }
×
684

685
                return &SignMessageResp{
3✔
686
                        Signature: sigBytes,
3✔
687
                }, nil
3✔
688
        }
689

690
        // Create the raw ECDSA signature first and convert it to the final wire
691
        // format after.
692
        sig, err := s.cfg.KeyRing.SignMessage(
3✔
693
                keyLocator, in.Msg, in.DoubleHash,
3✔
694
        )
3✔
695
        if err != nil {
3✔
696
                return nil, fmt.Errorf("can't sign the hash: %w", err)
×
697
        }
×
698
        wireSig, err := lnwire.NewSigFromSignature(sig)
3✔
699
        if err != nil {
3✔
700
                return nil, fmt.Errorf("can't convert to wire format: %w", err)
×
701
        }
×
702
        return &SignMessageResp{
3✔
703
                Signature: wireSig.ToSignatureBytes(),
3✔
704
        }, nil
3✔
705
}
706

707
// VerifyMessage verifies a signature over a message using the public key
708
// provided. The signature must be fixed-size LN wire format encoded.
709
func (s *Server) VerifyMessage(_ context.Context,
710
        in *VerifyMessageReq) (*VerifyMessageResp, error) {
3✔
711

3✔
712
        if in.Msg == nil {
3✔
713
                return nil, fmt.Errorf("a message to verify MUST be passed in")
×
714
        }
×
715
        if in.Signature == nil {
3✔
716
                return nil, fmt.Errorf("a signature to verify MUST be passed " +
×
717
                        "in")
×
718
        }
×
719
        if in.Pubkey == nil {
3✔
720
                return nil, fmt.Errorf("a pubkey to verify MUST be passed in")
×
721
        }
×
722
        if !in.IsSchnorrSig && len(in.Tag) > 0 {
6✔
723
                return nil, fmt.Errorf("tag can only be used when the " +
3✔
724
                        "Schnorr signature option is set")
3✔
725
        }
3✔
726

727
        // We allow for Schnorr signatures to be verified.
728
        if in.IsSchnorrSig {
6✔
729
                // We expect the public key to be in the BIP-340 32-byte format
3✔
730
                // for Schnorr signatures.
3✔
731
                pubkey, err := schnorr.ParsePubKey(in.Pubkey)
3✔
732
                if err != nil {
3✔
733
                        return nil, fmt.Errorf("unable to parse pubkey: %w",
×
734
                                err)
×
735
                }
×
736

737
                sigParsed, err := schnorr.ParseSignature(in.Signature)
3✔
738
                if err != nil {
3✔
739
                        return nil, fmt.Errorf("can't parse Schnorr "+
×
740
                                "signature: %w", err)
×
741
                }
×
742

743
                var digest []byte
3✔
744
                if len(in.Tag) == 0 {
6✔
745
                        digest = chainhash.HashB(in.Msg)
3✔
746
                } else {
6✔
747
                        taggedHash := chainhash.TaggedHash(in.Tag, in.Msg)
3✔
748
                        digest = taggedHash[:]
3✔
749
                }
3✔
750
                valid := sigParsed.Verify(digest, pubkey)
3✔
751

3✔
752
                return &VerifyMessageResp{
3✔
753
                        Valid: valid,
3✔
754
                }, nil
3✔
755
        }
756

757
        pubkey, err := btcec.ParsePubKey(in.Pubkey)
3✔
758
        if err != nil {
3✔
759
                return nil, fmt.Errorf("unable to parse pubkey: %w", err)
×
760
        }
×
761

762
        // The signature must be fixed-size LN wire format encoded.
763
        wireSig, err := lnwire.NewSigFromECDSARawSignature(in.Signature)
3✔
764
        if err != nil {
3✔
765
                return nil, fmt.Errorf("failed to decode signature: %w", err)
×
766
        }
×
767
        sig, err := wireSig.ToSignature()
3✔
768
        if err != nil {
3✔
769
                return nil, fmt.Errorf("failed to convert from wire format: %w",
×
770
                        err)
×
771
        }
×
772

773
        // The signature is over the sha256 hash of the message.
774
        digest := chainhash.HashB(in.Msg)
3✔
775
        valid := sig.Verify(digest, pubkey)
3✔
776
        return &VerifyMessageResp{
3✔
777
                Valid: valid,
3✔
778
        }, nil
3✔
779
}
780

781
// DeriveSharedKey returns a shared secret key by performing Diffie-Hellman key
782
// derivation between the ephemeral public key in the request and the node's
783
// key specified in the key_desc parameter. Either a key locator or a raw public
784
// key is expected in the key_desc, if neither is supplied, defaults to the
785
// node's identity private key. The old key_loc parameter in the request
786
// shouldn't be used anymore.
787
// The resulting shared public key is serialized in the compressed format and
788
// hashed with sha256, resulting in the final key length of 256bit.
789
func (s *Server) DeriveSharedKey(_ context.Context, in *SharedKeyRequest) (
790
        *SharedKeyResponse, error) {
3✔
791

3✔
792
        // Check that EphemeralPubkey is valid.
3✔
793
        ephemeralPubkey, err := parseRawKeyBytes(in.EphemeralPubkey)
3✔
794
        if err != nil {
3✔
795
                return nil, fmt.Errorf("error in ephemeral pubkey: %w", err)
×
796
        }
×
797
        if ephemeralPubkey == nil {
6✔
798
                return nil, fmt.Errorf("must provide ephemeral pubkey")
3✔
799
        }
3✔
800

801
        // Check for backward compatibility. The caller either specifies the old
802
        // key_loc field, or the new key_desc field, but not both.
803
        if in.KeyDesc != nil && in.KeyLoc != nil {
6✔
804
                return nil, fmt.Errorf("use either key_desc or key_loc")
3✔
805
        }
3✔
806

807
        // When key_desc is used, the key_desc.key_loc is expected as the caller
808
        // needs to specify the KeyFamily.
809
        if in.KeyDesc != nil && in.KeyDesc.KeyLoc == nil {
6✔
810
                return nil, fmt.Errorf("when setting key_desc the field " +
3✔
811
                        "key_desc.key_loc must also be set")
3✔
812
        }
3✔
813

814
        // We extract two params, rawKeyBytes and keyLoc. Notice their initial
815
        // values will be overwritten if not using the deprecated RPC param.
816
        var rawKeyBytes []byte
3✔
817
        keyLoc := in.KeyLoc
3✔
818
        if in.KeyDesc != nil {
6✔
819
                keyLoc = in.KeyDesc.GetKeyLoc()
3✔
820
                rawKeyBytes = in.KeyDesc.GetRawKeyBytes()
3✔
821
        }
3✔
822

823
        // When no keyLoc is supplied, defaults to the node's identity private
824
        // key.
825
        if keyLoc == nil {
6✔
826
                keyLoc = &KeyLocator{
3✔
827
                        KeyFamily: int32(keychain.KeyFamilyNodeKey),
3✔
828
                        KeyIndex:  0,
3✔
829
                }
3✔
830
        }
3✔
831

832
        // Check the caller is using either the key index or the raw public key
833
        // to perform the ECDH, we can't have both.
834
        if rawKeyBytes != nil && keyLoc.KeyIndex != 0 {
6✔
835
                return nil, fmt.Errorf("use either raw_key_bytes or key_index")
3✔
836
        }
3✔
837

838
        // Check the raw public key is valid. Notice that if the rawKeyBytes is
839
        // empty, the parseRawKeyBytes won't return an error, a nil
840
        // *btcec.PublicKey is returned instead.
841
        pk, err := parseRawKeyBytes(rawKeyBytes)
3✔
842
        if err != nil {
3✔
843
                return nil, fmt.Errorf("error in raw pubkey: %w", err)
×
844
        }
×
845

846
        // Create a key descriptor. When the KeyIndex is not specified, it uses
847
        // the empty value 0, and when the raw public key is not specified, the
848
        // pk is nil.
849
        keyDescriptor := keychain.KeyDescriptor{
3✔
850
                KeyLocator: keychain.KeyLocator{
3✔
851
                        Family: keychain.KeyFamily(keyLoc.KeyFamily),
3✔
852
                        Index:  uint32(keyLoc.KeyIndex),
3✔
853
                },
3✔
854
                PubKey: pk,
3✔
855
        }
3✔
856

3✔
857
        // Derive the shared key using ECDH and hashing the serialized
3✔
858
        // compressed shared point.
3✔
859
        sharedKeyHash, err := s.cfg.KeyRing.ECDH(keyDescriptor, ephemeralPubkey)
3✔
860
        if err != nil {
3✔
861
                err := fmt.Errorf("unable to derive shared key: %w", err)
×
862
                log.Error(err)
×
863
                return nil, err
×
864
        }
×
865

866
        return &SharedKeyResponse{SharedKey: sharedKeyHash[:]}, nil
3✔
867
}
868

869
// MuSig2CombineKeys combines the given set of public keys into a single
870
// combined MuSig2 combined public key, applying the given tweaks.
871
func (s *Server) MuSig2CombineKeys(_ context.Context,
872
        in *MuSig2CombineKeysRequest) (*MuSig2CombineKeysResponse, error) {
3✔
873

3✔
874
        // Check the now mandatory version first. We made the version mandatory,
3✔
875
        // so we don't get unexpected/undefined behavior for old clients that
3✔
876
        // don't specify the version. Since this API is still declared to be
3✔
877
        // experimental this should be the approach that leads to the least
3✔
878
        // amount of unexpected behavior.
3✔
879
        version, err := UnmarshalMuSig2Version(in.Version)
3✔
880
        if err != nil {
6✔
881
                return nil, fmt.Errorf("error parsing version: %w", err)
3✔
882
        }
3✔
883

884
        // Parse the public keys of all signing participants. This must also
885
        // include our own, local key.
886
        allSignerPubKeys, err := input.MuSig2ParsePubKeys(
3✔
887
                version, in.AllSignerPubkeys,
3✔
888
        )
3✔
889
        if err != nil {
3✔
890
                return nil, fmt.Errorf("error parsing all signer public "+
×
891
                        "keys: %w", err)
×
892
        }
×
893

894
        // Are there any tweaks to apply to the combined public key?
895
        tweaks, err := UnmarshalTweaks(in.Tweaks, in.TaprootTweak)
3✔
896
        if err != nil {
3✔
897
                return nil, fmt.Errorf("error unmarshaling tweak options: %w",
×
898
                        err)
×
899
        }
×
900

901
        // Combine the keys now without creating a session in memory.
902
        combinedKey, err := input.MuSig2CombineKeys(
3✔
903
                version, allSignerPubKeys, true, tweaks,
3✔
904
        )
3✔
905
        if err != nil {
3✔
906
                return nil, fmt.Errorf("error combining keys: %w", err)
×
907
        }
×
908

909
        var internalKeyBytes []byte
3✔
910
        if combinedKey.PreTweakedKey != nil {
6✔
911
                internalKeyBytes = schnorr.SerializePubKey(
3✔
912
                        combinedKey.PreTweakedKey,
3✔
913
                )
3✔
914
        }
3✔
915

916
        return &MuSig2CombineKeysResponse{
3✔
917
                CombinedKey: schnorr.SerializePubKey(
3✔
918
                        combinedKey.FinalKey,
3✔
919
                ),
3✔
920
                TaprootInternalKey: internalKeyBytes,
3✔
921
                Version:            in.Version,
3✔
922
        }, nil
3✔
923
}
924

925
// secNonceToPubNonce takes our two secret nonces, and produces their two
926
// corresponding EC points, serialized in compressed format.
927
//
928
// NOTE: This was copied from btcsuite/btcec/musig2/nonces.go.
929
func secNonceToPubNonce(secNonce [musig2.SecNonceSize]byte,
930
) [musig2.PubNonceSize]byte {
3✔
931

3✔
932
        var k1Mod, k2Mod btcec.ModNScalar
3✔
933
        k1Mod.SetByteSlice(secNonce[:btcec.PrivKeyBytesLen])
3✔
934
        k2Mod.SetByteSlice(secNonce[btcec.PrivKeyBytesLen:])
3✔
935

3✔
936
        var r1, r2 btcec.JacobianPoint
3✔
937
        btcec.ScalarBaseMultNonConst(&k1Mod, &r1)
3✔
938
        btcec.ScalarBaseMultNonConst(&k2Mod, &r2)
3✔
939

3✔
940
        // Next, we'll convert the key in jacobian format to a normal public
3✔
941
        // key expressed in affine coordinates.
3✔
942
        r1.ToAffine()
3✔
943
        r2.ToAffine()
3✔
944
        r1Pub := btcec.NewPublicKey(&r1.X, &r1.Y)
3✔
945
        r2Pub := btcec.NewPublicKey(&r2.X, &r2.Y)
3✔
946

3✔
947
        var pubNonce [musig2.PubNonceSize]byte
3✔
948

3✔
949
        // The public nonces are serialized as: R1 || R2, where both keys are
3✔
950
        // serialized in compressed format.
3✔
951
        copy(pubNonce[:], r1Pub.SerializeCompressed())
3✔
952
        copy(
3✔
953
                pubNonce[btcec.PubKeyBytesLenCompressed:],
3✔
954
                r2Pub.SerializeCompressed(),
3✔
955
        )
3✔
956

3✔
957
        return pubNonce
3✔
958
}
3✔
959

960
// MuSig2CreateSession creates a new MuSig2 signing session using the local
961
// key identified by the key locator. The complete list of all public keys of
962
// all signing parties must be provided, including the public key of the local
963
// signing key. If nonces of other parties are already known, they can be
964
// submitted as well to reduce the number of RPC calls necessary later on.
965
func (s *Server) MuSig2CreateSession(_ context.Context,
966
        in *MuSig2SessionRequest) (*MuSig2SessionResponse, error) {
3✔
967

3✔
968
        // Check the now mandatory version first. We made the version mandatory,
3✔
969
        // so we don't get unexpected/undefined behavior for old clients that
3✔
970
        // don't specify the version. Since this API is still declared to be
3✔
971
        // experimental this should be the approach that leads to the least
3✔
972
        // amount of unexpected behavior.
3✔
973
        version, err := UnmarshalMuSig2Version(in.Version)
3✔
974
        if err != nil {
6✔
975
                return nil, fmt.Errorf("error parsing version: %w", err)
3✔
976
        }
3✔
977

978
        // A key locator is always mandatory.
979
        if in.KeyLoc == nil {
3✔
980
                return nil, fmt.Errorf("missing key_loc")
×
981
        }
×
982
        keyLoc := keychain.KeyLocator{
3✔
983
                Family: keychain.KeyFamily(in.KeyLoc.KeyFamily),
3✔
984
                Index:  uint32(in.KeyLoc.KeyIndex),
3✔
985
        }
3✔
986

3✔
987
        // Parse the public keys of all signing participants. This must also
3✔
988
        // include our own, local key.
3✔
989
        allSignerPubKeys, err := input.MuSig2ParsePubKeys(
3✔
990
                version, in.AllSignerPubkeys,
3✔
991
        )
3✔
992
        if err != nil {
3✔
993
                return nil, fmt.Errorf("error parsing all signer public "+
×
994
                        "keys: %w", err)
×
995
        }
×
996

997
        // We participate a nonce ourselves, so we can't have more nonces than
998
        // the total number of participants minus ourselves.
999
        maxNonces := len(in.AllSignerPubkeys) - 1
3✔
1000
        if len(in.OtherSignerPublicNonces) > maxNonces {
3✔
1001
                return nil, fmt.Errorf("too many other signer public nonces, "+
×
1002
                        "got %d but expected a maximum of %d",
×
1003
                        len(in.OtherSignerPublicNonces), maxNonces)
×
1004
        }
×
1005

1006
        var localNonces *musig2.Nonces
3✔
1007

3✔
1008
        // If the pre generated local nonces were specified, then check to make
3✔
1009
        // sure they're the correct size and format.
3✔
1010
        nonceLen := len(in.PregeneratedLocalNonce)
3✔
1011
        switch {
3✔
1012
        case nonceLen != 0 && nonceLen != musig2.SecNonceSize:
×
1013
                return nil, fmt.Errorf("local nonces must be %v bytes, "+
×
1014
                        "instead was %v", musig2.SecNonceSize, nonceLen)
×
1015

1016
        case nonceLen == musig2.SecNonceSize:
3✔
1017
                var secNonce [musig2.SecNonceSize]byte
3✔
1018
                copy(secNonce[:], in.PregeneratedLocalNonce)
3✔
1019

3✔
1020
                localNonces = &musig2.Nonces{
3✔
1021
                        SecNonce: secNonce,
3✔
1022
                        PubNonce: secNonceToPubNonce(secNonce),
3✔
1023
                }
3✔
1024
        }
1025

1026
        // Parse all other nonces we might already know.
1027
        otherSignerNonces, err := parseMuSig2PublicNonces(
3✔
1028
                in.OtherSignerPublicNonces, true,
3✔
1029
        )
3✔
1030
        if err != nil {
3✔
1031
                return nil, fmt.Errorf("error parsing other nonces: %w", err)
×
1032
        }
×
1033

1034
        // Are there any tweaks to apply to the combined public key?
1035
        tweaks, err := UnmarshalTweaks(in.Tweaks, in.TaprootTweak)
3✔
1036
        if err != nil {
3✔
1037
                return nil, fmt.Errorf("error unmarshaling tweak options: %w",
×
1038
                        err)
×
1039
        }
×
1040

1041
        // Register the session with the internal wallet/signer now.
1042
        session, err := s.cfg.Signer.MuSig2CreateSession(
3✔
1043
                version, keyLoc, allSignerPubKeys, tweaks, otherSignerNonces,
3✔
1044
                localNonces,
3✔
1045
        )
3✔
1046
        if err != nil {
3✔
1047
                return nil, fmt.Errorf("error registering session: %w", err)
×
1048
        }
×
1049

1050
        var internalKeyBytes []byte
3✔
1051
        if session.TaprootTweak {
6✔
1052
                internalKeyBytes = schnorr.SerializePubKey(
3✔
1053
                        session.TaprootInternalKey,
3✔
1054
                )
3✔
1055
        }
3✔
1056

1057
        return &MuSig2SessionResponse{
3✔
1058
                SessionId: session.SessionID[:],
3✔
1059
                CombinedKey: schnorr.SerializePubKey(
3✔
1060
                        session.CombinedKey,
3✔
1061
                ),
3✔
1062
                TaprootInternalKey: internalKeyBytes,
3✔
1063
                LocalPublicNonces:  session.PublicNonce[:],
3✔
1064
                HaveAllNonces:      session.HaveAllNonces,
3✔
1065
                Version:            in.Version,
3✔
1066
        }, nil
3✔
1067
}
1068

1069
// MuSig2RegisterNonces registers one or more public nonces of other signing
1070
// participants for a session identified by its ID.
1071
func (s *Server) MuSig2RegisterNonces(_ context.Context,
1072
        in *MuSig2RegisterNoncesRequest) (*MuSig2RegisterNoncesResponse, error) {
3✔
1073

3✔
1074
        // Check session ID length.
3✔
1075
        sessionID, err := parseMuSig2SessionID(in.SessionId)
3✔
1076
        if err != nil {
3✔
1077
                return nil, fmt.Errorf("error parsing session ID: %w", err)
×
1078
        }
×
1079

1080
        // Parse the other signing participants' nonces. We can't validate the
1081
        // number of nonces here because we don't have access to the session in
1082
        // this context. But the signer will be able to make sure we don't
1083
        // register more nonces than there are signers (which would mean
1084
        // something is wrong in the signing setup). But we want at least a
1085
        // single nonce for each call.
1086
        otherSignerNonces, err := parseMuSig2PublicNonces(
3✔
1087
                in.OtherSignerPublicNonces, false,
3✔
1088
        )
3✔
1089
        if err != nil {
3✔
1090
                return nil, fmt.Errorf("error parsing other nonces: %w", err)
×
1091
        }
×
1092

1093
        // Register the nonces now.
1094
        haveAllNonces, err := s.cfg.Signer.MuSig2RegisterNonces(
3✔
1095
                sessionID, otherSignerNonces,
3✔
1096
        )
3✔
1097
        if err != nil {
3✔
1098
                return nil, fmt.Errorf("error registering nonces: %w", err)
×
1099
        }
×
1100

1101
        return &MuSig2RegisterNoncesResponse{HaveAllNonces: haveAllNonces}, nil
3✔
1102
}
1103

1104
// MuSig2Sign creates a partial signature using the local signing key that was
1105
// specified when the session was created. This can only be called when all
1106
// public nonces of all participants are known and have been registered with
1107
// the session. If this node isn't responsible for combining all the partial
1108
// signatures, then the cleanup flag should be set, indicating that the session
1109
// can be removed from memory once the signature was produced.
1110
func (s *Server) MuSig2Sign(_ context.Context,
1111
        in *MuSig2SignRequest) (*MuSig2SignResponse, error) {
3✔
1112

3✔
1113
        // Check session ID length.
3✔
1114
        sessionID, err := parseMuSig2SessionID(in.SessionId)
3✔
1115
        if err != nil {
3✔
1116
                return nil, fmt.Errorf("error parsing session ID: %w", err)
×
1117
        }
×
1118

1119
        // Schnorr signatures only work reliably if the message is 32 bytes.
1120
        msg := [sha256.Size]byte{}
3✔
1121
        if len(in.MessageDigest) != sha256.Size {
3✔
1122
                return nil, fmt.Errorf("invalid message digest size, got %d "+
×
1123
                        "but expected %d", len(in.MessageDigest), sha256.Size)
×
1124
        }
×
1125
        copy(msg[:], in.MessageDigest)
3✔
1126

3✔
1127
        // Create our own partial signature with the local signing key.
3✔
1128
        partialSig, err := s.cfg.Signer.MuSig2Sign(sessionID, msg, in.Cleanup)
3✔
1129
        if err != nil {
6✔
1130
                return nil, fmt.Errorf("error signing: %w", err)
3✔
1131
        }
3✔
1132

1133
        serializedPartialSig, err := input.SerializePartialSignature(partialSig)
3✔
1134
        if err != nil {
3✔
1135
                return nil, fmt.Errorf("error serializing sig: %w", err)
×
1136
        }
×
1137

1138
        return &MuSig2SignResponse{
3✔
1139
                LocalPartialSignature: serializedPartialSig[:],
3✔
1140
        }, nil
3✔
1141
}
1142

1143
// MuSig2CombineSig combines the given partial signature(s) with the local one,
1144
// if it already exists. Once a partial signature of all participants is
1145
// registered, the final signature will be combined and returned.
1146
func (s *Server) MuSig2CombineSig(_ context.Context,
1147
        in *MuSig2CombineSigRequest) (*MuSig2CombineSigResponse, error) {
3✔
1148

3✔
1149
        // Check session ID length.
3✔
1150
        sessionID, err := parseMuSig2SessionID(in.SessionId)
3✔
1151
        if err != nil {
3✔
1152
                return nil, fmt.Errorf("error parsing session ID: %w", err)
×
1153
        }
×
1154

1155
        // Parse all other signatures. This can be called multiple times, so we
1156
        // can't really sanity check how many we already have vs. how many the
1157
        // user supplied in this call.
1158
        partialSigs, err := parseMuSig2PartialSignatures(
3✔
1159
                in.OtherPartialSignatures,
3✔
1160
        )
3✔
1161
        if err != nil {
3✔
1162
                return nil, fmt.Errorf("error parsing partial signatures: %w",
×
1163
                        err)
×
1164
        }
×
1165

1166
        // Combine the signatures now, potentially getting the final, full
1167
        // signature if we've already got all partial ones.
1168
        finalSig, haveAllSigs, err := s.cfg.Signer.MuSig2CombineSig(
3✔
1169
                sessionID, partialSigs,
3✔
1170
        )
3✔
1171
        if err != nil {
3✔
1172
                return nil, fmt.Errorf("error combining signatures: %w", err)
×
1173
        }
×
1174

1175
        resp := &MuSig2CombineSigResponse{
3✔
1176
                HaveAllSignatures: haveAllSigs,
3✔
1177
        }
3✔
1178

3✔
1179
        if haveAllSigs {
6✔
1180
                resp.FinalSignature = finalSig.Serialize()
3✔
1181
        }
3✔
1182

1183
        return resp, err
3✔
1184
}
1185

1186
// MuSig2Cleanup removes a session from memory to free up resources.
1187
func (s *Server) MuSig2Cleanup(_ context.Context,
1188
        in *MuSig2CleanupRequest) (*MuSig2CleanupResponse, error) {
3✔
1189

3✔
1190
        // Check session ID length.
3✔
1191
        sessionID, err := parseMuSig2SessionID(in.SessionId)
3✔
1192
        if err != nil {
3✔
1193
                return nil, fmt.Errorf("error parsing session ID: %w", err)
×
1194
        }
×
1195

1196
        err = s.cfg.Signer.MuSig2Cleanup(sessionID)
3✔
1197
        if err != nil {
3✔
1198
                return nil, fmt.Errorf("error cleaning up session: %w", err)
×
1199
        }
×
1200

1201
        return &MuSig2CleanupResponse{}, nil
3✔
1202
}
1203

1204
// parseRawKeyBytes checks that the provided raw public key is valid and returns
1205
// the public key. A nil public key is returned if the length of the rawKeyBytes
1206
// is zero.
1207
func parseRawKeyBytes(rawKeyBytes []byte) (*btcec.PublicKey, error) {
3✔
1208
        switch {
3✔
1209
        case len(rawKeyBytes) == 33:
3✔
1210
                // If a proper raw key was provided, then we'll attempt
3✔
1211
                // to decode and parse it.
3✔
1212
                return btcec.ParsePubKey(rawKeyBytes)
3✔
1213

1214
        case len(rawKeyBytes) == 0:
3✔
1215
                // No key is provided, return nil.
3✔
1216
                return nil, nil
3✔
1217

1218
        default:
×
1219
                // If the user provided a raw key, but it's of the
×
1220
                // wrong length, then we'll return with an error.
×
1221
                return nil, fmt.Errorf("pubkey must be " +
×
1222
                        "serialized in compressed format if " +
×
1223
                        "specified")
×
1224
        }
1225
}
1226

1227
// parseMuSig2SessionID parses a MuSig2 session ID from a raw byte slice.
1228
func parseMuSig2SessionID(rawID []byte) (input.MuSig2SessionID, error) {
3✔
1229
        sessionID := input.MuSig2SessionID{}
3✔
1230

3✔
1231
        // The session ID must be exact in its length.
3✔
1232
        if len(rawID) != sha256.Size {
3✔
1233
                return sessionID, fmt.Errorf("invalid session ID size, got "+
×
1234
                        "%d but expected %d", len(rawID), sha256.Size)
×
1235
        }
×
1236
        copy(sessionID[:], rawID)
3✔
1237

3✔
1238
        return sessionID, nil
3✔
1239
}
1240

1241
// parseMuSig2PublicNonces sanity checks and parses the other signers' public
1242
// nonces.
1243
func parseMuSig2PublicNonces(pubNonces [][]byte,
1244
        emptyAllowed bool) ([][musig2.PubNonceSize]byte, error) {
3✔
1245

3✔
1246
        // For some calls the nonces are optional while for others it doesn't
3✔
1247
        // make any sense to not specify them (for example for the explicit
3✔
1248
        // nonce registration call there should be at least one nonce).
3✔
1249
        if !emptyAllowed && len(pubNonces) == 0 {
3✔
1250
                return nil, fmt.Errorf("at least one other signer public " +
×
1251
                        "nonce is required")
×
1252
        }
×
1253

1254
        // Parse all other nonces. This can be called multiple times, so we
1255
        // can't really sanity check how many we already have vs. how many the
1256
        // user supplied in this call.
1257
        otherSignerNonces := make([][musig2.PubNonceSize]byte, len(pubNonces))
3✔
1258
        for idx, otherNonceBytes := range pubNonces {
6✔
1259
                if len(otherNonceBytes) != musig2.PubNonceSize {
3✔
1260
                        return nil, fmt.Errorf("invalid public nonce at "+
×
1261
                                "index %d: invalid length, got %d but "+
×
1262
                                "expected %d", idx, len(otherNonceBytes),
×
1263
                                musig2.PubNonceSize)
×
1264
                }
×
1265
                copy(otherSignerNonces[idx][:], otherNonceBytes)
3✔
1266
        }
1267

1268
        return otherSignerNonces, nil
3✔
1269
}
1270

1271
// parseMuSig2PartialSignatures sanity checks and parses the other signers'
1272
// partial signatures.
1273
func parseMuSig2PartialSignatures(
1274
        partialSignatures [][]byte) ([]*musig2.PartialSignature, error) {
3✔
1275

3✔
1276
        // We always want at least one partial signature.
3✔
1277
        if len(partialSignatures) == 0 {
3✔
1278
                return nil, fmt.Errorf("at least one partial signature is " +
×
1279
                        "required")
×
1280
        }
×
1281

1282
        parsedPartialSigs := make(
3✔
1283
                []*musig2.PartialSignature, len(partialSignatures),
3✔
1284
        )
3✔
1285
        for idx, otherPartialSigBytes := range partialSignatures {
6✔
1286
                sig, err := input.DeserializePartialSignature(
3✔
1287
                        otherPartialSigBytes,
3✔
1288
                )
3✔
1289
                if err != nil {
3✔
1290
                        return nil, fmt.Errorf("invalid partial signature at "+
×
1291
                                "index %d: %v", idx, err)
×
1292
                }
×
1293

1294
                parsedPartialSigs[idx] = sig
3✔
1295
        }
1296

1297
        return parsedPartialSigs, nil
3✔
1298
}
1299

1300
// UnmarshalTweaks parses the RPC tweak descriptions into their native
1301
// counterpart.
1302
func UnmarshalTweaks(rpcTweaks []*TweakDesc,
1303
        taprootTweak *TaprootTweakDesc) (*input.MuSig2Tweaks, error) {
3✔
1304

3✔
1305
        // Parse the generic tweaks first.
3✔
1306
        tweaks := &input.MuSig2Tweaks{
3✔
1307
                GenericTweaks: make([]musig2.KeyTweakDesc, len(rpcTweaks)),
3✔
1308
        }
3✔
1309
        for idx, rpcTweak := range rpcTweaks {
3✔
1310
                if len(rpcTweak.Tweak) == 0 {
×
1311
                        return nil, fmt.Errorf("tweak cannot be empty")
×
1312
                }
×
1313

1314
                copy(tweaks.GenericTweaks[idx].Tweak[:], rpcTweak.Tweak)
×
1315
                tweaks.GenericTweaks[idx].IsXOnly = rpcTweak.IsXOnly
×
1316
        }
1317

1318
        // Now parse the taproot specific tweak.
1319
        if taprootTweak != nil {
6✔
1320
                if taprootTweak.KeySpendOnly {
6✔
1321
                        tweaks.TaprootBIP0086Tweak = true
3✔
1322
                } else {
6✔
1323
                        if len(taprootTweak.ScriptRoot) == 0 {
3✔
1324
                                return nil, fmt.Errorf("script root cannot " +
×
1325
                                        "be empty for non-keyspend")
×
1326
                        }
×
1327

1328
                        tweaks.TaprootTweak = taprootTweak.ScriptRoot
3✔
1329
                }
1330
        }
1331

1332
        return tweaks, nil
3✔
1333
}
1334

1335
// UnmarshalSignMethod parses the RPC sign method into the native counterpart.
1336
func UnmarshalSignMethod(rpcSignMethod SignMethod) (input.SignMethod, error) {
3✔
1337
        switch rpcSignMethod {
3✔
1338
        case SignMethod_SIGN_METHOD_WITNESS_V0:
3✔
1339
                return input.WitnessV0SignMethod, nil
3✔
1340

1341
        case SignMethod_SIGN_METHOD_TAPROOT_KEY_SPEND_BIP0086:
3✔
1342
                return input.TaprootKeySpendBIP0086SignMethod, nil
3✔
1343

1344
        case SignMethod_SIGN_METHOD_TAPROOT_KEY_SPEND:
3✔
1345
                return input.TaprootKeySpendSignMethod, nil
3✔
1346

1347
        case SignMethod_SIGN_METHOD_TAPROOT_SCRIPT_SPEND:
3✔
1348
                return input.TaprootScriptSpendSignMethod, nil
3✔
1349

1350
        default:
×
1351
                return 0, fmt.Errorf("unknown RPC sign method <%d>",
×
1352
                        rpcSignMethod)
×
1353
        }
1354
}
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