peer: update and use SyncMap in Brontide

This commit applies methods `ForEach` and `Len` to `Brontide`.
This commit is contained in:
yyforyongyu committed 2023-06-27 20:19:37 +08:00
1 parent a66d42c682
commit ccb86a9d1d
2 files changed
+66 -72

No files matched your search

+65 -71
View File
@@ -32,6 +32,7 @@ import (
"github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/invoices" "github.com/lightningnetwork/lnd/invoices"
"github.com/lightningnetwork/lnd/lnpeer" "github.com/lightningnetwork/lnd/lnpeer"
"github.com/lightningnetwork/lnd/lnutils"
"github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwallet/chainfee"
"github.com/lightningnetwork/lnd/lnwallet/chancloser" "github.com/lightningnetwork/lnd/lnwallet/chancloser"
@@ -403,10 +404,6 @@ type Brontide struct {
// objects to queue messages to be sent out on the wire. // objects to queue messages to be sent out on the wire.
outgoingQueue chan outgoingMsg outgoingQueue chan outgoingMsg
// activeChanMtx protects access to the activeChannels and
// addedChannels maps.
activeChanMtx sync.RWMutex
// activeChannels is a map which stores the state machines of all // activeChannels is a map which stores the state machines of all
// active channels. Channels are indexed into the map by the txid of // active channels. Channels are indexed into the map by the txid of
// the funding transaction which opened the channel. // the funding transaction which opened the channel.
@@ -417,13 +414,14 @@ type Brontide struct {
// see if this is a pending channel or not. The tradeoff here is either // see if this is a pending channel or not. The tradeoff here is either
// having two maps everywhere (one for pending, one for confirmed chans) // having two maps everywhere (one for pending, one for confirmed chans)
// or having an extra nil-check per access. // or having an extra nil-check per access.
activeChannels map[lnwire.ChannelID]*lnwallet.LightningChannel activeChannels *lnutils.SyncMap[
lnwire.ChannelID, *lnwallet.LightningChannel]
// addedChannels tracks any new channels opened during this peer's // addedChannels tracks any new channels opened during this peer's
// lifecycle. We use this to filter out these new channels when the time // lifecycle. We use this to filter out these new channels when the time
// comes to request a reenable for active channels, since they will have // comes to request a reenable for active channels, since they will have
// waited a shorter duration. // waited a shorter duration.
addedChannels map[lnwire.ChannelID]struct{} addedChannels *lnutils.SyncMap[lnwire.ChannelID, struct{}]
// newChannels is used by the fundingManager to send fully opened // newChannels is used by the fundingManager to send fully opened
// channels to the source peer which handled the funding workflow. // channels to the source peer which handled the funding workflow.
@@ -487,13 +485,15 @@ func NewBrontide(cfg Config) *Brontide {
logPrefix := fmt.Sprintf("Peer(%x):", cfg.PubKeyBytes) logPrefix := fmt.Sprintf("Peer(%x):", cfg.PubKeyBytes)
p := &Brontide{ p := &Brontide{
cfg: cfg, cfg: cfg,
activeSignal: make(chan struct{}), activeSignal: make(chan struct{}),
sendQueue: make(chan outgoingMsg), sendQueue: make(chan outgoingMsg),
outgoingQueue: make(chan outgoingMsg), outgoingQueue: make(chan outgoingMsg),
addedChannels: make(map[lnwire.ChannelID]struct{}), addedChannels: &lnutils.SyncMap[lnwire.ChannelID, struct{}]{},
activeChannels: make(map[lnwire.ChannelID]*lnwallet.LightningChannel), activeChannels: &lnutils.SyncMap[
newChannels: make(chan *newChannelMsg, 1), lnwire.ChannelID, *lnwallet.LightningChannel,
]{},
newChannels: make(chan *newChannelMsg, 1),
activeMsgStreams: make(map[lnwire.ChannelID]*msgStream), activeMsgStreams: make(map[lnwire.ChannelID]*msgStream),
activeChanCloses: make(map[lnwire.ChannelID]*chancloser.ChanCloser), activeChanCloses: make(map[lnwire.ChannelID]*chancloser.ChanCloser),
@@ -884,9 +884,7 @@ func (p *Brontide) loadActiveChannels(chans []*channeldb.OpenChannel) (
// here would just be extra work as we'll tear them down when creating // here would just be extra work as we'll tear them down when creating
// + adding the final link. // + adding the final link.
if lnChan.IsPending() { if lnChan.IsPending() {
p.activeChanMtx.Lock() p.activeChannels.Store(chanID, nil)
p.activeChannels[chanID] = nil
p.activeChanMtx.Unlock()
continue continue
} }
@@ -908,9 +906,7 @@ func (p *Brontide) loadActiveChannels(chans []*channeldb.OpenChannel) (
"switch: %v", chanPoint, err) "switch: %v", chanPoint, err)
} }
p.activeChanMtx.Lock() p.activeChannels.Store(chanID, lnChan)
p.activeChannels[chanID] = lnChan
p.activeChanMtx.Unlock()
} }
return msgs, nil return msgs, nil
@@ -1667,9 +1663,7 @@ func (p *Brontide) handleCustomMessage(msg *lnwire.Custom) error {
// isActiveChannel returns true if the provided channel id is active, otherwise // isActiveChannel returns true if the provided channel id is active, otherwise
// returns false. // returns false.
func (p *Brontide) isActiveChannel(chanID lnwire.ChannelID) bool { func (p *Brontide) isActiveChannel(chanID lnwire.ChannelID) bool {
p.activeChanMtx.RLock() _, ok := p.activeChannels.Load(chanID)
_, ok := p.activeChannels[chanID]
p.activeChanMtx.RUnlock()
return ok return ok
} }
@@ -1680,17 +1674,20 @@ func (p *Brontide) isActiveChannel(chanID lnwire.ChannelID) bool {
func (p *Brontide) storeError(err error) { func (p *Brontide) storeError(err error) {
var haveChannels bool var haveChannels bool
p.activeChanMtx.RLock() p.activeChannels.Range(func(_ lnwire.ChannelID,
for _, channel := range p.activeChannels { channel *lnwallet.LightningChannel) bool {
// Pending channels will be nil in the activeChannels map. // Pending channels will be nil in the activeChannels map.
if channel == nil { if channel == nil {
continue // Return true to continue the iteration.
return true
} }
haveChannels = true haveChannels = true
break
} // Return false to break the iteration.
p.activeChanMtx.RUnlock() return false
})
// If we do not have any active channels with the peer, we do not store // If we do not have any active channels with the peer, we do not store
// errors as a dos mitigation. // errors as a dos mitigation.
@@ -2286,25 +2283,30 @@ func (p *Brontide) queue(priority bool, msg lnwire.Message,
// ChannelSnapshots returns a slice of channel snapshots detailing all // ChannelSnapshots returns a slice of channel snapshots detailing all
// currently active channels maintained with the remote peer. // currently active channels maintained with the remote peer.
func (p *Brontide) ChannelSnapshots() []*channeldb.ChannelSnapshot { func (p *Brontide) ChannelSnapshots() []*channeldb.ChannelSnapshot {
p.activeChanMtx.RLock() snapshots := make(
defer p.activeChanMtx.RUnlock() []*channeldb.ChannelSnapshot, 0, p.activeChannels.Len(),
)
snapshots := make([]*channeldb.ChannelSnapshot, 0, len(p.activeChannels)) p.activeChannels.ForEach(func(_ lnwire.ChannelID,
for _, activeChan := range p.activeChannels { activeChan *lnwallet.LightningChannel) error {
// If the activeChan is nil, then we skip it as the channel is pending.
// If the activeChan is nil, then we skip it as the channel is
// pending.
if activeChan == nil { if activeChan == nil {
continue return nil
} }
// We'll only return a snapshot for channels that are // We'll only return a snapshot for channels that are
// *immediately* available for routing payments over. // *immediately* available for routing payments over.
if activeChan.RemoteNextRevocation() == nil { if activeChan.RemoteNextRevocation() == nil {
continue return nil
} }
snapshot := activeChan.StateSnapshot() snapshot := activeChan.StateSnapshot()
snapshots = append(snapshots, snapshot) snapshots = append(snapshots, snapshot)
}
return nil
})
return snapshots return snapshots
} }
@@ -2358,13 +2360,11 @@ out:
// Only update RemoteNextRevocation if the channel is in the // Only update RemoteNextRevocation if the channel is in the
// activeChannels map and if we added the link to the switch. // activeChannels map and if we added the link to the switch.
// Only active channels will be added to the switch. // Only active channels will be added to the switch.
p.activeChanMtx.Lock() currentChan, ok := p.activeChannels.Load(chanID)
currentChan, ok := p.activeChannels[chanID]
if ok && currentChan != nil { if ok && currentChan != nil {
p.log.Infof("Already have ChannelPoint(%v), "+ p.log.Infof("Already have ChannelPoint(%v), "+
"ignoring.", chanPoint) "ignoring.", chanPoint)
p.activeChanMtx.Unlock()
close(newChanReq.err) close(newChanReq.err)
// If we're being sent a new channel, and our // If we're being sent a new channel, and our
@@ -2397,7 +2397,6 @@ out:
p.cfg.Signer, newChan, p.cfg.SigPool, p.cfg.Signer, newChan, p.cfg.SigPool,
) )
if err != nil { if err != nil {
p.activeChanMtx.Unlock()
err := fmt.Errorf("unable to create "+ err := fmt.Errorf("unable to create "+
"LightningChannel: %v", err) "LightningChannel: %v", err)
p.log.Errorf(err.Error()) p.log.Errorf(err.Error())
@@ -2408,9 +2407,8 @@ out:
// This refreshes the activeChannels entry if the link was not in // This refreshes the activeChannels entry if the link was not in
// the switch, also populates for new entries. // the switch, also populates for new entries.
p.activeChannels[chanID] = lnChan p.activeChannels.Store(chanID, lnChan)
p.addedChannels[chanID] = struct{}{} p.addedChannels.Store(chanID, struct{}{})
p.activeChanMtx.Unlock()
p.log.Infof("New channel active ChannelPoint(%v) "+ p.log.Infof("New channel active ChannelPoint(%v) "+
"with peer", chanPoint) "with peer", chanPoint)
@@ -2525,16 +2523,19 @@ out:
case <-p.quit: case <-p.quit:
// As, we've been signalled to exit, we'll reset all // As, we've been signalled to exit, we'll reset all
// our active channel back to their default state. // our active channel back to their default state.
p.activeChanMtx.Lock() p.activeChannels.ForEach(func(_ lnwire.ChannelID,
for _, channel := range p.activeChannels { lc *lnwallet.LightningChannel) error {
// If the channel is nil, continue as it's a pending channel.
if channel == nil { // Exit if the channel is nil as it's a pending
continue // channel.
if lc == nil {
return nil
} }
channel.ResetState() lc.ResetState()
}
p.activeChanMtx.Unlock() return nil
})
break out break out
} }
@@ -2624,9 +2625,7 @@ func (p *Brontide) fetchActiveChanCloser(chanID lnwire.ChannelID) (
// First, we'll ensure that we actually know of the target channel. If // First, we'll ensure that we actually know of the target channel. If
// not, we'll ignore this message. // not, we'll ignore this message.
p.activeChanMtx.RLock() channel, ok := p.activeChannels.Load(chanID)
channel, ok := p.activeChannels[chanID]
p.activeChanMtx.RUnlock()
// If the channel isn't in the map or the channel is nil, return // If the channel isn't in the map or the channel is nil, return
// ErrChannelNotFound as the channel is pending. // ErrChannelNotFound as the channel is pending.
@@ -2688,19 +2687,18 @@ func (p *Brontide) fetchActiveChanCloser(chanID lnwire.ChannelID) (
func (p *Brontide) filterChannelsToEnable() []wire.OutPoint { func (p *Brontide) filterChannelsToEnable() []wire.OutPoint {
var activePublicChans []wire.OutPoint var activePublicChans []wire.OutPoint
p.activeChanMtx.RLock() p.activeChannels.Range(func(chanID lnwire.ChannelID,
defer p.activeChanMtx.RUnlock() lnChan *lnwallet.LightningChannel) bool {
for chanID, lnChan := range p.activeChannels {
// If the lnChan is nil, continue as this is a pending channel. // If the lnChan is nil, continue as this is a pending channel.
if lnChan == nil { if lnChan == nil {
continue return true
} }
dbChan := lnChan.State() dbChan := lnChan.State()
isPublic := dbChan.ChannelFlags&lnwire.FFAnnounceChannel != 0 isPublic := dbChan.ChannelFlags&lnwire.FFAnnounceChannel != 0
if !isPublic || dbChan.IsPending { if !isPublic || dbChan.IsPending {
continue return true
} }
// We'll also skip any channels added during this peer's // We'll also skip any channels added during this peer's
@@ -2708,14 +2706,16 @@ func (p *Brontide) filterChannelsToEnable() []wire.OutPoint {
// first announcement will be enabled, and the chan status // first announcement will be enabled, and the chan status
// manager will begin monitoring them passively since they exist // manager will begin monitoring them passively since they exist
// in the database. // in the database.
if _, ok := p.addedChannels[chanID]; ok { if _, ok := p.addedChannels.Load(chanID); ok {
continue return true
} }
activePublicChans = append( activePublicChans = append(
activePublicChans, dbChan.FundingOutpoint, activePublicChans, dbChan.FundingOutpoint,
) )
}
return true
})
return activePublicChans return activePublicChans
} }
@@ -2969,9 +2969,7 @@ func (p *Brontide) createChanCloser(channel *lnwallet.LightningChannel,
func (p *Brontide) handleLocalCloseReq(req *htlcswitch.ChanClose) { func (p *Brontide) handleLocalCloseReq(req *htlcswitch.ChanClose) {
chanID := lnwire.NewChanIDFromOutPoint(req.ChanPoint) chanID := lnwire.NewChanIDFromOutPoint(req.ChanPoint)
p.activeChanMtx.RLock() channel, ok := p.activeChannels.Load(chanID)
channel, ok := p.activeChannels[chanID]
p.activeChanMtx.RUnlock()
// Though this function can't be called for pending channels, we still // Though this function can't be called for pending channels, we still
// check whether channel is nil for safety. // check whether channel is nil for safety.
@@ -3081,9 +3079,7 @@ func (p *Brontide) handleLinkFailure(failure linkFailureReport) {
// Retrieve the channel from the map of active channels. We do this to // Retrieve the channel from the map of active channels. We do this to
// have access to it even after WipeChannel remove it from the map. // have access to it even after WipeChannel remove it from the map.
chanID := lnwire.NewChanIDFromOutPoint(&failure.chanPoint) chanID := lnwire.NewChanIDFromOutPoint(&failure.chanPoint)
p.activeChanMtx.Lock() lnChan, _ := p.activeChannels.Load(chanID)
lnChan := p.activeChannels[chanID]
p.activeChanMtx.Unlock()
// We begin by wiping the link, which will remove it from the switch, // We begin by wiping the link, which will remove it from the switch,
// such that it won't be attempted used for any more updates. // such that it won't be attempted used for any more updates.
@@ -3305,9 +3301,7 @@ func WaitForChanToClose(bestHeight uint32, notifier chainntnfs.ChainNotifier,
func (p *Brontide) WipeChannel(chanPoint *wire.OutPoint) { func (p *Brontide) WipeChannel(chanPoint *wire.OutPoint) {
chanID := lnwire.NewChanIDFromOutPoint(chanPoint) chanID := lnwire.NewChanIDFromOutPoint(chanPoint)
p.activeChanMtx.Lock() p.activeChannels.Delete(chanID)
delete(p.activeChannels, chanID)
p.activeChanMtx.Unlock()
// Instruct the HtlcSwitch to close this link as the channel is no // Instruct the HtlcSwitch to close this link as the channel is no
// longer active. // longer active.
+1 -1
View File
@@ -408,7 +408,7 @@ func createTestPeer(t *testing.T, notifier chainntnfs.ChainNotifier,
alicePeer.remoteFeatures = lnwire.NewFeatureVector(nil, lnwire.Features) alicePeer.remoteFeatures = lnwire.NewFeatureVector(nil, lnwire.Features)
chanID := lnwire.NewChanIDFromOutPoint(channelAlice.ChannelPoint()) chanID := lnwire.NewChanIDFromOutPoint(channelAlice.ChannelPoint())
alicePeer.activeChannels[chanID] = channelAlice alicePeer.activeChannels.Store(chanID, channelAlice)
alicePeer.wg.Add(1) alicePeer.wg.Add(1)
go alicePeer.channelManager() go alicePeer.channelManager()