github.com/decred/dcrd/blockchain@v1.2.1/notifications.go (about)

     1  // Copyright (c) 2013-2016 The btcsuite developers
     2  // Copyright (c) 2015-2016 The Decred developers
     3  // Use of this source code is governed by an ISC
     4  // license that can be found in the LICENSE file.
     5  
     6  package blockchain
     7  
     8  import (
     9  	"fmt"
    10  
    11  	"github.com/decred/dcrd/chaincfg/chainhash"
    12  	"github.com/decred/dcrd/dcrutil"
    13  )
    14  
    15  // NotificationType represents the type of a notification message.
    16  type NotificationType int
    17  
    18  // NotificationCallback is used for a caller to provide a callback for
    19  // notifications about various chain events.
    20  type NotificationCallback func(*Notification)
    21  
    22  // Constants for the type of a notification message.
    23  const (
    24  	// NTNewTipBlockChecked indicates the associated block intends to extend
    25  	// the current main chain and has passed all of the sanity and
    26  	// contextual checks such as having valid proof of work, valid merkle
    27  	// and stake roots, and only containing allowed votes and revocations.
    28  	//
    29  	// It should be noted that the block might still ultimately fail to
    30  	// become the new main chain tip if it contains invalid scripts, double
    31  	// spends, etc.  However, this is quite rare in practice because a lot
    32  	// of work was expended to create a block which satisifies the proof of
    33  	// work requirement.
    34  	//
    35  	// Finally, this notification is only sent if the the chain is believed
    36  	// to be current and the chain lock is NOT released, so consumers must
    37  	// take care to avoid calling blockchain functions to avoid potential
    38  	// deadlock.
    39  	//
    40  	// Typically, a caller would want to use this notification to relay the
    41  	// block to the rest of the network without needing to wait for the more
    42  	// time consuming full connection to take place.
    43  	NTNewTipBlockChecked NotificationType = iota
    44  
    45  	// NTBlockAccepted indicates the associated block was accepted into
    46  	// the block chain.  Note that this does not necessarily mean it was
    47  	// added to the main chain.  For that, use NTBlockConnected.
    48  	NTBlockAccepted
    49  
    50  	// NTBlockConnected indicates the associated block was connected to the
    51  	// main chain.
    52  	NTBlockConnected
    53  
    54  	// NTBlockDisconnected indicates the associated block was disconnected
    55  	// from the main chain.
    56  	NTBlockDisconnected
    57  
    58  	// NTChainReorgStarted indicates that a chain reorganization has commenced.
    59  	NTChainReorgStarted
    60  
    61  	// NTChainReorgDone indicates that a chain reorganization has concluded.
    62  	NTChainReorgDone
    63  
    64  	// NTReorganization indicates that a blockchain reorganization has taken
    65  	// place.
    66  	NTReorganization
    67  
    68  	// NTSpentAndMissedTickets indicates spent or missed tickets from a newly
    69  	// accepted block.
    70  	NTSpentAndMissedTickets
    71  
    72  	// NTSpentAndMissedTickets indicates newly maturing tickets from a newly
    73  	// accepted block.
    74  	NTNewTickets
    75  )
    76  
    77  // notificationTypeStrings is a map of notification types back to their constant
    78  // names for pretty printing.
    79  var notificationTypeStrings = map[NotificationType]string{
    80  	NTNewTipBlockChecked:    "NTNewTipBlockChecked",
    81  	NTBlockAccepted:         "NTBlockAccepted",
    82  	NTBlockConnected:        "NTBlockConnected",
    83  	NTBlockDisconnected:     "NTBlockDisconnected",
    84  	NTChainReorgStarted:     "NTChainReorgStarted",
    85  	NTChainReorgDone:        "NTChainReorgDone",
    86  	NTReorganization:        "NTReorganization",
    87  	NTSpentAndMissedTickets: "NTSpentAndMissedTickets",
    88  	NTNewTickets:            "NTNewTickets",
    89  }
    90  
    91  // String returns the NotificationType in human-readable form.
    92  func (n NotificationType) String() string {
    93  	if s, ok := notificationTypeStrings[n]; ok {
    94  		return s
    95  	}
    96  	return fmt.Sprintf("Unknown Notification Type (%d)", int(n))
    97  }
    98  
    99  // BlockAcceptedNtfnsData is the structure for data indicating information
   100  // about an accepted block.  Note that this does not necessarily mean the block
   101  // that was accepted extended the best chain as it might have created or
   102  // extended a side chain.
   103  type BlockAcceptedNtfnsData struct {
   104  	// BestHeight is the height of the current best chain.  Since the accepted
   105  	// block might be on a side chain, this is not necessarily the same as the
   106  	// height of the accepted block.
   107  	BestHeight int64
   108  
   109  	// ForkLen is the length of the side chain the block extended or zero in the
   110  	// case the block extended the main chain.
   111  	//
   112  	// This can be used in conjunction with the height of the accepted block to
   113  	// determine the height at which the side chain the block created or
   114  	// extended forked from the best chain.
   115  	ForkLen int64
   116  
   117  	// Block is the block that was accepted into the chain.
   118  	Block *dcrutil.Block
   119  }
   120  
   121  // ReorganizationNtfnsData is the structure for data indicating information
   122  // about a reorganization.
   123  type ReorganizationNtfnsData struct {
   124  	OldHash   chainhash.Hash
   125  	OldHeight int64
   126  	NewHash   chainhash.Hash
   127  	NewHeight int64
   128  }
   129  
   130  // TicketNotificationsData is the structure for new/spent/missed ticket
   131  // notifications at blockchain HEAD that are outgoing from chain.
   132  type TicketNotificationsData struct {
   133  	Hash            chainhash.Hash
   134  	Height          int64
   135  	StakeDifficulty int64
   136  	TicketsSpent    []chainhash.Hash
   137  	TicketsMissed   []chainhash.Hash
   138  	TicketsNew      []chainhash.Hash
   139  }
   140  
   141  // Notification defines notification that is sent to the caller via the callback
   142  // function provided during the call to New and consists of a notification type
   143  // as well as associated data that depends on the type as follows:
   144  // 	- NTNewTipBlockChecked:    *dcrutil.Block
   145  // 	- NTBlockAccepted:         *BlockAcceptedNtfnsData
   146  // 	- NTBlockConnected:        []*dcrutil.Block of len 2
   147  // 	- NTBlockDisconnected:     []*dcrutil.Block of len 2
   148  // 	- NTChainReorgStarted:     nil
   149  // 	- NTChainReorgDone:        nil
   150  //  - NTReorganization:        *ReorganizationNtfnsData
   151  //  - NTSpentAndMissedTickets: *TicketNotificationsData
   152  //  - NTNewTickets:            *TicketNotificationsData
   153  type Notification struct {
   154  	Type NotificationType
   155  	Data interface{}
   156  }
   157  
   158  // sendNotification sends a notification with the passed type and data if the
   159  // caller requested notifications by providing a callback function in the call
   160  // to New.
   161  func (b *BlockChain) sendNotification(typ NotificationType, data interface{}) {
   162  	// Ignore it if the caller didn't request notifications.
   163  	if b.notifications == nil {
   164  		return
   165  	}
   166  
   167  	// Generate and send the notification.
   168  	n := Notification{Type: typ, Data: data}
   169  	b.notifications(&n)
   170  }