8
8
"github.com/btcsuite/btcd/btcec/v2"
9
9
"github.com/btcsuite/btcd/btcec/v2/schnorr"
10
10
"github.com/btcsuite/btcd/btcec/v2/schnorr/musig2"
11
+ "github.com/btcsuite/btcd/btcutil"
11
12
"github.com/btcsuite/btcd/chaincfg/chainhash"
13
+ "github.com/btcsuite/btcd/txscript"
12
14
"github.com/lightningnetwork/lnd/channeldb/models"
13
15
"github.com/lightningnetwork/lnd/lnwire"
14
16
"github.com/lightningnetwork/lnd/tlv"
@@ -108,7 +110,8 @@ func CreateChanAnnouncement(chanProof *models.ChannelAuthProof,
108
110
109
111
// FetchPkScript defines a function that can be used to fetch the output script
110
112
// for the transaction with the given SCID.
111
- type FetchPkScript func (* lnwire.ShortChannelID ) ([]byte , error )
113
+ type FetchPkScript func (* lnwire.ShortChannelID ) (txscript.ScriptClass ,
114
+ btcutil.Address , error )
112
115
113
116
// ValidateChannelAnn validates the channel announcement.
114
117
func ValidateChannelAnn (a lnwire.ChannelAnnouncement ,
@@ -202,24 +205,124 @@ func validateChannelAnn1(a *lnwire.ChannelAnnouncement1) error {
202
205
func validateChannelAnn2 (a * lnwire.ChannelAnnouncement2 ,
203
206
fetchPkScript FetchPkScript ) error {
204
207
208
+ // Next, we fetch the funding transaction's PK script. We need this so
209
+ // that we know what type of channel we will be validating: P2WSH or
210
+ // P2TR.
211
+ scriptClass , scriptAddr , err := fetchPkScript (& a .ShortChannelID .Val )
212
+ if err != nil {
213
+ return err
214
+ }
215
+
216
+ var keys []* btcec.PublicKey
217
+
218
+ switch scriptClass {
219
+ case txscript .WitnessV0ScriptHashTy :
220
+ keys , err = chanAnn2P2WSHMuSig2Keys (a )
221
+ if err != nil {
222
+ return err
223
+ }
224
+ case txscript .WitnessV1TaprootTy :
225
+ keys , err = chanAnn2P2TRMuSig2Keys (a , scriptAddr )
226
+ if err != nil {
227
+ return err
228
+ }
229
+ default :
230
+ return fmt .Errorf ("invalid on-chain pk script type for " +
231
+ "channel_announcement_2: %s" , scriptClass )
232
+ }
233
+
234
+ // Do a MuSig2 aggregation of the keys to obtain the aggregate key that
235
+ // the signature will be validated against.
236
+ aggKey , _ , _ , err := musig2 .AggregateKeys (keys , true )
237
+ if err != nil {
238
+ return err
239
+ }
240
+
241
+ // Get the message that the signature should have signed.
205
242
dataHash , err := ChanAnn2DigestToSign (a )
206
243
if err != nil {
207
244
return err
208
245
}
209
246
247
+ // Obtain the signature.
210
248
sig , err := a .Signature .Val .ToSignature ()
211
249
if err != nil {
212
250
return err
213
251
}
214
252
253
+ // Check that the signature is valid for the aggregate key given the
254
+ // message digest.
255
+ if ! sig .Verify (dataHash .CloneBytes (), aggKey .FinalKey ) {
256
+ return fmt .Errorf ("invalid sig" )
257
+ }
258
+
259
+ return nil
260
+ }
261
+
262
+ // chanAnn2P2WSHMuSig2Keys returns the set of keys that should be used to
263
+ // construct the aggregate key that the signature in an
264
+ // lnwire.ChannelAnnouncement2 message should be verified against in the case
265
+ // where the channel being announced is a P2WSH channel.
266
+ func chanAnn2P2WSHMuSig2Keys (a * lnwire.ChannelAnnouncement2 ) (
267
+ []* btcec.PublicKey , error ) {
268
+
215
269
nodeKey1 , err := btcec .ParsePubKey (a .NodeID1 .Val [:])
216
270
if err != nil {
217
- return err
271
+ return nil , err
218
272
}
219
273
220
274
nodeKey2 , err := btcec .ParsePubKey (a .NodeID2 .Val [:])
221
275
if err != nil {
222
- return err
276
+ return nil , err
277
+ }
278
+
279
+ btcKeyMissingErrString := "bitcoin key %d missing for announcement " +
280
+ "of a P2WSH channel"
281
+
282
+ btcKey1Bytes , err := a .BitcoinKey1 .UnwrapOrErr (
283
+ fmt .Errorf (btcKeyMissingErrString , 1 ),
284
+ )
285
+ if err != nil {
286
+ return nil , err
287
+ }
288
+
289
+ btcKey1 , err := btcec .ParsePubKey (btcKey1Bytes .Val [:])
290
+ if err != nil {
291
+ return nil , err
292
+ }
293
+
294
+ btcKey2Bytes , err := a .BitcoinKey2 .UnwrapOrErr (
295
+ fmt .Errorf (btcKeyMissingErrString , 2 ),
296
+ )
297
+ if err != nil {
298
+ return nil , err
299
+ }
300
+
301
+ btcKey2 , err := btcec .ParsePubKey (btcKey2Bytes .Val [:])
302
+ if err != nil {
303
+ return nil , err
304
+ }
305
+
306
+ return []* btcec.PublicKey {
307
+ nodeKey1 , nodeKey2 , btcKey1 , btcKey2 ,
308
+ }, nil
309
+ }
310
+
311
+ // chanAnn2P2TRMuSig2Keys returns the set of keys that should be used to
312
+ // construct the aggregate key that the signature in an
313
+ // lnwire.ChannelAnnouncement2 message should be verified against in the case
314
+ // where the channel being announced is a P2TR channel.
315
+ func chanAnn2P2TRMuSig2Keys (a * lnwire.ChannelAnnouncement2 ,
316
+ scriptAddr btcutil.Address ) ([]* btcec.PublicKey , error ) {
317
+
318
+ nodeKey1 , err := btcec .ParsePubKey (a .NodeID1 .Val [:])
319
+ if err != nil {
320
+ return nil , err
321
+ }
322
+
323
+ nodeKey2 , err := btcec .ParsePubKey (a .NodeID2 .Val [:])
324
+ if err != nil {
325
+ return nil , err
223
326
}
224
327
225
328
keys := []* btcec.PublicKey {
@@ -240,42 +343,29 @@ func validateChannelAnn2(a *lnwire.ChannelAnnouncement2,
240
343
241
344
bitcoinKey1 , err := btcec .ParsePubKey (btcKey1 .Val [:])
242
345
if err != nil {
243
- return err
346
+ return nil , err
244
347
}
245
348
246
349
bitcoinKey2 , err := btcec .ParsePubKey (btcKey2 .Val [:])
247
350
if err != nil {
248
- return err
351
+ return nil , err
249
352
}
250
353
251
354
keys = append (keys , bitcoinKey1 , bitcoinKey2 )
252
355
} else {
253
- // If bitcoin keys are not provided, then we need to get the
254
- // on-chain output key since this will be the 3rd key in the
255
- // 3-of-3 MuSig2 signature.
256
- pkScript , err := fetchPkScript (& a .ShortChannelID .Val )
257
- if err != nil {
258
- return err
259
- }
260
-
261
- outputKey , err := schnorr .ParsePubKey (pkScript [2 :])
356
+ // If bitcoin keys are not provided, then the on-chain output
357
+ // key is considered the 3rd key in the 3-of-3 MuSig2 signature.
358
+ outputKey , err := schnorr .ParsePubKey (
359
+ scriptAddr .ScriptAddress (),
360
+ )
262
361
if err != nil {
263
- return err
362
+ return nil , err
264
363
}
265
364
266
365
keys = append (keys , outputKey )
267
366
}
268
367
269
- aggKey , _ , _ , err := musig2 .AggregateKeys (keys , true )
270
- if err != nil {
271
- return err
272
- }
273
-
274
- if ! sig .Verify (dataHash .CloneBytes (), aggKey .FinalKey ) {
275
- return fmt .Errorf ("invalid sig" )
276
- }
277
-
278
- return nil
368
+ return keys , nil
279
369
}
280
370
281
371
// ChanAnn2DigestToSign computes the digest of the message to be signed.
0 commit comments