server+netann+peer: put peer's alias in Update, proper config for link

This commit modifies the netann subsystem to use the peer's alias
for ChannelUpdates where appropriate (i.e. in case we are sending
the alias to the peer). It also modifies the loadActiveChannels
function in the peer package to handle upgrading a channel when the
scid-alias feature bit is turned on.
This commit is contained in:
eugene 2022-04-04 16:56:29 -04:00
parent 778be5be58
commit b9ef26061a
No known key found for this signature in database
GPG key ID: 118759E83439A9B1
5 changed files with 144 additions and 15 deletions

View file

@ -60,7 +60,8 @@ type ChanStatusConfig struct {
// ApplyChannelUpdate processes new ChannelUpdates signed by our node by
// updating our local routing table and broadcasting the update to our
// peers.
ApplyChannelUpdate func(*lnwire.ChannelUpdate) error
ApplyChannelUpdate func(*lnwire.ChannelUpdate, *wire.OutPoint,
bool) error
// DB stores the set of channels that are to be monitored.
DB DB
@ -621,7 +622,7 @@ func (m *ChanStatusManager) signAndSendNextUpdate(outpoint wire.OutPoint,
// Retrieve the latest update for this channel. We'll use this
// as our starting point to send the new update.
chanUpdate, err := m.fetchLastChanUpdateByOutPoint(outpoint)
chanUpdate, private, err := m.fetchLastChanUpdateByOutPoint(outpoint)
if err != nil {
return err
}
@ -634,22 +635,26 @@ func (m *ChanStatusManager) signAndSendNextUpdate(outpoint wire.OutPoint,
return err
}
return m.cfg.ApplyChannelUpdate(chanUpdate)
return m.cfg.ApplyChannelUpdate(chanUpdate, &outpoint, private)
}
// fetchLastChanUpdateByOutPoint fetches the latest policy for our direction of
// a channel, and crafts a new ChannelUpdate with this policy. Returns an error
// in case our ChannelEdgePolicy is not found in the database.
// in case our ChannelEdgePolicy is not found in the database. Also returns if
// the channel is private by checking AuthProof for nil.
func (m *ChanStatusManager) fetchLastChanUpdateByOutPoint(op wire.OutPoint) (
*lnwire.ChannelUpdate, error) {
*lnwire.ChannelUpdate, bool, error) {
// Get the edge info and policies for this channel from the graph.
info, edge1, edge2, err := m.cfg.Graph.FetchChannelEdgesByOutpoint(&op)
if err != nil {
return nil, err
return nil, false, err
}
return ExtractChannelUpdate(m.ourPubKeyBytes, info, edge1, edge2)
update, err := ExtractChannelUpdate(
m.ourPubKeyBytes, info, edge1, edge2,
)
return update, info.AuthProof == nil, err
}
// loadInitialChanState determines the initial ChannelState for a particular
@ -660,7 +665,7 @@ func (m *ChanStatusManager) fetchLastChanUpdateByOutPoint(op wire.OutPoint) (
func (m *ChanStatusManager) loadInitialChanState(
outpoint *wire.OutPoint) (ChannelState, error) {
lastUpdate, err := m.fetchLastChanUpdateByOutPoint(*outpoint)
lastUpdate, _, err := m.fetchLastChanUpdateByOutPoint(*outpoint)
if err != nil {
return ChannelState{}, err
}

View file

@ -176,7 +176,9 @@ func (g *mockGraph) FetchChannelEdgesByOutpoint(
return info, pol1, pol2, nil
}
func (g *mockGraph) ApplyChannelUpdate(update *lnwire.ChannelUpdate) error {
func (g *mockGraph) ApplyChannelUpdate(update *lnwire.ChannelUpdate,
op *wire.OutPoint, private bool) error {
g.mu.Lock()
defer g.mu.Unlock()

View file

@ -330,6 +330,18 @@ type Config struct {
// from the peer.
HandleCustomMessage func(peer [33]byte, msg *lnwire.Custom) error
// GetAliases is passed to created links so the Switch and link can be
// aware of the channel's aliases.
GetAliases func(base lnwire.ShortChannelID) []lnwire.ShortChannelID
// RequestAlias allows the Brontide struct to request an alias to send
// to the peer.
RequestAlias func() (lnwire.ShortChannelID, error)
// AddLocalAlias persists an alias to an underlying alias store.
AddLocalAlias func(alias, base lnwire.ShortChannelID,
gossip bool) error
// PongBuf is a slice we'll reuse instead of allocating memory on the
// heap. Since only reads will occur and no writes, there is no need
// for any synchronization primitives. As a result, it's safe to share
@ -666,7 +678,65 @@ func (p *Brontide) loadActiveChannels(chans []*channeldb.OpenChannel) (
// cannot be loaded normally.
var msgs []lnwire.Message
scidAliasNegotiated := p.hasNegotiatedScidAlias()
for _, dbChan := range chans {
hasScidFeature := dbChan.ChanType.HasScidAliasFeature()
if scidAliasNegotiated && !hasScidFeature {
// We'll request and store an alias, making sure that a
// gossiper mapping is not created for the alias to the
// real SCID. This is done because the peer and funding
// manager are not aware of each other's states and if
// we did not do this, we would accept alias channel
// updates after 6 confirmations, which would be buggy.
// We'll queue a funding_locked message with the new
// alias. This should technically be done *after* the
// reestablish, but this behavior is pre-existing since
// the funding manager may already queue a
// funding_locked before the channel_reestablish.
if !dbChan.IsPending {
aliasScid, err := p.cfg.RequestAlias()
if err != nil {
return nil, err
}
err = p.cfg.AddLocalAlias(
aliasScid, dbChan.ShortChanID(), false,
)
if err != nil {
return nil, err
}
chanID := lnwire.NewChanIDFromOutPoint(
&dbChan.FundingOutpoint,
)
// Fetch the second commitment point to send in
// the funding_locked message.
second, err := dbChan.SecondCommitmentPoint()
if err != nil {
return nil, err
}
fundingLockedMsg := lnwire.NewFundingLocked(
chanID, second,
)
fundingLockedMsg.AliasScid = &aliasScid
msgs = append(msgs, fundingLockedMsg)
}
// If we've negotiated the option-scid-alias feature
// and this channel does not have ScidAliasFeature set
// to true due to an upgrade where the feature bit was
// turned on, we'll update the channel's database
// state.
err := dbChan.MarkScidAliasNegotiated()
if err != nil {
return nil, err
}
}
lnChan, err := lnwallet.NewLightningChannel(
p.cfg.Signer, dbChan, p.cfg.SigPool,
)
@ -900,6 +970,7 @@ func (p *Brontide) addLink(chanPoint *wire.OutPoint,
NotifyActiveChannel: p.cfg.ChannelNotifier.NotifyActiveChannelEvent,
NotifyInactiveChannel: p.cfg.ChannelNotifier.NotifyInactiveChannelEvent,
HtlcNotifier: p.cfg.HtlcNotifier,
GetAliases: p.cfg.GetAliases,
}
// Before adding our new link, purge the switch of any pending or live
@ -3054,6 +3125,14 @@ func (p *Brontide) RemoteFeatures() *lnwire.FeatureVector {
return p.remoteFeatures
}
// hasNegotiatedScidAlias returns true if we've negotiated the
// option-scid-alias feature bit with the peer.
func (p *Brontide) hasNegotiatedScidAlias() bool {
peerHas := p.remoteFeatures.HasFeature(lnwire.ScidAliasOptional)
localHas := p.cfg.Features.HasFeature(lnwire.ScidAliasOptional)
return peerHas && localHas
}
// sendInitMsg sends the Init message to the remote peer. This message contains
// our currently supported local and global features.
func (p *Brontide) sendInitMsg(legacyChan bool) error {

View file

@ -340,7 +340,11 @@ func createTestPeer(notifier chainntnfs.ChainNotifier,
OurPubKey: aliceKeyPub,
OurKeyLoc: testKeyLoc,
IsChannelActive: func(lnwire.ChannelID) bool { return true },
ApplyChannelUpdate: func(*lnwire.ChannelUpdate) error { return nil },
ApplyChannelUpdate: func(*lnwire.ChannelUpdate,
*wire.OutPoint, bool) error {
return nil
},
})
if err != nil {
return nil, nil, nil, err

View file

@ -2138,7 +2138,9 @@ func (s *server) Stop() error {
s.connMgr.Stop()
// Shutdown the wallet, funding manager, and the rpc server.
s.chanStatusMgr.Stop()
if err := s.chanStatusMgr.Stop(); err != nil {
srvrLog.Warnf("failed to stop chanStatusMgr: %v", err)
}
if err := s.htlcSwitch.Stop(); err != nil {
srvrLog.Warnf("failed to stop htlcSwitch: %v", err)
}
@ -3175,7 +3177,6 @@ func (s *server) NotifyWhenOnline(peerKey [33]byte,
peerChan chan<- lnpeer.Peer) {
s.mu.Lock()
defer s.mu.Unlock()
// Compute the target peer's identifier.
pubStr := string(peerKey[:])
@ -3183,6 +3184,19 @@ func (s *server) NotifyWhenOnline(peerKey [33]byte,
// Check if peer is connected.
peer, ok := s.peersByPub[pubStr]
if ok {
// Unlock here so that the mutex isn't held while we are
// waiting for the peer to become active.
s.mu.Unlock()
// Wait until the peer signals that it is actually active
// rather than only in the server's maps.
select {
case <-peer.ActiveSignal():
case <-peer.QuitSignal():
// The peer quit so we'll just return.
return
}
// Connected, can return early.
srvrLog.Debugf("Notifying that peer %x is online", peerKey)
@ -3199,6 +3213,7 @@ func (s *server) NotifyWhenOnline(peerKey [33]byte,
s.peerConnectedListeners[pubStr] = append(
s.peerConnectedListeners[pubStr], peerChan,
)
s.mu.Unlock()
}
// NotifyWhenOffline delivers a notification to the caller of when the peer with
@ -3696,6 +3711,9 @@ func (s *server) peerConnected(conn net.Conn, connReq *connmgr.ConnReq,
PendingCommitInterval: s.cfg.PendingCommitInterval,
ChannelCommitBatchSize: s.cfg.ChannelCommitBatchSize,
HandleCustomMessage: s.handleCustomMessage,
GetAliases: s.aliasMgr.GetAliases,
RequestAlias: s.aliasMgr.RequestAlias,
AddLocalAlias: s.aliasMgr.AddLocalAlias,
Quit: s.quit,
}
@ -4444,9 +4462,30 @@ func (s *server) fetchLastChanUpdate() func(lnwire.ShortChannelID) (
}
// applyChannelUpdate applies the channel update to the different sub-systems of
// the server.
func (s *server) applyChannelUpdate(update *lnwire.ChannelUpdate) error {
errChan := s.authGossiper.ProcessLocalAnnouncement(update)
// the server. The useAlias boolean denotes whether or not to send an alias in
// place of the real SCID.
func (s *server) applyChannelUpdate(update *lnwire.ChannelUpdate,
op *wire.OutPoint, useAlias bool) error {
var (
peerAlias *lnwire.ShortChannelID
defaultAlias lnwire.ShortChannelID
)
chanID := lnwire.NewChanIDFromOutPoint(op)
// Fetch the peer's alias from the lnwire.ChannelID so it can be used
// in the ChannelUpdate if it hasn't been announced yet.
if useAlias {
foundAlias, _ := s.aliasMgr.GetPeerAlias(chanID)
if foundAlias != defaultAlias {
peerAlias = &foundAlias
}
}
errChan := s.authGossiper.ProcessLocalAnnouncement(
update, discovery.RemoteAlias(peerAlias),
)
select {
case err := <-errChan:
return err