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  }