netann: update ChanAnn2 validation to work for P2WSH channels
This commit expands the ChannelAnnouncement2 validation for the case where it is announcing a P2WSH channel.
This commit is contained in:
5 files changed
+308
-58
No files matched your search
+34
-16
@@ -13,7 +13,9 @@ import (
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/lightninglabs/neutrino/cache"
|
||||
@@ -193,14 +195,9 @@ type PinnedSyncers map[route.Vertex]struct{}
|
||||
// Config defines the configuration for the service. ALL elements within the
|
||||
// configuration MUST be non-nil for the service to carry out its duties.
|
||||
type Config struct {
|
||||
// ChainHash is a hash that indicates which resident chain of the
|
||||
// AuthenticatedGossiper. Any announcements that don't match this
|
||||
// chain hash will be ignored.
|
||||
//
|
||||
// TODO(roasbeef): eventually make into map so can de-multiplex
|
||||
// incoming announcements
|
||||
// * also need to do same for Notifier
|
||||
ChainHash chainhash.Hash
|
||||
// ChainParams holds the chain parameters for the active network this
|
||||
// node is participating on.
|
||||
ChainParams *chaincfg.Params
|
||||
|
||||
// Graph is the subsystem which is responsible for managing the
|
||||
// topology of lightning network. After incoming channel, node, channel
|
||||
@@ -596,7 +593,7 @@ func New(cfg Config, selfKeyDesc *keychain.KeyDescriptor) *AuthenticatedGossiper
|
||||
gossiper.vb = NewValidationBarrier(1000, gossiper.quit)
|
||||
|
||||
gossiper.syncMgr = newSyncManager(&SyncManagerCfg{
|
||||
ChainHash: cfg.ChainHash,
|
||||
ChainHash: *cfg.ChainParams.GenesisHash,
|
||||
ChanSeries: cfg.ChanSeries,
|
||||
RotateTicker: cfg.RotateTicker,
|
||||
HistoricalSyncTicker: cfg.HistoricalSyncTicker,
|
||||
@@ -2034,9 +2031,28 @@ func (d *AuthenticatedGossiper) processRejectedEdge(_ context.Context,
|
||||
|
||||
// fetchPKScript fetches the output script for the given SCID.
|
||||
func (d *AuthenticatedGossiper) fetchPKScript(chanID lnwire.ShortChannelID) (
|
||||
[]byte, error) {
|
||||
txscript.ScriptClass, btcutil.Address, error) {
|
||||
|
||||
return lnwallet.FetchPKScriptWithQuit(d.cfg.ChainIO, chanID, d.quit)
|
||||
pkScript, err := lnwallet.FetchPKScriptWithQuit(
|
||||
d.cfg.ChainIO, chanID, d.quit,
|
||||
)
|
||||
if err != nil {
|
||||
return txscript.WitnessUnknownTy, nil, err
|
||||
}
|
||||
|
||||
scriptClass, addrs, _, err := txscript.ExtractPkScriptAddrs(
|
||||
pkScript, d.cfg.ChainParams,
|
||||
)
|
||||
if err != nil {
|
||||
return txscript.WitnessUnknownTy, nil, err
|
||||
}
|
||||
|
||||
if len(addrs) != 1 {
|
||||
return txscript.WitnessUnknownTy, nil, fmt.Errorf("expected "+
|
||||
"1 address, got: %d", len(addrs))
|
||||
}
|
||||
|
||||
return scriptClass, addrs[0], nil
|
||||
}
|
||||
|
||||
// addNode processes the given node announcement, and adds it to our channel
|
||||
@@ -2530,16 +2546,16 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(ctx context.Context,
|
||||
ops ...batch.SchedulerOption) ([]networkMsg, bool) {
|
||||
|
||||
scid := ann.ShortChannelID
|
||||
chainHash := d.cfg.ChainParams.GenesisHash
|
||||
|
||||
log.Debugf("Processing ChannelAnnouncement1: peer=%v, short_chan_id=%v",
|
||||
nMsg.peer, scid.ToUint64())
|
||||
|
||||
// We'll ignore any channel announcements that target any chain other
|
||||
// than the set of chains we know of.
|
||||
if !bytes.Equal(ann.ChainHash[:], d.cfg.ChainHash[:]) {
|
||||
if !bytes.Equal(ann.ChainHash[:], chainHash[:]) {
|
||||
err := fmt.Errorf("ignoring ChannelAnnouncement1 from chain=%v"+
|
||||
", gossiper on chain=%v", ann.ChainHash,
|
||||
d.cfg.ChainHash)
|
||||
", gossiper on chain=%v", ann.ChainHash, chainHash)
|
||||
log.Errorf(err.Error())
|
||||
|
||||
key := newRejectCacheKey(
|
||||
@@ -2960,11 +2976,13 @@ func (d *AuthenticatedGossiper) handleChanUpdate(ctx context.Context,
|
||||
log.Debugf("Processing ChannelUpdate: peer=%v, short_chan_id=%v, ",
|
||||
nMsg.peer, upd.ShortChannelID.ToUint64())
|
||||
|
||||
chainHash := d.cfg.ChainParams.GenesisHash
|
||||
|
||||
// We'll ignore any channel updates that target any chain other than
|
||||
// the set of chains we know of.
|
||||
if !bytes.Equal(upd.ChainHash[:], d.cfg.ChainHash[:]) {
|
||||
if !bytes.Equal(upd.ChainHash[:], chainHash[:]) {
|
||||
err := fmt.Errorf("ignoring ChannelUpdate from chain=%v, "+
|
||||
"gossiper on chain=%v", upd.ChainHash, d.cfg.ChainHash)
|
||||
"gossiper on chain=%v", upd.ChainHash, chainHash)
|
||||
log.Errorf(err.Error())
|
||||
|
||||
key := newRejectCacheKey(
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
@@ -620,6 +621,7 @@ func createUpdateAnnouncement(blockHeight uint32,
|
||||
|
||||
htlcMinMsat := lnwire.MilliSatoshi(100)
|
||||
a := &lnwire.ChannelUpdate1{
|
||||
ChainHash: *chaincfg.MainNetParams.GenesisHash,
|
||||
ShortChannelID: lnwire.ShortChannelID{
|
||||
BlockHeight: blockHeight,
|
||||
},
|
||||
@@ -772,6 +774,7 @@ func (ctx *testCtx) createAnnouncementWithoutProof(blockHeight uint32,
|
||||
}
|
||||
|
||||
a := &lnwire.ChannelAnnouncement1{
|
||||
ChainHash: *chaincfg.MainNetParams.GenesisHash,
|
||||
ShortChannelID: lnwire.ShortChannelID{
|
||||
BlockHeight: blockHeight,
|
||||
TxIndex: 0,
|
||||
@@ -938,8 +941,9 @@ func createTestCtx(t *testing.T, startHeight uint32, isChanPeer bool) (
|
||||
}
|
||||
|
||||
gossiper := New(Config{
|
||||
ChainIO: chain,
|
||||
Notifier: notifier,
|
||||
ChainIO: chain,
|
||||
ChainParams: &chaincfg.MainNetParams,
|
||||
Notifier: notifier,
|
||||
Broadcast: func(senders map[route.Vertex]struct{},
|
||||
msgs ...lnwire.Message) error {
|
||||
|
||||
@@ -1669,6 +1673,7 @@ func TestSignatureAnnouncementRetryAtStartup(t *testing.T) {
|
||||
|
||||
//nolint:ll
|
||||
gossiper := New(Config{
|
||||
ChainParams: &chaincfg.MainNetParams,
|
||||
Notifier: tCtx.gossiper.cfg.Notifier,
|
||||
Broadcast: tCtx.gossiper.cfg.Broadcast,
|
||||
NotifyWhenOnline: tCtx.gossiper.reliableSender.cfg.NotifyWhenOnline,
|
||||
|
||||
+115
-25
@@ -7,7 +7,9 @@ import (
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcec/v2/schnorr"
|
||||
"github.com/btcsuite/btcd/btcec/v2/schnorr/musig2"
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/tlv"
|
||||
@@ -104,7 +106,8 @@ func CreateChanAnnouncement(chanProof *models.ChannelAuthProof,
|
||||
|
||||
// FetchPkScript defines a function that can be used to fetch the output script
|
||||
// for the transaction with the given SCID.
|
||||
type FetchPkScript func(lnwire.ShortChannelID) ([]byte, error)
|
||||
type FetchPkScript func(lnwire.ShortChannelID) (txscript.ScriptClass,
|
||||
btcutil.Address, error)
|
||||
|
||||
// ValidateChannelAnn validates the channel announcement.
|
||||
func ValidateChannelAnn(a lnwire.ChannelAnnouncement,
|
||||
@@ -198,24 +201,124 @@ func validateChannelAnn1(a *lnwire.ChannelAnnouncement1) error {
|
||||
func validateChannelAnn2(a *lnwire.ChannelAnnouncement2,
|
||||
fetchPkScript FetchPkScript) error {
|
||||
|
||||
// Next, we fetch the funding transaction's PK script. We need this so
|
||||
// that we know what type of channel we will be validating: P2WSH or
|
||||
// P2TR.
|
||||
scriptClass, scriptAddr, err := fetchPkScript(a.ShortChannelID.Val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var keys []*btcec.PublicKey
|
||||
|
||||
switch scriptClass {
|
||||
case txscript.WitnessV0ScriptHashTy:
|
||||
keys, err = chanAnn2P2WSHMuSig2Keys(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case txscript.WitnessV1TaprootTy:
|
||||
keys, err = chanAnn2P2TRMuSig2Keys(a, scriptAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("invalid on-chain pk script type for "+
|
||||
"channel_announcement_2: %s", scriptClass)
|
||||
}
|
||||
|
||||
// Do a MuSig2 aggregation of the keys to obtain the aggregate key that
|
||||
// the signature will be validated against.
|
||||
aggKey, _, _, err := musig2.AggregateKeys(keys, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get the message that the signature should have signed.
|
||||
dataHash, err := ChanAnn2DigestToSign(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Obtain the signature.
|
||||
sig, err := a.Signature.Val.ToSignature()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check that the signature is valid for the aggregate key given the
|
||||
// message digest.
|
||||
if !sig.Verify(dataHash.CloneBytes(), aggKey.FinalKey) {
|
||||
return fmt.Errorf("invalid sig")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// chanAnn2P2WSHMuSig2Keys returns the set of keys that should be used to
|
||||
// construct the aggregate key that the signature in an
|
||||
// lnwire.ChannelAnnouncement2 message should be verified against in the case
|
||||
// where the channel being announced is a P2WSH channel.
|
||||
func chanAnn2P2WSHMuSig2Keys(a *lnwire.ChannelAnnouncement2) (
|
||||
[]*btcec.PublicKey, error) {
|
||||
|
||||
nodeKey1, err := btcec.ParsePubKey(a.NodeID1.Val[:])
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nodeKey2, err := btcec.ParsePubKey(a.NodeID2.Val[:])
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
btcKeyMissingErrString := "bitcoin key %d missing for announcement " +
|
||||
"of a P2WSH channel"
|
||||
|
||||
btcKey1Bytes, err := a.BitcoinKey1.UnwrapOrErr(
|
||||
fmt.Errorf(btcKeyMissingErrString, 1),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
btcKey1, err := btcec.ParsePubKey(btcKey1Bytes.Val[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
btcKey2Bytes, err := a.BitcoinKey2.UnwrapOrErr(
|
||||
fmt.Errorf(btcKeyMissingErrString, 2),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
btcKey2, err := btcec.ParsePubKey(btcKey2Bytes.Val[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return []*btcec.PublicKey{
|
||||
nodeKey1, nodeKey2, btcKey1, btcKey2,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// chanAnn2P2TRMuSig2Keys returns the set of keys that should be used to
|
||||
// construct the aggregate key that the signature in an
|
||||
// lnwire.ChannelAnnouncement2 message should be verified against in the case
|
||||
// where the channel being announced is a P2TR channel.
|
||||
func chanAnn2P2TRMuSig2Keys(a *lnwire.ChannelAnnouncement2,
|
||||
scriptAddr btcutil.Address) ([]*btcec.PublicKey, error) {
|
||||
|
||||
nodeKey1, err := btcec.ParsePubKey(a.NodeID1.Val[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nodeKey2, err := btcec.ParsePubKey(a.NodeID2.Val[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
keys := []*btcec.PublicKey{
|
||||
@@ -236,42 +339,29 @@ func validateChannelAnn2(a *lnwire.ChannelAnnouncement2,
|
||||
|
||||
bitcoinKey1, err := btcec.ParsePubKey(btcKey1.Val[:])
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bitcoinKey2, err := btcec.ParsePubKey(btcKey2.Val[:])
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
keys = append(keys, bitcoinKey1, bitcoinKey2)
|
||||
} else {
|
||||
// If bitcoin keys are not provided, then we need to get the
|
||||
// on-chain output key since this will be the 3rd key in the
|
||||
// 3-of-3 MuSig2 signature.
|
||||
pkScript, err := fetchPkScript(a.ShortChannelID.Val)
|
||||
// If bitcoin keys are not provided, then the on-chain output
|
||||
// key is considered the 3rd key in the 3-of-3 MuSig2 signature.
|
||||
outputKey, err := schnorr.ParsePubKey(
|
||||
scriptAddr.ScriptAddress(),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
outputKey, err := schnorr.ParsePubKey(pkScript[2:])
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
keys = append(keys, outputKey)
|
||||
}
|
||||
|
||||
aggKey, _, _, err := musig2.AggregateKeys(keys, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !sig.Verify(dataHash.CloneBytes(), aggKey.FinalKey) {
|
||||
return fmt.Errorf("invalid sig")
|
||||
}
|
||||
|
||||
return nil
|
||||
return keys, nil
|
||||
}
|
||||
|
||||
// ChanAnn2DigestToSign computes the digest of the message to be signed.
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/graph/db/models"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
@@ -73,20 +74,25 @@ func TestChanAnnounce2Validation(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run(
|
||||
"test 4-of-4 MuSig2 channel announcement",
|
||||
test4of4MuSig2ChanAnnouncement,
|
||||
"test 4-of-4 MuSig2 P2TR channel announcement",
|
||||
test4of4MuSig2P2TRChanAnnouncement,
|
||||
)
|
||||
|
||||
t.Run(
|
||||
"test 3-of-3 MuSig2 channel announcement",
|
||||
"test 3-of-3 MuSig2 P2TR channel announcement",
|
||||
test3of3MuSig2ChanAnnouncement,
|
||||
)
|
||||
|
||||
t.Run(
|
||||
"test 4-of-4 MuSig2 P2WSH channel announcement",
|
||||
test4of4MuSig2P2WSHChanAnnouncement,
|
||||
)
|
||||
}
|
||||
|
||||
// test4of4MuSig2ChanAnnouncement covers the case where both bitcoin keys are
|
||||
// present in the channel announcement. In this case, the signature should be
|
||||
// a 4-of-4 MuSig2.
|
||||
func test4of4MuSig2ChanAnnouncement(t *testing.T) {
|
||||
// test4of4MuSig2P2TRChanAnnouncement covers the case where the funding
|
||||
// transaction PK script is a P2WSH. In this case, the signature should be valid
|
||||
// for the MuSig2 4-of-4 aggregation of the node keys and the bitcoin keys.
|
||||
func test4of4MuSig2P2WSHChanAnnouncement(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Generate the keys for node 1 and node2.
|
||||
@@ -161,8 +167,136 @@ func test4of4MuSig2ChanAnnouncement(t *testing.T) {
|
||||
|
||||
ann.Signature.Val = sig
|
||||
|
||||
// Create an accurate representation of what the on-chain pk script will
|
||||
// look like. For this case, it is only important that we get the
|
||||
// correct script class.
|
||||
multiSigScript, err := input.GenMultiSigScript(
|
||||
node1.btcPub.SerializeCompressed(),
|
||||
node2.btcPub.SerializeCompressed(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
scriptHash, err := input.WitnessScriptHash(multiSigScript)
|
||||
require.NoError(t, err)
|
||||
pkAddr, err := btcutil.NewAddressScriptHash(
|
||||
scriptHash, &chaincfg.MainNetParams,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create a mock tx fetcher that returns the expected script class and
|
||||
// pk address.
|
||||
fetchTx := func(lnwire.ShortChannelID) (txscript.ScriptClass,
|
||||
btcutil.Address, error) {
|
||||
|
||||
return txscript.WitnessV0ScriptHashTy, pkAddr, nil
|
||||
}
|
||||
|
||||
// Validate the announcement.
|
||||
require.NoError(t, ValidateChannelAnn(ann, nil))
|
||||
require.NoError(t, ValidateChannelAnn(ann, fetchTx))
|
||||
}
|
||||
|
||||
// test4of4MuSig2P2TRChanAnnouncement covers the case where both bitcoin keys
|
||||
// are present in the channel announcement 2 and the funding transaction PK
|
||||
// script is a P2TR. In this case, the signature should be a 4-of-4 MuSig2.
|
||||
func test4of4MuSig2P2TRChanAnnouncement(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Generate the keys for node 1 and node2.
|
||||
node1, node2 := genChanAnnKeys(t)
|
||||
|
||||
// Build the unsigned channel announcement.
|
||||
ann := buildUnsignedChanAnnouncement(node1, node2, true)
|
||||
|
||||
// Serialise the bytes that need to be signed.
|
||||
msg, err := ChanAnn2DigestToSign(ann)
|
||||
require.NoError(t, err)
|
||||
|
||||
var msgBytes [32]byte
|
||||
copy(msgBytes[:], msg.CloneBytes())
|
||||
|
||||
// Generate the 4 nonces required for producing the signature.
|
||||
var (
|
||||
node1NodeNonce = genNonceForPubKey(t, node1.nodePub)
|
||||
node1BtcNonce = genNonceForPubKey(t, node1.btcPub)
|
||||
node2NodeNonce = genNonceForPubKey(t, node2.nodePub)
|
||||
node2BtcNonce = genNonceForPubKey(t, node2.btcPub)
|
||||
)
|
||||
|
||||
nonceAgg, err := musig2.AggregateNonces([][66]byte{
|
||||
node1NodeNonce.PubNonce,
|
||||
node1BtcNonce.PubNonce,
|
||||
node2NodeNonce.PubNonce,
|
||||
node2BtcNonce.PubNonce,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
pubKeys := []*btcec.PublicKey{
|
||||
node1.nodePub, node2.nodePub, node1.btcPub, node2.btcPub,
|
||||
}
|
||||
|
||||
// Let Node1 sign the announcement message with its node key.
|
||||
psA1, err := musig2.Sign(
|
||||
node1NodeNonce.SecNonce, node1.nodePriv, nonceAgg, pubKeys,
|
||||
msgBytes, musig2.WithSortedKeys(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Let Node1 sign the announcement message with its bitcoin key.
|
||||
psA2, err := musig2.Sign(
|
||||
node1BtcNonce.SecNonce, node1.btcPriv, nonceAgg, pubKeys,
|
||||
msgBytes, musig2.WithSortedKeys(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Let Node2 sign the announcement message with its node key.
|
||||
psB1, err := musig2.Sign(
|
||||
node2NodeNonce.SecNonce, node2.nodePriv, nonceAgg, pubKeys,
|
||||
msgBytes, musig2.WithSortedKeys(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Let Node2 sign the announcement message with its bitcoin key.
|
||||
psB2, err := musig2.Sign(
|
||||
node2BtcNonce.SecNonce, node2.btcPriv, nonceAgg, pubKeys,
|
||||
msgBytes, musig2.WithSortedKeys(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Finally, combine the partial signatures from Node1 and Node2 and add
|
||||
// the signature to the announcement message.
|
||||
s := musig2.CombineSigs(psA1.R, []*musig2.PartialSignature{
|
||||
psA1, psA2, psB1, psB2,
|
||||
})
|
||||
|
||||
sig, err := lnwire.NewSigFromSignature(s)
|
||||
require.NoError(t, err)
|
||||
|
||||
ann.Signature.Val = sig
|
||||
|
||||
// Create an accurate representation of what the on-chain pk script will
|
||||
// look like. For this case, it is only important that we get the
|
||||
// correct script class.
|
||||
combinedKey, _, _, err := musig2.AggregateKeys(
|
||||
[]*btcec.PublicKey{node1.btcPub, node2.btcPub}, true,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
pkAddr, err := btcutil.NewAddressTaproot(
|
||||
combinedKey.FinalKey.SerializeCompressed()[1:],
|
||||
&chaincfg.MainNetParams,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create a mock tx fetcher that returns the expected script class and
|
||||
// pk address.
|
||||
fetchTx := func(lnwire.ShortChannelID) (txscript.ScriptClass,
|
||||
btcutil.Address, error) {
|
||||
|
||||
return txscript.WitnessV1TaprootTy, pkAddr, nil
|
||||
}
|
||||
|
||||
// Validate the announcement.
|
||||
require.NoError(t, ValidateChannelAnn(ann, fetchTx))
|
||||
}
|
||||
|
||||
// test3of3MuSig2ChanAnnouncement covers the case where no bitcoin keys are
|
||||
@@ -217,14 +351,17 @@ func test3of3MuSig2ChanAnnouncement(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
pkScript, err := input.PayToTaprootScript(outputKey)
|
||||
pkAddr, err := btcutil.NewAddressTaproot(
|
||||
outputKey.SerializeCompressed()[1:], &chaincfg.MainNetParams,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// We'll pass in a mock tx fetcher that will return the funding output
|
||||
// containing this key. This is needed since the output key can not be
|
||||
// determined from the channel announcement itself.
|
||||
fetchTx := func(_ lnwire.ShortChannelID) ([]byte, error) {
|
||||
return pkScript, nil
|
||||
// Create a mock tx fetcher that returns the expected script class
|
||||
// and pk address.
|
||||
fetchTx := func(lnwire.ShortChannelID) (txscript.ScriptClass,
|
||||
btcutil.Address, error) {
|
||||
|
||||
return txscript.WitnessV1TaprootTy, pkAddr, nil
|
||||
}
|
||||
|
||||
pubKeys := []*btcec.PublicKey{node1.nodePub, node2.nodePub, outputKey}
|
||||
|
||||
@@ -1063,7 +1063,7 @@ func newServer(ctx context.Context, cfg *Config, listenAddrs []net.Addr,
|
||||
Graph: s.graphBuilder,
|
||||
ChainIO: s.cc.ChainIO,
|
||||
Notifier: s.cc.ChainNotifier,
|
||||
ChainHash: *s.cfg.ActiveNetParams.GenesisHash,
|
||||
ChainParams: s.cfg.ActiveNetParams.Params,
|
||||
Broadcast: s.BroadcastMessage,
|
||||
ChanSeries: chanSeries,
|
||||
NotifyWhenOnline: s.NotifyWhenOnline,
|
||||
|
||||
Reference in new issue
Block a user