github.com/decred/dcrlnd@v0.7.6/channelnotifier/channelnotifier.go (about) 1 package channelnotifier 2 3 import ( 4 "sync" 5 6 "github.com/decred/dcrd/wire" 7 "github.com/decred/dcrlnd/channeldb" 8 "github.com/decred/dcrlnd/subscribe" 9 ) 10 11 // ChannelNotifier is a subsystem which all active, inactive, and closed channel 12 // events pipe through. It takes subscriptions for its events, and whenever 13 // it receives a new event it notifies its subscribers over the proper channel. 14 type ChannelNotifier struct { 15 started sync.Once 16 stopped sync.Once 17 18 ntfnServer *subscribe.Server 19 20 chanDB *channeldb.ChannelStateDB 21 } 22 23 // PendingOpenChannelEvent represents a new event where a new channel has 24 // entered a pending open state. 25 type PendingOpenChannelEvent struct { 26 // ChannelPoint is the channel outpoint for the new channel. 27 ChannelPoint *wire.OutPoint 28 29 // PendingChannel is the channel configuration for the newly created 30 // channel. This might not have been persisted to the channel DB yet 31 // because we are still waiting for the final message from the remote 32 // peer. 33 PendingChannel *channeldb.OpenChannel 34 } 35 36 // OpenChannelEvent represents a new event where a channel goes from pending 37 // open to open. 38 type OpenChannelEvent struct { 39 // Channel is the channel that has become open. 40 Channel *channeldb.OpenChannel 41 } 42 43 // ActiveLinkEvent represents a new event where the link becomes active in the 44 // switch. This happens before the ActiveChannelEvent. 45 type ActiveLinkEvent struct { 46 // ChannelPoint is the channel point for the newly active channel. 47 ChannelPoint *wire.OutPoint 48 } 49 50 // ActiveChannelEvent represents a new event where a channel becomes active. 51 type ActiveChannelEvent struct { 52 // ChannelPoint is the channelpoint for the newly active channel. 53 ChannelPoint *wire.OutPoint 54 } 55 56 // InactiveChannelEvent represents a new event where a channel becomes inactive. 57 type InactiveChannelEvent struct { 58 // ChannelPoint is the channelpoint for the newly inactive channel. 59 ChannelPoint *wire.OutPoint 60 } 61 62 // ClosedChannelEvent represents a new event where a channel becomes closed. 63 type ClosedChannelEvent struct { 64 // CloseSummary is the summary of the channel close that has occurred. 65 CloseSummary *channeldb.ChannelCloseSummary 66 } 67 68 // FullyResolvedChannelEvent represents a new event where a channel becomes 69 // fully resolved. 70 type FullyResolvedChannelEvent struct { 71 // ChannelPoint is the channelpoint for the newly fully resolved 72 // channel. 73 ChannelPoint *wire.OutPoint 74 } 75 76 // New creates a new channel notifier. The ChannelNotifier gets channel 77 // events from peers and from the chain arbitrator, and dispatches them to 78 // its clients. 79 func New(chanDB *channeldb.ChannelStateDB) *ChannelNotifier { 80 return &ChannelNotifier{ 81 ntfnServer: subscribe.NewServer(), 82 chanDB: chanDB, 83 } 84 } 85 86 // Start starts the ChannelNotifier and all goroutines it needs to carry out its task. 87 func (c *ChannelNotifier) Start() error { 88 var err error 89 c.started.Do(func() { 90 log.Trace("ChannelNotifier starting") 91 err = c.ntfnServer.Start() 92 }) 93 return err 94 } 95 96 // Stop signals the notifier for a graceful shutdown. 97 func (c *ChannelNotifier) Stop() error { 98 var err error 99 c.stopped.Do(func() { 100 log.Info("ChannelNotifier shutting down") 101 err = c.ntfnServer.Stop() 102 }) 103 return err 104 } 105 106 // SubscribeChannelEvents returns a subscribe.Client that will receive updates 107 // any time the Server is made aware of a new event. The subscription provides 108 // channel events from the point of subscription onwards. 109 // 110 // TODO(carlaKC): update to allow subscriptions to specify a block height from 111 // which we would like to subscribe to events. 112 func (c *ChannelNotifier) SubscribeChannelEvents() (*subscribe.Client, error) { 113 return c.ntfnServer.Subscribe() 114 } 115 116 // NotifyPendingOpenChannelEvent notifies the channelEventNotifier goroutine 117 // that a new channel is pending. The pending channel is passed as a parameter 118 // instead of read from the database because it might not yet have been 119 // persisted to the DB because we still wait for the final message from the 120 // remote peer. 121 func (c *ChannelNotifier) NotifyPendingOpenChannelEvent(chanPoint wire.OutPoint, 122 pendingChan *channeldb.OpenChannel) { 123 124 event := PendingOpenChannelEvent{ 125 ChannelPoint: &chanPoint, 126 PendingChannel: pendingChan, 127 } 128 129 if err := c.ntfnServer.SendUpdate(event); err != nil { 130 log.Warnf("Unable to send pending open channel update: %v", err) 131 } 132 } 133 134 // NotifyOpenChannelEvent notifies the channelEventNotifier goroutine that a 135 // channel has gone from pending open to open. 136 func (c *ChannelNotifier) NotifyOpenChannelEvent(chanPoint wire.OutPoint) { 137 // Fetch the relevant channel from the database. 138 channel, err := c.chanDB.FetchChannel(nil, chanPoint) 139 if err != nil { 140 log.Warnf("Unable to fetch open channel from the db: %v", err) 141 } 142 143 // Send the open event to all channel event subscribers. 144 event := OpenChannelEvent{Channel: channel} 145 if err := c.ntfnServer.SendUpdate(event); err != nil { 146 log.Warnf("Unable to send open channel update: %v", err) 147 } 148 } 149 150 // NotifyClosedChannelEvent notifies the channelEventNotifier goroutine that a 151 // channel has closed. 152 func (c *ChannelNotifier) NotifyClosedChannelEvent(chanPoint wire.OutPoint) { 153 // Fetch the relevant closed channel from the database. 154 closeSummary, err := c.chanDB.FetchClosedChannel(&chanPoint) 155 if err != nil { 156 log.Warnf("Unable to fetch closed channel summary from the db: %v", err) 157 } 158 159 // Send the closed event to all channel event subscribers. 160 event := ClosedChannelEvent{CloseSummary: closeSummary} 161 if err := c.ntfnServer.SendUpdate(event); err != nil { 162 log.Warnf("Unable to send closed channel update: %v", err) 163 } 164 } 165 166 // NotifyFullyResolvedChannelEvent notifies the channelEventNotifier goroutine 167 // that a channel was fully resolved on chain. 168 func (c *ChannelNotifier) NotifyFullyResolvedChannelEvent( 169 chanPoint wire.OutPoint) { 170 171 // Send the resolved event to all channel event subscribers. 172 event := FullyResolvedChannelEvent{ChannelPoint: &chanPoint} 173 if err := c.ntfnServer.SendUpdate(event); err != nil { 174 log.Warnf("Unable to send resolved channel update: %v", err) 175 } 176 } 177 178 // NotifyActiveLinkEvent notifies the channelEventNotifier goroutine that a 179 // link has been added to the switch. 180 func (c *ChannelNotifier) NotifyActiveLinkEvent(chanPoint wire.OutPoint) { 181 event := ActiveLinkEvent{ChannelPoint: &chanPoint} 182 if err := c.ntfnServer.SendUpdate(event); err != nil { 183 log.Warnf("Unable to send active link update: %v", err) 184 } 185 } 186 187 // NotifyActiveChannelEvent notifies the channelEventNotifier goroutine that a 188 // channel is active. 189 func (c *ChannelNotifier) NotifyActiveChannelEvent(chanPoint wire.OutPoint) { 190 event := ActiveChannelEvent{ChannelPoint: &chanPoint} 191 if err := c.ntfnServer.SendUpdate(event); err != nil { 192 log.Warnf("Unable to send active channel update: %v", err) 193 } 194 } 195 196 // NotifyInactiveChannelEvent notifies the channelEventNotifier goroutine that a 197 // channel is inactive. 198 func (c *ChannelNotifier) NotifyInactiveChannelEvent(chanPoint wire.OutPoint) { 199 event := InactiveChannelEvent{ChannelPoint: &chanPoint} 200 if err := c.ntfnServer.SendUpdate(event); err != nil { 201 log.Warnf("Unable to send inactive channel update: %v", err) 202 } 203 }