Skip to content

Commit

Permalink
server+netann+peer: put peer's alias in Update, proper config for link
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Crypt-iQ committed Jul 7, 2022
1 parent 778be5b commit b9ef260
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 15 deletions.
21 changes: 13 additions & 8 deletions netann/chan_status_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}
Expand All @@ -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
Expand All @@ -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
}
Expand Down
4 changes: 3 additions & 1 deletion netann/chan_status_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down
79 changes: 79 additions & 0 deletions peer/brontide.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
6 changes: 5 additions & 1 deletion peer/test_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
49 changes: 44 additions & 5 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -3175,14 +3177,26 @@ 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[:])

// 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)

Expand All @@ -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
Expand Down Expand Up @@ -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,
}

Expand Down Expand Up @@ -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
Expand Down

0 comments on commit b9ef260

Please sign in to comment.