chainntfns: document the BtcdNotifier implementation of ChainNotifier
This commit is contained in:
parent
77d37298f4
commit
9b9f792f10
@ -14,10 +14,12 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/chainntfs"
|
"github.com/lightningnetwork/lnd/chainntfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BtcdNotifier...
|
// BtcdNotifier implements the ChainNotifier interface using btcd's websockets
|
||||||
|
// notifications. Multiple concurrent clients are supported. All notifications
|
||||||
|
// are achieved via non-blocking sends on client channels.
|
||||||
type BtcdNotifier struct {
|
type BtcdNotifier struct {
|
||||||
started int32 // To be used atomically
|
started int32 // To be used atomically.
|
||||||
stopped int32 // To be used atomically
|
stopped int32 // To be used atomically.
|
||||||
|
|
||||||
chainConn *btcrpcclient.Client
|
chainConn *btcrpcclient.Client
|
||||||
|
|
||||||
@ -37,16 +39,14 @@ type BtcdNotifier struct {
|
|||||||
quit chan struct{}
|
quit chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure BtcdNotifier implements the ChainNotifier interface at compile time.
|
||||||
var _ chainntnfs.ChainNotifier = (*BtcdNotifier)(nil)
|
var _ chainntnfs.ChainNotifier = (*BtcdNotifier)(nil)
|
||||||
|
|
||||||
// NewBtcdNotifier...
|
// NewBtcdNotifier returns a new BtcdNotifier instance. This function assumes
|
||||||
// TODO(roasbeef):
|
// the btcd node detailed in the passed configuration is already running, and
|
||||||
// * when asked for spent, request via client
|
// willing to accept new websockets clients.
|
||||||
//func NewBtcdNotifier(ntfnSource *btcwallet.NotificationServer,
|
|
||||||
// chainConn *chain.RPCClient) (*BtcdNotifier, error) {
|
|
||||||
func NewBtcdNotifier(config *btcrpcclient.ConnConfig) (*BtcdNotifier, error) {
|
func NewBtcdNotifier(config *btcrpcclient.ConnConfig) (*BtcdNotifier, error) {
|
||||||
notifier := &BtcdNotifier{
|
notifier := &BtcdNotifier{
|
||||||
|
|
||||||
notificationRegistry: make(chan interface{}),
|
notificationRegistry: make(chan interface{}),
|
||||||
|
|
||||||
spendNotifications: make(map[wire.OutPoint]*spendNotification),
|
spendNotifications: make(map[wire.OutPoint]*spendNotification),
|
||||||
@ -66,6 +66,8 @@ func NewBtcdNotifier(config *btcrpcclient.ConnConfig) (*BtcdNotifier, error) {
|
|||||||
OnRedeemingTx: notifier.onRedeemingTx,
|
OnRedeemingTx: notifier.onRedeemingTx,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disable connecting to btcd within the btcrpcclient.New method. We defer
|
||||||
|
// establishing the connection to our .Start() method.
|
||||||
config.DisableConnectOnNew = true
|
config.DisableConnectOnNew = true
|
||||||
config.DisableAutoReconnect = false
|
config.DisableAutoReconnect = false
|
||||||
chainConn, err := btcrpcclient.New(config, ntfnCallbacks)
|
chainConn, err := btcrpcclient.New(config, ntfnCallbacks)
|
||||||
@ -77,17 +79,19 @@ func NewBtcdNotifier(config *btcrpcclient.ConnConfig) (*BtcdNotifier, error) {
|
|||||||
return notifier, nil
|
return notifier, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start...
|
// Start connects to the running btcd node over websockets, registers for block
|
||||||
|
// notifications, and finally launches all related helper goroutines.
|
||||||
func (b *BtcdNotifier) Start() error {
|
func (b *BtcdNotifier) Start() error {
|
||||||
// Already started?
|
// Already started?
|
||||||
if atomic.AddInt32(&b.started, 1) != 1 {
|
if atomic.AddInt32(&b.started, 1) != 1 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Connect to btcd, and register for notifications on connected, and
|
||||||
|
// disconnected blocks.
|
||||||
if err := b.chainConn.Connect(20); err != nil {
|
if err := b.chainConn.Connect(20); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := b.chainConn.NotifyBlocks(); err != nil {
|
if err := b.chainConn.NotifyBlocks(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -98,13 +102,15 @@ func (b *BtcdNotifier) Start() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop...
|
// Stop shutsdown the BtcdNotifier.
|
||||||
func (b *BtcdNotifier) Stop() error {
|
func (b *BtcdNotifier) Stop() error {
|
||||||
// Already shutting down?
|
// Already shutting down?
|
||||||
if atomic.AddInt32(&b.stopped, 1) != 1 {
|
if atomic.AddInt32(&b.stopped, 1) != 1 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shutdown the rpc client, this gracefully disconnects from btcd, and
|
||||||
|
// cleans up all related resources.
|
||||||
b.chainConn.Shutdown()
|
b.chainConn.Shutdown()
|
||||||
|
|
||||||
close(b.quit)
|
close(b.quit)
|
||||||
@ -123,13 +129,14 @@ func (b *BtcdNotifier) Stop() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// connectedBlock...
|
// blockNtfn packages a notification of a connected/disconnected block along
|
||||||
|
// with its height at the time.
|
||||||
type blockNtfn struct {
|
type blockNtfn struct {
|
||||||
sha *wire.ShaHash
|
sha *wire.ShaHash
|
||||||
height int32
|
height int32
|
||||||
}
|
}
|
||||||
|
|
||||||
// onBlockConnected...
|
// onBlockConnected implements on OnBlockConnected callback for btcrpcclient.
|
||||||
func (b *BtcdNotifier) onBlockConnected(hash *wire.ShaHash, height int32, t time.Time) {
|
func (b *BtcdNotifier) onBlockConnected(hash *wire.ShaHash, height int32, t time.Time) {
|
||||||
select {
|
select {
|
||||||
case b.connectedBlockHashes <- &blockNtfn{hash, height}:
|
case b.connectedBlockHashes <- &blockNtfn{hash, height}:
|
||||||
@ -137,12 +144,12 @@ func (b *BtcdNotifier) onBlockConnected(hash *wire.ShaHash, height int32, t time
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// onBlockDisconnected...
|
// onBlockDisconnected implements on OnBlockDisconnected callback for btcrpcclient.
|
||||||
func (b *BtcdNotifier) onBlockDisconnected(hash *wire.ShaHash, height int32, t time.Time) {
|
func (b *BtcdNotifier) onBlockDisconnected(hash *wire.ShaHash, height int32, t time.Time) {
|
||||||
b.onBlockDisconnected(hash, height, t)
|
b.onBlockDisconnected(hash, height, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// onRedeemingTx...
|
// onRedeemingTx implements on OnRedeemingTx callback for btcrpcclient.
|
||||||
func (b *BtcdNotifier) onRedeemingTx(transaction *btcutil.Tx, details *btcjson.BlockDetails) {
|
func (b *BtcdNotifier) onRedeemingTx(transaction *btcutil.Tx, details *btcjson.BlockDetails) {
|
||||||
select {
|
select {
|
||||||
case b.relevantTxs <- transaction:
|
case b.relevantTxs <- transaction:
|
||||||
@ -150,7 +157,8 @@ func (b *BtcdNotifier) onRedeemingTx(transaction *btcutil.Tx, details *btcjson.B
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// notificationDispatcher...
|
// notificationDispatcher is the primary goroutine which handles client
|
||||||
|
// notification registrations, as well as notification dispatches.
|
||||||
func (b *BtcdNotifier) notificationDispatcher() {
|
func (b *BtcdNotifier) notificationDispatcher() {
|
||||||
out:
|
out:
|
||||||
for {
|
for {
|
||||||
@ -222,7 +230,9 @@ out:
|
|||||||
b.wg.Done()
|
b.wg.Done()
|
||||||
}
|
}
|
||||||
|
|
||||||
// notifyConfs...
|
// notifyConfs examines the current confirmation heap, sending off any
|
||||||
|
// notifications which have been triggered by the connection of a new block at
|
||||||
|
// newBlockHeight.
|
||||||
func (b *BtcdNotifier) notifyConfs(newBlockHeight int32) {
|
func (b *BtcdNotifier) notifyConfs(newBlockHeight int32) {
|
||||||
// If the heap is empty, we have nothing to do.
|
// If the heap is empty, we have nothing to do.
|
||||||
if b.confHeap.Len() == 0 {
|
if b.confHeap.Len() == 0 {
|
||||||
@ -249,8 +259,11 @@ func (b *BtcdNotifier) notifyConfs(newBlockHeight int32) {
|
|||||||
heap.Push(b.confHeap, nextConf)
|
heap.Push(b.confHeap, nextConf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkConfirmationTrigger...
|
// checkConfirmationTrigger determines if the passed txSha included at blockHeight
|
||||||
// TODO(roasbeef): perheps lookup, then track by inputs instead?
|
// triggers any single confirmation notifications. In the event that the txid
|
||||||
|
// matches, yet needs additional confirmations, it is added to the confirmation
|
||||||
|
// heap to be triggered at a later time.
|
||||||
|
// TODO(roasbeef): perhaps lookup, then track by inputs instead?
|
||||||
func (b *BtcdNotifier) checkConfirmationTrigger(txSha *wire.ShaHash, blockHeight int32) {
|
func (b *BtcdNotifier) checkConfirmationTrigger(txSha *wire.ShaHash, blockHeight int32) {
|
||||||
// If a confirmation notification has been registered
|
// If a confirmation notification has been registered
|
||||||
// for this txid, then either trigger a notification
|
// for this txid, then either trigger a notification
|
||||||
@ -280,15 +293,18 @@ func (b *BtcdNotifier) checkConfirmationTrigger(txSha *wire.ShaHash, blockHeight
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// spendNotification....
|
// spendNotification couples a target outpoint along with the channel used for
|
||||||
|
// notifications once a spend of the outpoint has been detected.
|
||||||
type spendNotification struct {
|
type spendNotification struct {
|
||||||
targetOutpoint *wire.OutPoint
|
targetOutpoint *wire.OutPoint
|
||||||
|
|
||||||
spendChan chan *chainntnfs.SpendDetail
|
spendChan chan *chainntnfs.SpendDetail
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterSpendNotification...
|
// RegisterSpendNotification registers an intent to be notified once the target
|
||||||
// NOTE: eventChan MUST be buffered
|
// outpoint has been spent by a transaction on-chain. Once a spend of the target
|
||||||
|
// outpoint has been detected, the details of the spending event will be sent
|
||||||
|
// across the 'Spend' channel.
|
||||||
func (b *BtcdNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint) (*chainntnfs.SpendEvent, error) {
|
func (b *BtcdNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint) (*chainntnfs.SpendEvent, error) {
|
||||||
if err := b.chainConn.NotifySpent([]*wire.OutPoint{outpoint}); err != nil {
|
if err := b.chainConn.NotifySpent([]*wire.OutPoint{outpoint}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -304,8 +320,8 @@ func (b *BtcdNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint) (*chainntnfs.S
|
|||||||
return &chainntnfs.SpendEvent{ntfn.spendChan}, nil
|
return &chainntnfs.SpendEvent{ntfn.spendChan}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// confirmationNotification...
|
// confirmationNotification represents a client's intent to receive a
|
||||||
// TODO(roasbeef): re-org funny business
|
// notification once the target txid reaches numConfirmations confirmations.
|
||||||
type confirmationsNotification struct {
|
type confirmationsNotification struct {
|
||||||
txid *wire.ShaHash
|
txid *wire.ShaHash
|
||||||
|
|
||||||
@ -313,10 +329,12 @@ type confirmationsNotification struct {
|
|||||||
numConfirmations uint32
|
numConfirmations uint32
|
||||||
|
|
||||||
finConf chan struct{}
|
finConf chan struct{}
|
||||||
negativeConf chan int32
|
negativeConf chan int32 // TODO(roasbeef): re-org funny business
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterConfirmationsNotification...
|
// RegisterConfirmationsNotification registers a notification with BtcdNotifier
|
||||||
|
// which will be triggered once the txid reaches numConfs number of
|
||||||
|
// confirmations.
|
||||||
func (b *BtcdNotifier) RegisterConfirmationsNtfn(txid *wire.ShaHash,
|
func (b *BtcdNotifier) RegisterConfirmationsNtfn(txid *wire.ShaHash,
|
||||||
numConfs uint32) (*chainntnfs.ConfirmationEvent, error) {
|
numConfs uint32) (*chainntnfs.ConfirmationEvent, error) {
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user