funding+peer: add support for new musig2 channel funding flow

In this commit, we add support for the new musig2 channel funding flow.
This flow is identical to the existing flow, but not both sides need to
exchange local nonces up front, and then signatures sent are now partial
signatures instead of regular signatures.

The funding manager also gains some new state of the local nonces it
needs to generate in order to send the funding locked message, and also
process the funding locked message from the remote party.

In order to allow the funding manger to generate the nonces that need to
be applied to each channel, then AddNewChannel method has been modified
to accept a set of options that the peer will then use to bind the
nonces to a new channel.
This commit is contained in:
Olaoluwa Osuntokun 2023-01-19 20:26:05 -08:00
parent a8416300dd
commit 15978a8691
No known key found for this signature in database
GPG Key ID: 3BBD59E99B280306
9 changed files with 347 additions and 60 deletions

View File

@ -7,7 +7,6 @@ import (
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lnpeer"
"github.com/lightningnetwork/lnd/lnwire"
)
@ -42,7 +41,9 @@ func (p *mockPeer) SendMessageLazy(sync bool, msgs ...lnwire.Message) error {
return p.SendMessage(sync, msgs...)
}
func (p *mockPeer) AddNewChannel(_ *channeldb.OpenChannel, _ <-chan struct{}) error {
func (p *mockPeer) AddNewChannel(_ *lnpeer.NewChannel,
_ <-chan struct{}) error {
return nil
}
func (p *mockPeer) WipeChannel(_ *wire.OutPoint) {}

View File

@ -10,6 +10,7 @@ import (
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
"github.com/btcsuite/btcd/btcec/v2/schnorr/musig2"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/txscript"
@ -574,6 +575,17 @@ type Manager struct {
nonceMtx sync.RWMutex
chanIDNonce uint64
// pendingMusigNonces is used to store the musig2 nonce we generate to
// send funding locked until we receive a funding locked message from
// the remote party. We'll use this to keep track of the nonce we
// generated, so we send the local+remote nonces to the peer state
// machine.
//
// NOTE: This map is protected by the nonceMtx above.
//
// TODO(roasbeef): replace w/ generic concurrent map
pendingMusigNonces map[lnwire.ChannelID]*musig2.Nonces
// activeReservations is a map which houses the state of all pending
// funding workflows.
activeReservations map[serializedPubKey]pendingChannels
@ -674,6 +686,9 @@ func NewFundingManager(cfg Config) (*Manager, error) {
handleChannelReadyBarriers: &lnutils.SyncMap[
lnwire.ChannelID, struct{},
]{},
pendingMusigNonces: make(
map[lnwire.ChannelID]*musig2.Nonces,
),
quit: make(chan struct{}),
}, nil
}
@ -1504,15 +1519,25 @@ func (f *Manager) handleFundingOpen(peer lnpeer.Peer,
}
}
public := msg.ChannelFlags&lnwire.FFAnnounceChannel != 0
switch {
// Sending the option-scid-alias channel type for a public channel is
// disallowed.
public := msg.ChannelFlags&lnwire.FFAnnounceChannel != 0
if public && scid {
case public && scid:
err = fmt.Errorf("option-scid-alias chantype for public " +
"channel")
log.Error(err)
f.failFundingFlow(peer, cid, err)
return
// The current variant of taproot channels can only be used with
// unadvertised channels for now.
case commitType.IsTaproot() && public:
err = fmt.Errorf("taproot channel type for public channel")
log.Error(err)
f.failFundingFlow(peer, cid, err)
return
}
req := &lnwallet.InitFundingReserveMsg{
@ -1749,6 +1774,22 @@ func (f *Manager) handleFundingOpen(peer lnpeer.Peer,
},
UpfrontShutdown: msg.UpfrontShutdownScript,
}
if resCtx.reservation.IsTaproot() {
if msg.LocalNonce == nil {
err := fmt.Errorf("local nonce not set for taproot " +
"chan")
log.Error(err)
f.failFundingFlow(
resCtx.peer, cid, err,
)
}
remoteContribution.LocalNonce = &musig2.Nonces{
PubNonce: *msg.LocalNonce,
}
}
err = reservation.ProcessSingleContribution(remoteContribution)
if err != nil {
log.Errorf("unable to add contribution reservation: %v", err)
@ -1761,6 +1802,13 @@ func (f *Manager) handleFundingOpen(peer lnpeer.Peer,
log.Debugf("Remote party accepted commitment constraints: %v",
spew.Sdump(remoteContribution.ChannelConfig.ChannelConstraints))
var localNonce *lnwire.Musig2Nonce
if commitType.IsTaproot() {
localNonce = (*lnwire.Musig2Nonce)(
&ourContribution.LocalNonce.PubNonce,
)
}
// With the initiator's contribution recorded, respond with our
// contribution in the next message of the workflow.
fundingAccept := lnwire.AcceptChannel{
@ -1781,6 +1829,7 @@ func (f *Manager) handleFundingOpen(peer lnpeer.Peer,
UpfrontShutdownScript: ourContribution.UpfrontShutdown,
ChannelType: chanType,
LeaseExpiry: msg.LeaseExpiry,
LocalNonce: localNonce,
}
if err := peer.SendMessage(true, &fundingAccept); err != nil {
@ -1966,6 +2015,20 @@ func (f *Manager) handleFundingAccept(peer lnpeer.Peer,
},
UpfrontShutdown: msg.UpfrontShutdownScript,
}
if resCtx.reservation.IsTaproot() {
if msg.LocalNonce == nil {
err := fmt.Errorf("local nonce not set for taproot " +
"chan")
log.Error(err)
f.failFundingFlow(resCtx.peer, cid, err)
}
remoteContribution.LocalNonce = &musig2.Nonces{
PubNonce: *msg.LocalNonce,
}
}
err = resCtx.reservation.ProcessContribution(remoteContribution)
// The wallet has detected that a PSBT funding process was requested by
@ -2160,12 +2223,30 @@ func (f *Manager) continueFundingAccept(resCtx *reservationWithCtx,
PendingChannelID: cid.tempChanID,
FundingPoint: *outPoint,
}
fundingCreated.CommitSig, err = lnwire.NewSigFromSignature(sig)
if err != nil {
log.Errorf("Unable to parse signature: %v", err)
f.failFundingFlow(resCtx.peer, cid, err)
return
// If this is a taproot channel, then we'll need to populate the musig2
// partial sig field instead of the regular commit sig field.
if resCtx.reservation.IsTaproot() {
partialSig, ok := sig.(*lnwallet.MusigPartialSig)
if !ok {
err := fmt.Errorf("expected musig partial sig, got %T",
sig)
log.Error(err)
f.failFundingFlow(resCtx.peer, cid, err)
return
}
fundingCreated.PartialSig = partialSig.ToWireSig()
} else {
fundingCreated.CommitSig, err = lnwire.NewSigFromSignature(sig)
if err != nil {
log.Errorf("Unable to parse signature: %v", err)
f.failFundingFlow(resCtx.peer, cid, err)
return
}
}
if err := resCtx.peer.SendMessage(true, fundingCreated); err != nil {
log.Errorf("Unable to send funding complete message: %v", err)
f.failFundingFlow(resCtx.peer, cid, err)
@ -2202,11 +2283,27 @@ func (f *Manager) handleFundingCreated(peer lnpeer.Peer,
// Create the channel identifier without setting the active channel ID.
cid := newChanIdentifier(pendingChanID)
commitSig, err := msg.CommitSig.ToSignature()
if err != nil {
log.Errorf("unable to parse signature: %v", err)
f.failFundingFlow(peer, cid, err)
return
// For taproot channels, the commit signature is actually the partial
// signature. Otherwise, we can convert the ECDSA commit signature into
// our internal input.Signature type.
var commitSig input.Signature
if resCtx.reservation.IsTaproot() {
if msg.PartialSig == nil {
log.Errorf("partial sig not included: %v", err)
f.failFundingFlow(peer, cid, err)
return
}
commitSig = new(lnwallet.MusigPartialSig).FromWireSig(
msg.PartialSig,
)
} else {
commitSig, err = msg.CommitSig.ToSignature()
if err != nil {
log.Errorf("unable to parse signature: %v", err)
f.failFundingFlow(peer, cid, err)
return
}
}
// With all the necessary data available, attempt to advance the
@ -2266,18 +2363,33 @@ func (f *Manager) handleFundingCreated(peer lnpeer.Peer,
log.Debugf("Creating chan barrier for ChanID(%v)", channelID)
f.newChanBarriers.Store(channelID, make(chan struct{}))
log.Infof("sending FundingSigned for pending_id(%x) over "+
"ChannelPoint(%v)", pendingChanID[:], fundingOut)
fundingSigned := &lnwire.FundingSigned{}
// With their signature for our version of the commitment transaction
// verified, we can now send over our signature to the remote peer.
// For taproot channels, we'll need to send over a partial signature
// that includes the nonce along side the signature.
_, sig := resCtx.reservation.OurSignatures()
ourCommitSig, err := lnwire.NewSigFromSignature(sig)
if err != nil {
log.Errorf("unable to parse signature: %v", err)
f.failFundingFlow(peer, cid, err)
deleteFromDatabase()
return
if resCtx.reservation.IsTaproot() {
partialSig, ok := sig.(*lnwallet.MusigPartialSig)
if !ok {
err := fmt.Errorf("expected musig partial sig, got %T",
sig)
log.Error(err)
f.failFundingFlow(resCtx.peer, cid, err)
deleteFromDatabase()
return
}
fundingSigned.PartialSig = partialSig.ToWireSig()
} else {
fundingSigned.CommitSig, err = lnwire.NewSigFromSignature(sig)
if err != nil {
log.Errorf("unable to parse signature: %v", err)
f.failFundingFlow(peer, cid, err)
deleteFromDatabase()
return
}
}
// Before sending FundingSigned, we notify Brontide first to keep track
@ -2293,10 +2405,13 @@ func (f *Manager) handleFundingCreated(peer lnpeer.Peer,
// funding flow fails.
cid.setChanID(channelID)
fundingSigned := &lnwire.FundingSigned{
ChanID: cid.chanID,
CommitSig: ourCommitSig,
}
fundingSigned.ChanID = cid.chanID
log.Infof("sending FundingSigned for pending_id(%x) over "+
"ChannelPoint(%v)", pendingChanID[:], fundingOut)
// With their signature for our version of the commitment transaction
// verified, we can now send over our signature to the remote peer.
if err := peer.SendMessage(true, fundingSigned); err != nil {
log.Errorf("unable to send FundingSigned message: %v", err)
f.failFundingFlow(peer, cid, err)
@ -2417,14 +2532,27 @@ func (f *Manager) handleFundingSigned(peer lnpeer.Peer,
log.Errorf("Unable to store the forwarding policy: %v", err)
}
// The remote peer has responded with a signature for our commitment
// transaction. We'll verify the signature for validity, then commit
// the state to disk as we can now open the channel.
commitSig, err := msg.CommitSig.ToSignature()
if err != nil {
log.Errorf("Unable to parse signature: %v", err)
f.failFundingFlow(peer, cid, err)
return
// For taproot channels, the commit signature is actually the partial
// signature. Otherwise, we can convert the ECDSA commit signature into
// our internal input.Signature type.
var commitSig input.Signature
if resCtx.reservation.IsTaproot() {
if msg.PartialSig == nil {
log.Errorf("partial sig not included: %v", err)
f.failFundingFlow(peer, cid, err)
return
}
commitSig = new(lnwallet.MusigPartialSig).FromWireSig(
msg.PartialSig,
)
} else {
commitSig, err = msg.CommitSig.ToSignature()
if err != nil {
log.Errorf("unable to parse signature: %v", err)
f.failFundingFlow(peer, cid, err)
return
}
}
completeChan, err := resCtx.reservation.CompleteReservation(
@ -2657,10 +2785,24 @@ func (f *Manager) waitForFundingWithTimeout(
// makeFundingScript re-creates the funding script for the funding transaction
// of the target channel.
func makeFundingScript(channel *channeldb.OpenChannel) ([]byte, error) {
localKey := channel.LocalChanCfg.MultiSigKey.PubKey.SerializeCompressed()
remoteKey := channel.RemoteChanCfg.MultiSigKey.PubKey.SerializeCompressed()
localKey := channel.LocalChanCfg.MultiSigKey.PubKey
remoteKey := channel.RemoteChanCfg.MultiSigKey.PubKey
multiSigScript, err := input.GenMultiSigScript(localKey, remoteKey)
if channel.ChanType.IsTaproot() {
pkScript, _, err := input.GenTaprootFundingScript(
localKey, remoteKey, int64(channel.Capacity),
)
if err != nil {
return nil, err
}
return pkScript, nil
}
multiSigScript, err := input.GenMultiSigScript(
localKey.SerializeCompressed(),
remoteKey.SerializeCompressed(),
)
if err != nil {
return nil, err
}
@ -2956,6 +3098,38 @@ func (f *Manager) sendChannelReady(completeChan *channeldb.OpenChannel,
}
channelReadyMsg := lnwire.NewChannelReady(chanID, nextRevocation)
// If this is a taproot channel, then we also need to send along our
// set of musig2 nonces as well.
if completeChan.ChanType.IsTaproot() {
log.Infof("ChanID(%v): generating musig2 nonces...",
chanID)
f.nonceMtx.Lock()
localNonce, ok := f.pendingMusigNonces[chanID]
if !ok {
// If we don't have any nonces generated yet for this
// first state, then we'll generate them now and stow
// them away. When we receive the funding locked
// message, we'll then pass along this same set of
// nonces.
newNonce, err := channel.GenMusigNonces()
if err != nil {
f.nonceMtx.Unlock()
return err
}
// Now that we've generated the nonce for this channel,
// we'll store it in the set of pending nonces.
localNonce = newNonce
f.pendingMusigNonces[chanID] = localNonce
}
f.nonceMtx.Unlock()
channelReadyMsg.NextLocalNonce = (*lnwire.Musig2Nonce)(
&localNonce.PubNonce,
)
}
// If the channel negotiated the option-scid-alias feature bit, we'll
// send a TLV segment that includes an alias the peer can use in their
// invoice hop hints. We'll send the first alias we find for the
@ -3145,6 +3319,7 @@ func (f *Manager) addToRouterGraph(completeChan *channeldb.OpenChannel,
&completeChan.LocalChanCfg.MultiSigKey,
completeChan.RemoteChanCfg.MultiSigKey.PubKey, *shortChanID,
chanID, fwdMinHTLC, fwdMaxHTLC, ourPolicy,
completeChan.ChanType,
)
if err != nil {
return fmt.Errorf("error generating channel "+
@ -3336,7 +3511,7 @@ func (f *Manager) annAfterSixConfs(completeChan *channeldb.OpenChannel,
f.cfg.IDKey, completeChan.IdentityPub,
&completeChan.LocalChanCfg.MultiSigKey,
completeChan.RemoteChanCfg.MultiSigKey.PubKey,
*shortChanID, chanID,
*shortChanID, chanID, completeChan.ChanType,
)
if err != nil {
return fmt.Errorf("channel announcement failed: %w",
@ -3440,6 +3615,35 @@ func (f *Manager) waitForZeroConfChannel(c *channeldb.OpenChannel,
return nil
}
// genFirstStateMusigNonce generates a nonces for the "first" local state. This
// is the verification nonce for the state created for us after the initial
// commitment transaction signed as part of the funding flow.
func genFirstStateMusigNonce(channel *channeldb.OpenChannel,
) (*musig2.Nonces, error) {
musig2ShaChain, err := channeldb.DeriveMusig2Shachain(
channel.RevocationProducer,
)
if err != nil {
return nil, fmt.Errorf("unable to generate musig channel "+
"nonces: %v", err)
}
// We use the _next_ commitment height here as we need to generate the
// nonce for the next state the remote party will sign for us.
verNonce, err := channeldb.NewMusigVerificationNonce(
channel.LocalChanCfg.MultiSigKey.PubKey,
channel.LocalCommitment.CommitHeight+1,
musig2ShaChain,
)
if err != nil {
return nil, fmt.Errorf("unable to generate musig channel "+
"nonces: %v", err)
}
return verNonce, nil
}
// handleChannelReady finalizes the channel funding process and enables the
// channel to enter normal operating mode.
func (f *Manager) handleChannelReady(peer lnpeer.Peer,
@ -3517,6 +3721,17 @@ func (f *Manager) handleChannelReady(peer lnpeer.Peer,
return
}
// If this is a taproot channel, then we can generate the set of nonces
// the remote party needs to send the next remote commitment here.
var firstVerNonce *musig2.Nonces
if channel.ChanType.IsTaproot() {
firstVerNonce, err = genFirstStateMusigNonce(channel)
if err != nil {
log.Error(err)
return
}
}
// We'll need to store the received TLV alias if the option_scid_alias
// feature was negotiated. This will be used to provide route hints
// during invoice creation. In the zero-conf case, it is also used to
@ -3580,6 +3795,14 @@ func (f *Manager) handleChannelReady(peer lnpeer.Peer,
)
channelReadyMsg.AliasScid = &alias
if firstVerNonce != nil {
wireNonce := (*lnwire.Musig2Nonce)(
&firstVerNonce.PubNonce,
)
channelReadyMsg.NextLocalNonce = wireNonce
}
err = peer.SendMessage(true, channelReadyMsg)
if err != nil {
log.Errorf("unable to send channel_ready: %v",
@ -3604,6 +3827,38 @@ func (f *Manager) handleChannelReady(peer lnpeer.Peer,
return
}
// If this is a taproot channel, then we'll need to map the received
// nonces to a nonce pair, and also fetch our pending nonces, which are
// required in order to make the channel whole.
var chanOpts []lnwallet.ChannelOpt
if channel.ChanType.IsTaproot() {
f.nonceMtx.Lock()
localNonce, ok := f.pendingMusigNonces[chanID]
if !ok {
// If there's no pending nonce for this channel ID,
// we'll use the one generatd above.
localNonce = firstVerNonce
f.pendingMusigNonces[chanID] = firstVerNonce
}
f.nonceMtx.Unlock()
log.Infof("ChanID(%v): applying local+remote musig2 nonces",
chanID)
if msg.NextLocalNonce == nil {
log.Errorf("remote nonces are nil")
return
}
chanOpts = append(
chanOpts,
lnwallet.WithLocalMusigNonces(localNonce),
lnwallet.WithRemoteMusigNonces(&musig2.Nonces{
PubNonce: *msg.NextLocalNonce,
}),
)
}
// The channel_ready message contains the next commitment point we'll
// need to create the next commitment state for the remote party. So
// we'll insert that into the channel now before passing it along to
@ -3635,7 +3890,11 @@ func (f *Manager) handleChannelReady(peer lnpeer.Peer,
err)
}
if err := peer.AddNewChannel(channel, f.quit); err != nil {
err = peer.AddNewChannel(&lnpeer.NewChannel{
OpenChannel: channel,
ChanOpts: chanOpts,
}, f.quit)
if err != nil {
log.Errorf("Unable to add new channel %v with peer %x: %v",
channel.FundingOutpoint,
peer.IdentityKey().SerializeCompressed(), err,
@ -3654,6 +3913,12 @@ func (f *Manager) handleChannelReadyReceived(channel *channeldb.OpenChannel,
chanID := lnwire.NewChanIDFromOutPoint(&channel.FundingOutpoint)
// Since we've sent+received funding locked at this point, we
// can clean up the pending musig2 nonce state.
f.nonceMtx.Lock()
delete(f.pendingMusigNonces, chanID)
f.nonceMtx.Unlock()
var peerAlias *lnwire.ShortChannelID
if channel.IsZeroConf() {
// We'll need to wait until channel_ready has been received and
@ -3788,9 +4053,9 @@ type chanAnnouncement struct {
func (f *Manager) newChanAnnouncement(localPubKey,
remotePubKey *btcec.PublicKey, localFundingKey *keychain.KeyDescriptor,
remoteFundingKey *btcec.PublicKey, shortChanID lnwire.ShortChannelID,
chanID lnwire.ChannelID, fwdMinHTLC,
fwdMaxHTLC lnwire.MilliSatoshi,
ourPolicy *channeldb.ChannelEdgePolicy) (*chanAnnouncement, error) {
chanID lnwire.ChannelID, fwdMinHTLC, fwdMaxHTLC lnwire.MilliSatoshi,
ourPolicy *channeldb.ChannelEdgePolicy,
chanType channeldb.ChannelType) (*chanAnnouncement, error) {
chainHash := *f.cfg.Wallet.Cfg.NetParams.GenesisHash
@ -3982,7 +4247,7 @@ func (f *Manager) newChanAnnouncement(localPubKey,
func (f *Manager) announceChannel(localIDKey, remoteIDKey *btcec.PublicKey,
localFundingKey *keychain.KeyDescriptor,
remoteFundingKey *btcec.PublicKey, shortChanID lnwire.ShortChannelID,
chanID lnwire.ChannelID) error {
chanID lnwire.ChannelID, chanType channeldb.ChannelType) error {
// First, we'll create the batch of announcements to be sent upon
// initial channel creation. This includes the channel announcement
@ -3993,7 +4258,7 @@ func (f *Manager) announceChannel(localIDKey, remoteIDKey *btcec.PublicKey,
// only use the channel announcement message from the returned struct.
ann, err := f.newChanAnnouncement(localIDKey, remoteIDKey,
localFundingKey, remoteFundingKey, shortChanID, chanID,
0, 0, nil,
0, 0, nil, chanType,
)
if err != nil {
log.Errorf("can't generate channel announcement: %v", err)
@ -4421,6 +4686,13 @@ func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) {
log.Infof("Starting funding workflow with %v for pending_id(%x), "+
"committype=%v", msg.Peer.Address(), chanID, commitType)
var localNonce *lnwire.Musig2Nonce
if commitType.IsTaproot() {
localNonce = (*lnwire.Musig2Nonce)(
&ourContribution.LocalNonce.PubNonce,
)
}
fundingOpen := lnwire.OpenChannel{
ChainHash: *f.cfg.Wallet.Cfg.NetParams.GenesisHash,
PendingChannelID: chanID,
@ -4443,6 +4715,7 @@ func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) {
UpfrontShutdownScript: shutdown,
ChannelType: chanType,
LeaseExpiry: leaseExpiry,
LocalNonce: localNonce,
}
if err := msg.Peer.SendMessage(true, &fundingOpen); err != nil {
e := fmt.Errorf("unable to send funding request message: %v",

View File

@ -235,7 +235,7 @@ func (m *mockZeroConfAcceptor) Accept(
}
type newChannelMsg struct {
channel *channeldb.OpenChannel
channel *lnpeer.NewChannel
err chan error
}
@ -299,7 +299,7 @@ func (n *testNode) RemoteFeatures() *lnwire.FeatureVector {
)
}
func (n *testNode) AddNewChannel(channel *channeldb.OpenChannel,
func (n *testNode) AddNewChannel(channel *lnpeer.NewChannel,
quit <-chan struct{}) error {
errChan := make(chan error)

View File

@ -706,7 +706,8 @@ func (l *channelLink) syncChanStates() error {
// very same nonce that we sent above, as they should
// take the latest verification nonce we send.
if chanState.ChanType.IsTaproot() {
fundingLockedMsg.NextLocalNonce = localChanSyncMsg.LocalNonce //nolint:lll
//nolint:lll
channelReadyMsg.NextLocalNonce = localChanSyncMsg.LocalNonce
}
// For channels that negotiated the option-scid-alias

View File

@ -1868,7 +1868,7 @@ func (m *mockPeer) SendMessage(sync bool, msgs ...lnwire.Message) error {
func (m *mockPeer) SendMessageLazy(sync bool, msgs ...lnwire.Message) error {
return m.SendMessage(sync, msgs...)
}
func (m *mockPeer) AddNewChannel(_ *channeldb.OpenChannel,
func (m *mockPeer) AddNewChannel(_ *lnpeer.NewChannel,
_ <-chan struct{}) error {
return nil
}

View File

@ -666,7 +666,7 @@ func (s *mockServer) Address() net.Addr {
return nil
}
func (s *mockServer) AddNewChannel(channel *channeldb.OpenChannel,
func (s *mockServer) AddNewChannel(channel *lnpeer.NewChannel,
cancel <-chan struct{}) error {
return nil

View File

@ -5,7 +5,6 @@ import (
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/stretchr/testify/mock"
)
@ -28,7 +27,7 @@ func (m *MockPeer) SendMessageLazy(sync bool, msgs ...lnwire.Message) error {
return args.Error(0)
}
func (m *MockPeer) AddNewChannel(channel *channeldb.OpenChannel,
func (m *MockPeer) AddNewChannel(channel *NewChannel,
cancel <-chan struct{}) error {
args := m.Called(channel, cancel)

View File

@ -6,9 +6,20 @@ import (
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire"
)
// NewChannel is a newly funded channel. This struct couples a channel along
// with the set of channel options that may change how the channel is created.
// This can be used to pass along the nonce state needed for taproot channels.
type NewChannel struct {
*channeldb.OpenChannel
// ChanOpts can be used to change how the channel is created.
ChanOpts []lnwallet.ChannelOpt
}
// Peer is an interface which represents a remote lightning node.
type Peer interface {
// SendMessage sends a variadic number of high-priority message to
@ -25,7 +36,7 @@ type Peer interface {
// AddNewChannel adds a new channel to the peer. The channel should fail
// to be added if the cancel channel is closed.
AddNewChannel(channel *channeldb.OpenChannel, cancel <-chan struct{}) error
AddNewChannel(newChan *NewChannel, cancel <-chan struct{}) error
// AddPendingChannel adds a pending open channel ID to the peer. The
// channel should fail to be added if the cancel chan is closed.

View File

@ -90,7 +90,7 @@ type outgoingMsg struct {
// completed.
type newChannelMsg struct {
// channel is used when the pending channel becomes active.
channel *channeldb.OpenChannel
channel *lnpeer.NewChannel
// channelID is used when there's a new pending channel.
channelID lnwire.ChannelID
@ -3506,12 +3506,12 @@ func (p *Brontide) Address() net.Addr {
// added if the cancel channel is closed.
//
// NOTE: Part of the lnpeer.Peer interface.
func (p *Brontide) AddNewChannel(channel *channeldb.OpenChannel,
func (p *Brontide) AddNewChannel(newChan *lnpeer.NewChannel,
cancel <-chan struct{}) error {
errChan := make(chan error, 1)
newChanMsg := &newChannelMsg{
channel: channel,
channel: newChan,
err: errChan,
}
@ -3813,7 +3813,7 @@ func (p *Brontide) updateNextRevocation(c *channeldb.OpenChannel) error {
// addActiveChannel adds a new active channel to the `activeChannels` map. It
// takes a `channeldb.OpenChannel`, creates a `lnwallet.LightningChannel` from
// it and assembles it with a channel link.
func (p *Brontide) addActiveChannel(c *channeldb.OpenChannel) error {
func (p *Brontide) addActiveChannel(c *lnpeer.NewChannel) error {
chanPoint := &c.FundingOutpoint
chanID := lnwire.NewChanIDFromOutPoint(chanPoint)
@ -3821,7 +3821,8 @@ func (p *Brontide) addActiveChannel(c *channeldb.OpenChannel) error {
// channels, so we can look it up later easily according to its channel
// ID.
lnChan, err := lnwallet.NewLightningChannel(
p.cfg.Signer, c, p.cfg.SigPool,
p.cfg.Signer, c.OpenChannel,
p.cfg.SigPool, c.ChanOpts...,
)
if err != nil {
return fmt.Errorf("unable to create LightningChannel: %w", err)
@ -3887,7 +3888,8 @@ func (p *Brontide) handleNewActiveChannel(req *newChannelMsg) {
close(req.err)
// Update the next revocation point.
if err := p.updateNextRevocation(newChan); err != nil {
err := p.updateNextRevocation(newChan.OpenChannel)
if err != nil {
p.log.Errorf(err.Error())
}