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 }