diff --git a/fundingmanager.go b/fundingmanager.go index 43134b22..b64b8854 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -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,