@@ -10,6 +10,11 @@ import (
1010 "github.com/lightningnetwork/lnd/lnwire"
1111)
1212
13+ // UpdateLinkAliases locates the active link that matches the given
14+ // shortID and triggers an update based on the latest values of the
15+ // alias manager.
16+ type UpdateLinkAliases func (shortID lnwire.ShortChannelID ) error
17+
1318var (
1419 // aliasBucket stores aliases as keys and their base SCIDs as values.
1520 // This is used to populate the maps that the Manager uses. The keys
7782type Manager struct {
7883 backend kvdb.Backend
7984
85+ // LinkUpdater is a function used by aliasmgr to facilitate live update
86+ // of aliases in other subsystems.
87+ LinkUpdater UpdateLinkAliases
88+
8089 // baseToSet is a mapping from the "base" SCID to the set of aliases
8190 // for this channel. This mapping includes all channels that
8291 // negotiated the option-scid-alias feature bit.
@@ -98,11 +107,14 @@ type Manager struct {
98107}
99108
100109// NewManager initializes an alias Manager from the passed database backend.
101- func NewManager (db kvdb.Backend ) (* Manager , error ) {
110+ func NewManager (db kvdb.Backend ,
111+ linkUpdater UpdateLinkAliases ) (* Manager , error ) {
112+
102113 m := & Manager {backend : db }
103114 m .baseToSet = make (map [lnwire.ShortChannelID ][]lnwire.ShortChannelID )
104115 m .aliasToBase = make (map [lnwire.ShortChannelID ]lnwire.ShortChannelID )
105116 m .peerAlias = make (map [lnwire.ChannelID ]lnwire.ShortChannelID )
117+ m .LinkUpdater = linkUpdater
106118
107119 err := m .populateMaps ()
108120 return m , err
@@ -215,12 +227,22 @@ func (m *Manager) populateMaps() error {
215227// AddLocalAlias adds a database mapping from the passed alias to the passed
216228// base SCID. The gossip boolean marks whether or not to create a mapping
217229// that the gossiper will use. It is set to false for the upgrade path where
218- // the feature-bit is toggled on and there are existing channels.
230+ // the feature-bit is toggled on and there are existing channels. The linkUpdate
231+ // flag is used to signal whether this function should also trigger an update
232+ // on the htlcswitch scid alias maps.
219233func (m * Manager ) AddLocalAlias (alias , baseScid lnwire.ShortChannelID ,
220- gossip bool ) error {
234+ gossip , linkUpdate bool ) error {
221235
236+ // We need to lock the manager for the whole duration of this method,
237+ // except for the very last part where we call the link updater. In
238+ // order for us to safely use a defer _and_ still be able to manually
239+ // unlock, we use a sync.Once.
222240 m .Lock ()
223- defer m .Unlock ()
241+ unlockOnce := sync.Once {}
242+ unlock := func () {
243+ unlockOnce .Do (m .Unlock )
244+ }
245+ defer unlock ()
224246
225247 err := kvdb .Update (m .backend , func (tx kvdb.RwTx ) error {
226248 // If the caller does not want to allow the alias to be used
@@ -270,6 +292,18 @@ func (m *Manager) AddLocalAlias(alias, baseScid lnwire.ShortChannelID,
270292 m .aliasToBase [alias ] = baseScid
271293 }
272294
295+ // We definitely need to unlock the Manager before calling the link
296+ // updater. If we don't, we'll deadlock. We use a sync.Once to ensure
297+ // that we only unlock once.
298+ unlock ()
299+
300+ // Finally, we trigger a htlcswitch update if the flag is set, in order
301+ // for any future htlc that references the added alias to be properly
302+ // routed.
303+ if linkUpdate {
304+ return m .LinkUpdater (baseScid )
305+ }
306+
273307 return nil
274308}
275309
@@ -340,6 +374,72 @@ func (m *Manager) DeleteSixConfs(baseScid lnwire.ShortChannelID) error {
340374 return nil
341375}
342376
377+ // DeleteLocalAlias removes a mapping from the database and the Manager's maps.
378+ func (m * Manager ) DeleteLocalAlias (alias ,
379+ baseScid lnwire.ShortChannelID ) error {
380+
381+ // We need to lock the manager for the whole duration of this method,
382+ // except for the very last part where we call the link updater. In
383+ // order for us to safely use a defer _and_ still be able to manually
384+ // unlock, we use a sync.Once.
385+ m .Lock ()
386+ unlockOnce := sync.Once {}
387+ unlock := func () {
388+ unlockOnce .Do (m .Unlock )
389+ }
390+ defer unlock ()
391+
392+ err := kvdb .Update (m .backend , func (tx kvdb.RwTx ) error {
393+ aliasToBaseBucket , err := tx .CreateTopLevelBucket (aliasBucket )
394+ if err != nil {
395+ return err
396+ }
397+
398+ var aliasBytes [8 ]byte
399+ byteOrder .PutUint64 (aliasBytes [:], alias .ToUint64 ())
400+
401+ return aliasToBaseBucket .Delete (aliasBytes [:])
402+ }, func () {})
403+ if err != nil {
404+ return err
405+ }
406+
407+ // Now that the database state has been updated, we'll delete the
408+ // mapping from the Manager's maps.
409+ aliasSet , ok := m .baseToSet [baseScid ]
410+ if ! ok {
411+ return nil
412+ }
413+
414+ // We'll iterate through the alias set and remove the alias from the
415+ // set.
416+ for i , a := range aliasSet {
417+ if a .ToUint64 () == alias .ToUint64 () {
418+ aliasSet = append (aliasSet [:i ], aliasSet [i + 1 :]... )
419+ break
420+ }
421+ }
422+
423+ // If the alias set is empty, we'll delete the base SCID from the
424+ // baseToSet map.
425+ if len (aliasSet ) == 0 {
426+ delete (m .baseToSet , baseScid )
427+ } else {
428+ m .baseToSet [baseScid ] = aliasSet
429+ }
430+
431+ // Finally, we'll delete the aliasToBase mapping from the Manager's
432+ // cache.
433+ delete (m .aliasToBase , alias )
434+
435+ // We definitely need to unlock the Manager before calling the link
436+ // updater. If we don't, we'll deadlock. We use a sync.Once to ensure
437+ // that we only unlock once.
438+ unlock ()
439+
440+ return m .LinkUpdater (baseScid )
441+ }
442+
343443// PutPeerAlias stores the peer's alias SCID once we learn of it in the
344444// channel_ready message.
345445func (m * Manager ) PutPeerAlias (chanID lnwire.ChannelID ,
0 commit comments