funding: cleanup of 6 conf and 'private' channel logic
This commits slightly rewrites the newly introduced logic for private channels. Instead of keeping the channel announce preference in a database within fundingManager, it is stored as part of the OpenChannel struct. In addition, the ChanOpenStatus_Open update is now sent after the channel is added to the router, instead of waiting until the 6 blocks confirmation has passed.
This commit is contained in:
parent
fffe15f0fd
commit
9af7cc9b99
@ -21,6 +21,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/routing"
|
||||
"github.com/roasbeef/btcd/btcec"
|
||||
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
||||
"github.com/roasbeef/btcd/wire"
|
||||
@ -182,10 +183,10 @@ type fundingConfig struct {
|
||||
// announcement from the backing Lighting Network node.
|
||||
CurrentNodeAnnouncement func() (lnwire.NodeAnnouncement, error)
|
||||
|
||||
// SendLocalAnnouncement is used by the FundingManager to send
|
||||
// SendAnnouncement is used by the FundingManager to send
|
||||
// announcement messages to the Gossiper to possibly broadcast
|
||||
// to the greater network.
|
||||
SendLocalAnnouncement func(msg lnwire.Message) error
|
||||
SendAnnouncement func(msg lnwire.Message) error
|
||||
|
||||
// SendToPeer allows the FundingManager to send messages to the peer
|
||||
// node during the multiple steps involved in the creation of the
|
||||
@ -261,10 +262,6 @@ type fundingManager struct {
|
||||
// funding workflows.
|
||||
activeReservations map[serializedPubKey]pendingChannels
|
||||
|
||||
// pendingChanAnnPrefs is a map which stores a pending channel's id
|
||||
// along with its announcement preference.
|
||||
pendingChanAnnPrefs map[[32]byte]bool
|
||||
|
||||
// signedReservations is a utility map that maps the permanent channel
|
||||
// ID of a funding reservation to its temporary channel ID. This is
|
||||
// required as mid funding flow, we switch to referencing the channel
|
||||
@ -334,12 +331,6 @@ var (
|
||||
// of being opened.
|
||||
channelOpeningStateBucket = []byte("channelOpeningState")
|
||||
|
||||
// openChanAnnPrefBucket is the database bucket used to store each
|
||||
// channel's announcement preference signalled by the LSB of
|
||||
// channel_flags of the open_channel message in the funding workflow.
|
||||
// It only stores open channels' announcement preferences.
|
||||
openChanAnnPrefBucket = []byte("open_chan_ann")
|
||||
|
||||
// ErrChannelNotFound is returned when we are looking for a specific
|
||||
// channel opening state in the FundingManager's internal database, but
|
||||
// the channel in question is not considered being in an opening state.
|
||||
@ -359,7 +350,6 @@ func newFundingManager(cfg fundingConfig) (*fundingManager, error) {
|
||||
fundingRequests: make(chan *initFundingMsg, msgBufferSize),
|
||||
localDiscoverySignals: make(map[lnwire.ChannelID]chan struct{}),
|
||||
handleFundingLockedBarriers: make(map[lnwire.ChannelID]struct{}),
|
||||
pendingChanAnnPrefs: make(map[[32]byte]bool),
|
||||
queries: make(chan interface{}, 1),
|
||||
quit: make(chan struct{}),
|
||||
}, nil
|
||||
@ -505,40 +495,22 @@ func (f *fundingManager) Start() error {
|
||||
go func(dbChan *channeldb.OpenChannel) {
|
||||
defer f.wg.Done()
|
||||
|
||||
// Retrieve channel announcement preference
|
||||
private, err := f.getOpenChanAnnPref(
|
||||
&dbChan.FundingOutpoint)
|
||||
if err != nil {
|
||||
fndgLog.Errorf("unable to retrieve channel "+
|
||||
"announcement preference: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
lnChannel, err := lnwallet.NewLightningChannel(
|
||||
nil, nil, f.cfg.FeeEstimator, dbChan)
|
||||
if err != nil {
|
||||
fndgLog.Errorf("error creating "+
|
||||
"lightning channel: %v", err)
|
||||
return
|
||||
}
|
||||
defer lnChannel.Stop()
|
||||
|
||||
err = f.addToRouterGraph(dbChan, lnChannel,
|
||||
shortChanID, private)
|
||||
err = f.addToRouterGraph(dbChan, shortChanID)
|
||||
if err != nil {
|
||||
fndgLog.Errorf("failed adding to "+
|
||||
"router graph: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if !private {
|
||||
err = f.annAfterSixConfs(dbChan,
|
||||
lnChannel, shortChanID)
|
||||
if err != nil {
|
||||
fndgLog.Errorf("error sending channel "+
|
||||
"announcement: %v", err)
|
||||
return
|
||||
}
|
||||
// TODO(halseth): should create a state machine
|
||||
// that can more easily be resumed from
|
||||
// different states, to avoid this code
|
||||
// duplication.
|
||||
err = f.annAfterSixConfs(dbChan, shortChanID)
|
||||
if err != nil {
|
||||
fndgLog.Errorf("error sending channel "+
|
||||
"announcements: %v", err)
|
||||
return
|
||||
}
|
||||
}(channel)
|
||||
|
||||
@ -548,43 +520,13 @@ func (f *fundingManager) Start() error {
|
||||
f.wg.Add(1)
|
||||
go func(dbChan *channeldb.OpenChannel) {
|
||||
defer f.wg.Done()
|
||||
// Retrieve channel announcement preference
|
||||
private, err := f.getOpenChanAnnPref(
|
||||
&dbChan.FundingOutpoint)
|
||||
if err != nil {
|
||||
fndgLog.Errorf("unable to retrieve channel "+
|
||||
"announcement preference: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
lnChannel, err := lnwallet.NewLightningChannel(
|
||||
nil, nil, f.cfg.FeeEstimator, dbChan)
|
||||
err = f.annAfterSixConfs(channel, shortChanID)
|
||||
if err != nil {
|
||||
fndgLog.Errorf("error creating "+
|
||||
"lightning channel: %v", err)
|
||||
fndgLog.Errorf("error sending channel "+
|
||||
"announcement: %v", err)
|
||||
return
|
||||
}
|
||||
defer lnChannel.Stop()
|
||||
|
||||
if private {
|
||||
// We delete the channel from our internal
|
||||
// database.
|
||||
err := f.deleteChannelOpeningState(
|
||||
&channel.FundingOutpoint)
|
||||
if err != nil {
|
||||
fndgLog.Errorf("error deleting "+
|
||||
"channel state: %v", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
err = f.annAfterSixConfs(channel,
|
||||
lnChannel, shortChanID)
|
||||
if err != nil {
|
||||
fndgLog.Errorf("error sending channel "+
|
||||
"announcement: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}(channel)
|
||||
|
||||
default:
|
||||
@ -729,7 +671,6 @@ func (f *fundingManager) failFundingFlow(peer *btcec.PublicKey,
|
||||
return
|
||||
}
|
||||
|
||||
delete(f.pendingChanAnnPrefs, tempChanID)
|
||||
f.cancelReservationCtx(peer, tempChanID)
|
||||
return
|
||||
}
|
||||
@ -826,6 +767,7 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) {
|
||||
// number and send ErrorGeneric to remote peer if condition is
|
||||
// violated.
|
||||
peerIDKey := newSerializedKey(fmsg.peerAddress.IdentityKey)
|
||||
|
||||
msg := fmsg.msg
|
||||
amt := msg.FundingAmount
|
||||
|
||||
@ -883,7 +825,7 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) {
|
||||
reservation, err := f.cfg.Wallet.InitChannelReservation(amt, 0,
|
||||
msg.PushAmount, btcutil.Amount(msg.FeePerKiloWeight), 0,
|
||||
fmsg.peerAddress.IdentityKey, fmsg.peerAddress.Address,
|
||||
&chainHash)
|
||||
&chainHash, msg.ChannelFlags)
|
||||
if err != nil {
|
||||
fndgLog.Errorf("Unable to initialize reservation: %v", err)
|
||||
f.failFundingFlow(fmsg.peerAddress.IdentityKey,
|
||||
@ -934,16 +876,6 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) {
|
||||
}
|
||||
f.resMtx.Unlock()
|
||||
|
||||
// Save the announcement preference of this pending channel
|
||||
if msg.ChannelFlags&1 == 0 {
|
||||
// This channel WILL be announced to the greater network later.
|
||||
f.pendingChanAnnPrefs[msg.PendingChannelID] = false
|
||||
} else {
|
||||
// This channel WILL NOT be announced to the greater network
|
||||
// later.
|
||||
f.pendingChanAnnPrefs[msg.PendingChannelID] = true
|
||||
}
|
||||
|
||||
// Using the RequiredRemoteDelay closure, we'll compute the remote CSV
|
||||
// delay we require given the total amount of funds within the channel.
|
||||
remoteCsvDelay := f.cfg.RequiredRemoteDelay(amt)
|
||||
@ -1178,12 +1110,6 @@ func (f *fundingManager) handleFundingCreated(fmsg *fundingCreatedMsg) {
|
||||
peerKey, pendingChanID[:])
|
||||
return
|
||||
}
|
||||
private, ok := f.pendingChanAnnPrefs[pendingChanID]
|
||||
if !ok {
|
||||
fndgLog.Warnf("can't find channel announcement preference for"+
|
||||
"chanID:%x", pendingChanID[:])
|
||||
return
|
||||
}
|
||||
|
||||
// The channel initiator has responded with the funding outpoint of the
|
||||
// final funding transaction, as well as a signature for our version of
|
||||
@ -1210,32 +1136,10 @@ func (f *fundingManager) handleFundingCreated(fmsg *fundingCreatedMsg) {
|
||||
return
|
||||
}
|
||||
|
||||
// A new channel has almost finished the funding process. In order to
|
||||
// properly synchronize with the writeHandler goroutine, we add a new
|
||||
// channel to the barriers map which will be closed once the channel is
|
||||
// fully open.
|
||||
f.barrierMtx.Lock()
|
||||
channelID := lnwire.NewChanIDFromOutPoint(&fundingOut)
|
||||
fndgLog.Debugf("Creating chan barrier for ChanID(%v)", channelID)
|
||||
f.newChanBarriers[channelID] = make(chan struct{})
|
||||
f.barrierMtx.Unlock()
|
||||
|
||||
// Store channel announcement preference in boltdb
|
||||
if err = f.saveOpenChanAnnPref(&fundingOut, private); err != nil {
|
||||
fndgLog.Errorf("unable to save channel announcement preference "+
|
||||
"to db for chanID:%x", channelID)
|
||||
}
|
||||
|
||||
// If something goes wrong before the funding transaction is confirmed,
|
||||
// we use this convenience method to delete the pending OpenChannel
|
||||
// from the database.
|
||||
deleteFromDatabase := func() {
|
||||
err := f.deleteOpenChanAnnPref(&completeChan.FundingOutpoint)
|
||||
if err != nil {
|
||||
fndgLog.Errorf("Failed to delete channel announcement "+
|
||||
"preference: %v", err)
|
||||
}
|
||||
|
||||
closeInfo := &channeldb.ChannelCloseSummary{
|
||||
ChanPoint: completeChan.FundingOutpoint,
|
||||
ChainHash: completeChan.ChainHash,
|
||||
@ -1318,31 +1222,36 @@ func (f *fundingManager) handleFundingCreated(fmsg *fundingCreatedMsg) {
|
||||
go f.waitForFundingWithTimeout(completeChan, confChan,
|
||||
timeoutChan)
|
||||
|
||||
var shortChanID *lnwire.ShortChannelID
|
||||
var ok bool
|
||||
select {
|
||||
case <-timeoutChan:
|
||||
// We did not see the funding confirmation before
|
||||
// timeout, so we forget the channel.
|
||||
deleteFromDatabase()
|
||||
return
|
||||
case <-f.quit:
|
||||
// The fundingManager is shutting down, will resume
|
||||
// wait for funding transaction on startup.
|
||||
case shortChanID, ok := <-confChan:
|
||||
return
|
||||
case shortChanID, ok = <-confChan:
|
||||
if !ok {
|
||||
fndgLog.Errorf("waiting for funding confirmation" +
|
||||
" failed")
|
||||
return
|
||||
}
|
||||
// Fallthrough.
|
||||
}
|
||||
|
||||
f.deleteReservationCtx(peerKey, fmsg.msg.PendingChannelID)
|
||||
// Success, funding transaction was confirmed.
|
||||
f.deleteReservationCtx(peerKey, fmsg.msg.PendingChannelID)
|
||||
|
||||
// Success, funding transaction was confirmed.
|
||||
err := f.handleFundingConfirmation(completeChan,
|
||||
shortChanID)
|
||||
if err != nil {
|
||||
fndgLog.Errorf("failed to handle funding"+
|
||||
"confirmation: %v", err)
|
||||
return
|
||||
}
|
||||
err := f.handleFundingConfirmation(completeChan,
|
||||
shortChanID)
|
||||
if err != nil {
|
||||
fndgLog.Errorf("failed to handle funding"+
|
||||
"confirmation: %v", err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
}
|
||||
@ -1391,12 +1300,6 @@ func (f *fundingManager) handleFundingSigned(fmsg *fundingSignedMsg) {
|
||||
pendingChanID, []byte(err.Error()))
|
||||
return
|
||||
}
|
||||
private, ok := f.pendingChanAnnPrefs[pendingChanID]
|
||||
if !ok {
|
||||
fndgLog.Warnf("can't find channel announcement preference for"+
|
||||
"chanID:%x", pendingChanID[:])
|
||||
return
|
||||
}
|
||||
|
||||
// Create an entry in the local discovery map so we can ensure that we
|
||||
// process the channel confirmation fully before we receive a funding
|
||||
@ -1407,12 +1310,6 @@ func (f *fundingManager) handleFundingSigned(fmsg *fundingSignedMsg) {
|
||||
f.localDiscoverySignals[permChanID] = make(chan struct{})
|
||||
f.localDiscoveryMtx.Unlock()
|
||||
|
||||
// Store channel announcement preference in boltdb
|
||||
if err = f.saveOpenChanAnnPref(fundingPoint, private); err != nil {
|
||||
fndgLog.Errorf("unable to save channel announcement preference "+
|
||||
"to db for chanID:%x", permChanID)
|
||||
}
|
||||
|
||||
// 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.
|
||||
@ -1459,29 +1356,55 @@ func (f *fundingManager) handleFundingSigned(fmsg *fundingSignedMsg) {
|
||||
confChan)
|
||||
}()
|
||||
|
||||
var shortChanID *lnwire.ShortChannelID
|
||||
var ok bool
|
||||
select {
|
||||
case <-f.quit:
|
||||
return
|
||||
case shortChanID, ok := <-confChan:
|
||||
case shortChanID, ok = <-confChan:
|
||||
if !ok {
|
||||
fndgLog.Errorf("waiting for funding confirmation" +
|
||||
" failed")
|
||||
return
|
||||
}
|
||||
|
||||
f.deleteReservationCtx(peerKey, pendingChanID)
|
||||
|
||||
// Success, funding transaction was confirmed
|
||||
err := f.handleFundingConfirmation(completeChan,
|
||||
shortChanID)
|
||||
if err != nil {
|
||||
fndgLog.Errorf("failed to handle funding"+
|
||||
"confirmation: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Finally give the caller a final update notifying them that
|
||||
// Success, funding transaction was confirmed.
|
||||
fndgLog.Debugf("Channel with ShortChanID %v now confirmed",
|
||||
shortChanID.ToUint64())
|
||||
|
||||
// Go on adding the channel to the channel graph, and crafting
|
||||
// channel announcements.
|
||||
|
||||
// We create the state-machine object which wraps the database state.
|
||||
lnChannel, err := lnwallet.NewLightningChannel(nil, nil, f.cfg.FeeEstimator,
|
||||
completeChan)
|
||||
if err != nil {
|
||||
fndgLog.Errorf("failed creating lnChannel: %v", err)
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
lnChannel.Stop()
|
||||
lnChannel.CancelObserver()
|
||||
}()
|
||||
|
||||
err = f.sendFundingLocked(completeChan, lnChannel, shortChanID)
|
||||
if err != nil {
|
||||
fndgLog.Errorf("failed sending fundingLocked: %v", err)
|
||||
return
|
||||
}
|
||||
fndgLog.Debugf("FundingLocked for channel with ShortChanID "+
|
||||
"%v sent", shortChanID.ToUint64())
|
||||
|
||||
err = f.addToRouterGraph(completeChan, shortChanID)
|
||||
if err != nil {
|
||||
fndgLog.Errorf("failed adding to router graph: %v", err)
|
||||
return
|
||||
}
|
||||
fndgLog.Debugf("Channel with ShortChanID %v added to "+
|
||||
"router graph", shortChanID.ToUint64())
|
||||
|
||||
// Give the caller a final update notifying them that
|
||||
// the channel is now open.
|
||||
// TODO(roasbeef): only notify after recv of funding locked?
|
||||
resCtx.updates <- &lnrpc.OpenStatusUpdate{
|
||||
@ -1494,6 +1417,15 @@ func (f *fundingManager) handleFundingSigned(fmsg *fundingSignedMsg) {
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
f.deleteReservationCtx(peerKey, pendingChanID)
|
||||
|
||||
err = f.annAfterSixConfs(completeChan, shortChanID)
|
||||
if err != nil {
|
||||
fndgLog.Errorf("failed sending channel announcement: %v",
|
||||
err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
@ -1672,8 +1604,9 @@ func (f *fundingManager) waitForFundingConfirmation(completeChan *channeldb.Open
|
||||
return
|
||||
}
|
||||
|
||||
// This closes the discoverySignal channel, indicating to a separate
|
||||
// goroutine that it is acceptable to process funding locked messages
|
||||
// Close the discoverySignal channel, indicating to a separate
|
||||
// goroutine that the channel now is marked as open in the database
|
||||
// and that it is acceptable to process funding locked messages
|
||||
// from the peer.
|
||||
f.localDiscoveryMtx.Lock()
|
||||
if discoverySignal, ok := f.localDiscoverySignals[chanID]; ok {
|
||||
@ -1689,13 +1622,6 @@ func (f *fundingManager) waitForFundingConfirmation(completeChan *channeldb.Open
|
||||
func (f *fundingManager) handleFundingConfirmation(completeChan *channeldb.OpenChannel,
|
||||
shortChanID *lnwire.ShortChannelID) error {
|
||||
|
||||
// Retrieve channel announcement preference
|
||||
private, err := f.getOpenChanAnnPref(&completeChan.FundingOutpoint)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to retrieve channel announcement "+
|
||||
"preference: %v", err)
|
||||
}
|
||||
|
||||
// We create the state-machine object which wraps the database state.
|
||||
lnChannel, err := lnwallet.NewLightningChannel(nil, nil, f.cfg.FeeEstimator,
|
||||
completeChan)
|
||||
@ -1715,23 +1641,14 @@ func (f *fundingManager) handleFundingConfirmation(completeChan *channeldb.OpenC
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed sending fundingLocked: %v", err)
|
||||
}
|
||||
err = f.addToRouterGraph(completeChan, lnChannel, shortChanID, private)
|
||||
err = f.addToRouterGraph(completeChan, shortChanID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed adding to router graph: %v", err)
|
||||
}
|
||||
|
||||
if private {
|
||||
// We delete the channel from our internal database.
|
||||
err := f.deleteChannelOpeningState(&completeChan.FundingOutpoint)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error deleting channel state: %v", err)
|
||||
}
|
||||
} else {
|
||||
err = f.annAfterSixConfs(completeChan, lnChannel, shortChanID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed sending channel announcement: %v",
|
||||
err)
|
||||
}
|
||||
err = f.annAfterSixConfs(completeChan, shortChanID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed sending channel announcement: %v",
|
||||
err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -1813,19 +1730,26 @@ func (f *fundingManager) sendFundingLocked(completeChan *channeldb.OpenChannel,
|
||||
return nil
|
||||
}
|
||||
|
||||
// addToRouterGraph sends a private ChannelAnnouncement and a private
|
||||
// ChannelUpdate to the gossiper so that it is added to the Router's internal
|
||||
// graph before the announcement_signatures is sent in
|
||||
// annAfterSixConfs. These private announcement messages are NOT
|
||||
// broadcasted to the greater network.
|
||||
// addToRouterGraph sends a ChannelAnnouncement and a ChannelUpdate to the
|
||||
// gossiper so that the channel is added to the Router's internal graph.
|
||||
// These announcement messages are NOT broadcasted to the greater network,
|
||||
// only to the channel counter party. The proofs required to announce the
|
||||
// channel to the greater network will be created and sent in annAfterSixConfs.
|
||||
func (f *fundingManager) addToRouterGraph(completeChan *channeldb.OpenChannel,
|
||||
shortChanID *lnwire.ShortChannelID, private bool) error {
|
||||
shortChanID *lnwire.ShortChannelID) error {
|
||||
|
||||
chanID := lnwire.NewChanIDFromOutPoint(&completeChan.FundingOutpoint)
|
||||
|
||||
// We'll obtain their min HTLC as we'll use this value within our
|
||||
// ChannelUpdate. We use this value isn't of ours, as the remote party
|
||||
// will be the one that's carrying the HTLC towards us.
|
||||
remoteMinHTLC := completeChan.RemoteChanCfg.MinHTLC
|
||||
|
||||
ann, err := f.newChanAnnouncement(f.cfg.IDKey, completeChan.IdentityPub,
|
||||
completeChan.LocalChanCfg.MultiSigKey,
|
||||
completeChan.RemoteChanCfg.MultiSigKey, *shortChanID, chanID)
|
||||
completeChan.RemoteChanCfg.MultiSigKey, *shortChanID, chanID,
|
||||
remoteMinHTLC,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error generating channel "+
|
||||
"announcement: %v", err)
|
||||
@ -1833,21 +1757,30 @@ func (f *fundingManager) addToRouterGraph(completeChan *channeldb.OpenChannel,
|
||||
|
||||
// Send ChannelAnnouncement and ChannelUpdate to the gossiper to add
|
||||
// to the Router's topology.
|
||||
if err = f.cfg.SendLocalAnnouncement(ann.chanAnn); err != nil {
|
||||
return fmt.Errorf("error sending private channel "+
|
||||
"announcement: %v", err)
|
||||
if err = f.cfg.SendAnnouncement(ann.chanAnn); err != nil {
|
||||
if routing.IsError(err, routing.ErrOutdated, routing.ErrIgnored) {
|
||||
fndgLog.Debugf("Router rejected ChannelAnnouncement: %v",
|
||||
err)
|
||||
} else {
|
||||
return fmt.Errorf("error sending channel "+
|
||||
"announcement: %v", err)
|
||||
}
|
||||
}
|
||||
if err = f.cfg.SendLocalAnnouncement(ann.chanUpdateAnn); err != nil {
|
||||
return fmt.Errorf("error sending private channel "+
|
||||
"update: %v", err)
|
||||
if err = f.cfg.SendAnnouncement(ann.chanUpdateAnn); err != nil {
|
||||
if routing.IsError(err, routing.ErrOutdated, routing.ErrIgnored) {
|
||||
fndgLog.Debugf("Router rejected ChannelUpdate: %v", err)
|
||||
} else {
|
||||
return fmt.Errorf("error sending channel "+
|
||||
"update: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// As the channel is now added to the ChannelRouter's topology, the
|
||||
// channel is moved to the next state of the state machine. It will be
|
||||
// moved to the last state (actually deleted from the database) after
|
||||
// the channel is finally announced.
|
||||
err = f.saveChannelOpeningState(&completeChan.FundingOutpoint, addedToRouterGraph,
|
||||
shortChanID)
|
||||
err = f.saveChannelOpeningState(&completeChan.FundingOutpoint,
|
||||
addedToRouterGraph, shortChanID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error setting channel state to"+
|
||||
" addedToRouterGraph: %v", err)
|
||||
@ -1859,61 +1792,86 @@ func (f *fundingManager) addToRouterGraph(completeChan *channeldb.OpenChannel,
|
||||
// annAfterSixConfs broadcasts the necessary channel announcement messages to
|
||||
// the network after 6 confs. Should be called after the fundingLocked message
|
||||
// is sent and the channel is added to the router graph (channelState is
|
||||
// 'addedToRouterGraph') and the channel is ready to be used.
|
||||
// 'addedToRouterGraph') and the channel is ready to be used. This is the last
|
||||
// step in the channel opening process, and the opening state will be deleted
|
||||
// from the database if successful.
|
||||
func (f *fundingManager) annAfterSixConfs(completeChan *channeldb.OpenChannel,
|
||||
shortChanID *lnwire.ShortChannelID) error {
|
||||
|
||||
// Register with the ChainNotifier for a notification once the
|
||||
// funding transaction reaches 6 confirmations.
|
||||
txid := completeChan.FundingOutpoint.Hash
|
||||
confNtfn, err := f.cfg.Notifier.RegisterConfirmationsNtfn(&txid, 6,
|
||||
completeChan.FundingBroadcastHeight)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to register for confirmation of "+
|
||||
"ChannelPoint(%v): %v", completeChan.FundingOutpoint, err)
|
||||
}
|
||||
|
||||
// Wait until 6 confirmations has been reached or the wallet signals
|
||||
// a shutdown.
|
||||
select {
|
||||
case _, ok := <-confNtfn.Confirmed:
|
||||
if !ok {
|
||||
return fmt.Errorf("ChainNotifier shutting down, cannot "+
|
||||
"complete funding flow for ChannelPoint(%v)",
|
||||
completeChan.FundingOutpoint)
|
||||
// If this channel is meant to be announced to the greater network,
|
||||
// wait until the funding tx has reached 6 confirmations before
|
||||
// announcing it.
|
||||
announceChan := completeChan.ChannelFlags&lnwire.FFAnnounceChannel != 0
|
||||
if !announceChan {
|
||||
fndgLog.Debugf("Will not announce private channel %v.",
|
||||
shortChanID.ToUint64())
|
||||
} else {
|
||||
// Register with the ChainNotifier for a notification once the
|
||||
// funding transaction reaches at least 6 confirmations.
|
||||
numConfs := uint32(completeChan.NumConfsRequired)
|
||||
if numConfs < 6 {
|
||||
numConfs = 6
|
||||
}
|
||||
case <-f.quit:
|
||||
return fmt.Errorf("fundingManager shutting down, stopping funding "+
|
||||
"flow for ChannelPoint(%v)", completeChan.FundingOutpoint)
|
||||
txid := completeChan.FundingOutpoint.Hash
|
||||
fndgLog.Debugf("Will announce channel %v after ChannelPoint"+
|
||||
"(%v) has gotten %d confirmations",
|
||||
shortChanID.ToUint64(), completeChan.FundingOutpoint,
|
||||
numConfs)
|
||||
|
||||
confNtfn, err := f.cfg.Notifier.RegisterConfirmationsNtfn(&txid,
|
||||
numConfs, completeChan.FundingBroadcastHeight)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to register for confirmation of "+
|
||||
"ChannelPoint(%v): %v", completeChan.FundingOutpoint, err)
|
||||
}
|
||||
|
||||
// Wait until 6 confirmations has been reached or the wallet signals
|
||||
// a shutdown.
|
||||
select {
|
||||
case _, ok := <-confNtfn.Confirmed:
|
||||
if !ok {
|
||||
return fmt.Errorf("ChainNotifier shutting down, cannot "+
|
||||
"complete funding flow for ChannelPoint(%v)",
|
||||
completeChan.FundingOutpoint)
|
||||
}
|
||||
// Fallthrough.
|
||||
|
||||
case <-f.quit:
|
||||
return fmt.Errorf("fundingManager shutting down, stopping funding "+
|
||||
"flow for ChannelPoint(%v)", completeChan.FundingOutpoint)
|
||||
}
|
||||
|
||||
fundingPoint := completeChan.FundingOutpoint
|
||||
chanID := lnwire.NewChanIDFromOutPoint(&fundingPoint)
|
||||
|
||||
fndgLog.Infof("Announcing ChannelPoint(%v), short_chan_id=%v",
|
||||
&fundingPoint, spew.Sdump(shortChanID))
|
||||
|
||||
// We'll obtain their min HTLC as we'll use this value within our
|
||||
// ChannelUpdate. We use this value isn't of ours, as the remote party
|
||||
// will be the one that's carrying the HTLC towards us.
|
||||
remoteMinHTLC := completeChan.RemoteChanCfg.MinHTLC
|
||||
|
||||
// Create and broadcast the proofs required to make this channel
|
||||
// public and usable for other nodes for routing.
|
||||
err = f.announceChannel(f.cfg.IDKey, completeChan.IdentityPub,
|
||||
completeChan.LocalChanCfg.MultiSigKey,
|
||||
completeChan.RemoteChanCfg.MultiSigKey, *shortChanID, chanID,
|
||||
remoteMinHTLC,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("channel announcement failed: %v", err)
|
||||
}
|
||||
|
||||
fndgLog.Debugf("Channel with ChannelPoint(%v), short_chan_id=%v "+
|
||||
"announced", &fundingPoint, spew.Sdump(shortChanID))
|
||||
}
|
||||
|
||||
fundingPoint := completeChan.FundingOutpoint
|
||||
chanID := lnwire.NewChanIDFromOutPoint(&fundingPoint)
|
||||
|
||||
fndgLog.Infof("Announcing ChannelPoint(%v), short_chan_id=%v",
|
||||
&fundingPoint, spew.Sdump(shortChanID))
|
||||
|
||||
// We'll obtain their min HTLC as we'll use this value within our
|
||||
// ChannelUpdate. We use this value isn't of ours, as the remote party
|
||||
// will be the one that's carrying the HTLC towards us.
|
||||
remoteMinHTLC := completeChan.RemoteChanCfg.MinHTLC
|
||||
|
||||
// Register the new link with the L3 routing manager so this new
|
||||
// channel can be utilized during path finding.
|
||||
err := f.announceChannel(f.cfg.IDKey, completeChan.IdentityPub,
|
||||
completeChan.LocalChanCfg.MultiSigKey,
|
||||
completeChan.RemoteChanCfg.MultiSigKey, *shortChanID, chanID,
|
||||
remoteMinHTLC,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("channel announcement failed: %v", err)
|
||||
}
|
||||
|
||||
// After the channel is successfully announced from the fundingManager,
|
||||
// we delete the channel from our internal database. We can do this
|
||||
// because we assume the AuthenticatedGossiper queues the announcement
|
||||
// messages, and persists them in case of a daemon shutdown.
|
||||
err = f.deleteChannelOpeningState(&fundingPoint)
|
||||
// We delete the channel opening state from our internal database
|
||||
// as the opening process has succeeded. We can do this because we
|
||||
// assume the AuthenticatedGossiper queues the announcement messages,
|
||||
// and persists them in case of a daemon shutdown.
|
||||
err := f.deleteChannelOpeningState(&completeChan.FundingOutpoint)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error deleting channel state: %v", err)
|
||||
}
|
||||
@ -2240,8 +2198,13 @@ func (f *fundingManager) announceChannel(localIDKey, remoteIDKey, localFundingKe
|
||||
// the ChannelUpdate announcement messages. The channel proof and node
|
||||
// announcements are broadcast to the greater network.
|
||||
if err = f.cfg.SendAnnouncement(ann.chanProof); err != nil {
|
||||
fndgLog.Errorf("Unable to send channel proof: %v", err)
|
||||
return err
|
||||
if routing.IsError(err, routing.ErrOutdated, routing.ErrIgnored) {
|
||||
fndgLog.Debugf("Router rejected AnnounceSignatures: %v",
|
||||
err)
|
||||
} else {
|
||||
fndgLog.Errorf("Unable to send channel proof: %v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Now that the channel is announced to the network, we will also
|
||||
@ -2254,9 +2217,14 @@ func (f *fundingManager) announceChannel(localIDKey, remoteIDKey, localFundingKe
|
||||
return err
|
||||
}
|
||||
|
||||
if err = f.cfg.SendAnnouncement(&nodeAnn); err != nil {
|
||||
fndgLog.Errorf("Unable to send node announcement: %v", err)
|
||||
return err
|
||||
if err := f.cfg.SendAnnouncement(&nodeAnn); err != nil {
|
||||
if routing.IsError(err, routing.ErrOutdated, routing.ErrIgnored) {
|
||||
fndgLog.Debugf("Router rejected NodeAnnouncement: %v",
|
||||
err)
|
||||
} else {
|
||||
fndgLog.Errorf("Unable to send node announcement: %v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -2305,12 +2273,20 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
|
||||
// multiply the computed sat/weight by 1000 to arrive at fee-per-kw.
|
||||
commitFeePerKw := feePerWeight * 1000
|
||||
|
||||
// We set the channel flags to indicate whether we want this channel
|
||||
// to be announced to the network.
|
||||
var channelFlags lnwire.FundingFlag
|
||||
if !msg.openChanReq.private {
|
||||
// This channel will be announced.
|
||||
channelFlags = lnwire.FFAnnounceChannel
|
||||
}
|
||||
|
||||
// Initialize a funding reservation with the local wallet. If the
|
||||
// wallet doesn't have enough funds to commit to this channel, then the
|
||||
// request will fail, and be aborted.
|
||||
reservation, err := f.cfg.Wallet.InitChannelReservation(capacity,
|
||||
localAmt, msg.pushAmt, commitFeePerKw, msg.fundingFeePerWeight,
|
||||
peerKey, msg.peerAddress.Address, &msg.chainHash)
|
||||
peerKey, msg.peerAddress.Address, &msg.chainHash, channelFlags)
|
||||
if err != nil {
|
||||
msg.err <- err
|
||||
return
|
||||
@ -2358,18 +2334,6 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
|
||||
fndgLog.Infof("Starting funding workflow with %v for pendingID(%x)",
|
||||
msg.peerAddress.Address, chanID)
|
||||
|
||||
// Save the announcement preference of this pending channel
|
||||
var channelFlags byte
|
||||
if msg.openChanReq.private {
|
||||
// This channel will be private
|
||||
channelFlags = 1
|
||||
f.pendingChanAnnPrefs[chanID] = true
|
||||
} else {
|
||||
// This channel will be publicly announced to the greater network.
|
||||
channelFlags = 0
|
||||
f.pendingChanAnnPrefs[chanID] = false
|
||||
}
|
||||
|
||||
fundingOpen := lnwire.OpenChannel{
|
||||
ChainHash: *f.cfg.Wallet.Cfg.NetParams.GenesisHash,
|
||||
PendingChannelID: chanID,
|
||||
@ -2388,7 +2352,7 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
|
||||
HtlcPoint: ourContribution.HtlcBasePoint,
|
||||
DelayedPaymentPoint: ourContribution.DelayBasePoint,
|
||||
FirstCommitmentPoint: ourContribution.FirstCommitmentPoint,
|
||||
ChannelFlags: lnwire.FFAnnounceChannel,
|
||||
ChannelFlags: channelFlags,
|
||||
}
|
||||
if err := f.cfg.SendToPeer(peerKey, &fundingOpen); err != nil {
|
||||
fndgLog.Errorf("Unable to send funding request message: %v", err)
|
||||
@ -2470,7 +2434,6 @@ func (f *fundingManager) handleErrorMsg(fmsg *fundingErrorMsg) {
|
||||
)
|
||||
}
|
||||
|
||||
delete(f.pendingChanAnnPrefs, chanID)
|
||||
if _, err := f.cancelReservationCtx(peerKey, chanID); err != nil {
|
||||
fndgLog.Warnf("unable to delete reservation: %v", err)
|
||||
return
|
||||
@ -2539,86 +2502,6 @@ func copyPubKey(pub *btcec.PublicKey) *btcec.PublicKey {
|
||||
}
|
||||
}
|
||||
|
||||
// saveOpenChanAnnPref saves an open channel's announcement preference.
|
||||
func (f *fundingManager) saveOpenChanAnnPref(chanPoint *wire.OutPoint,
|
||||
pref bool) error {
|
||||
return f.cfg.Wallet.Cfg.Database.Update(func(tx *bolt.Tx) error {
|
||||
|
||||
bucket, err := tx.CreateBucketIfNotExists(openChanAnnPrefBucket)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var outpointBytes bytes.Buffer
|
||||
if err = writeOutpoint(&outpointBytes, chanPoint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
scratch := make([]byte, 0)
|
||||
var b byte
|
||||
if pref {
|
||||
b = 1
|
||||
} else {
|
||||
b = 0
|
||||
}
|
||||
scratch = append(scratch[:], b)
|
||||
|
||||
return bucket.Put(outpointBytes.Bytes(), scratch[:])
|
||||
})
|
||||
}
|
||||
|
||||
// getOpenChanAnnPref retrives an open channel's announcement preference.
|
||||
func (f *fundingManager) getOpenChanAnnPref(chanPoint *wire.OutPoint) (bool, error) {
|
||||
|
||||
var pref bool
|
||||
err := f.cfg.Wallet.Cfg.Database.View(func(tx *bolt.Tx) error {
|
||||
|
||||
bucket := tx.Bucket(openChanAnnPrefBucket)
|
||||
if bucket == nil {
|
||||
return fmt.Errorf("Channel announcement preference " +
|
||||
"not found")
|
||||
}
|
||||
|
||||
var outpointBytes bytes.Buffer
|
||||
if err := writeOutpoint(&outpointBytes, chanPoint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
value := bucket.Get(outpointBytes.Bytes())
|
||||
if value == nil {
|
||||
return fmt.Errorf("Channel announcement preference " +
|
||||
"not found")
|
||||
}
|
||||
|
||||
if value[0] == 1 {
|
||||
pref = true
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return pref, nil
|
||||
}
|
||||
|
||||
// deleteOpenChanAnnPref deletes an open channel's announcement preference.
|
||||
func (f *fundingManager) deleteOpenChanAnnPref(chanPoint *wire.OutPoint) error {
|
||||
return f.cfg.Wallet.Cfg.Database.Update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(openChanAnnPrefBucket)
|
||||
if bucket == nil {
|
||||
return fmt.Errorf("Bucket not found")
|
||||
}
|
||||
|
||||
var outpointBytes bytes.Buffer
|
||||
if err := writeOutpoint(&outpointBytes, chanPoint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return bucket.Delete(outpointBytes.Bytes())
|
||||
})
|
||||
}
|
||||
|
||||
// saveChannelOpeningState saves the channelOpeningState for the provided
|
||||
// chanPoint to the channelOpeningStateBucket.
|
||||
func (f *fundingManager) saveChannelOpeningState(chanPoint *wire.OutPoint,
|
||||
|
Loading…
Reference in New Issue
Block a user