chainntnfs

package
v0.0.0-...-73ec5f1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 13, 2018 License: MIT Imports: 12 Imported by: 0

README

chainntnfs

Build Status MIT licensed GoDoc

The chainntnfs package implements a set of interfaces which allow callers to receive notifications in response to specific on-chain events. The set of notifications available include:

  • Notifications for each new block connected to the current best chain.
  • Notifications once a txid has reached a specified number of confirmations.
  • Notifications once a target outpoint (txid:index) has been spent.

These notifications are used within lnd in order to properly handle the workflows for: channel funding, cooperative channel closures, forced channel closures, channel contract breaches, sweeping time-locked outputs, and finally pruning the channel graph.

This package is intentionally general enough to be applicable outside the specific use cases within lnd outlined above. The current sole concrete implementation of the ChainNotifier interface depends on btcd.

Installation and Updating

$ go get -u github.com/lightningnetwork/lnd/chainntnfs

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (

	// ErrCorruptedHeightHintCache indicates that the on-disk bucketing
	// structure has altered since the height hint cache instance was
	// initialized.
	ErrCorruptedHeightHintCache = errors.New("height hint cache has been " +
		"corrupted")

	// ErrSpendHintNotFound is an error returned when a spend hint for an
	// outpoint was not found.
	ErrSpendHintNotFound = errors.New("spend hint not found")

	// ErrConfirmHintNotFound is an error returned when a confirm hint for a
	// transaction was not found.
	ErrConfirmHintNotFound = errors.New("confirm hint not found")
)
View Source
var (
	// ErrTxConfNotifierExiting is an error returned when attempting to
	// interact with the TxConfNotifier but it been shut down.
	ErrTxConfNotifierExiting = errors.New("TxConfNotifier is exiting")
)

Log is a logger that is initialized with no output filters. This means the package will not perform any logging by default until the caller requests it.

Functions

func DisableLog

func DisableLog()

DisableLog disables all library log output. Logging output is disabled by default until UseLogger is called.

func GetCommonBlockAncestorHeight

func GetCommonBlockAncestorHeight(chainConn ChainConn, reorgHash,
	chainHash chainhash.Hash) (int32, error)

GetCommonBlockAncestorHeight takes in: (1) the hash of a block that has been reorged out of the main chain (2) the hash of the block of the same height from the main chain It returns the height of the nearest common ancestor between the two hashes, or an error

func HandleMissedBlocks

func HandleMissedBlocks(chainConn ChainConn, txConfNotifier *TxConfNotifier,
	currBestBlock BlockEpoch, newHeight int32,
	backendStoresReorgs bool) (BlockEpoch, []BlockEpoch, error)

HandleMissedBlocks is called when the chain backend for a notifier misses a series of blocks, handling a reorg if necessary. Its backendStoresReorgs parameter tells it whether or not the notifier's chainConn stores information about blocks that have been reorged out of the chain, which allows HandleMissedBlocks to check whether the notifier's best block has been reorged out, and rewind the chain accordingly. It returns the best block for the notifier and a slice of the missed blocks. The new best block needs to be returned in case a chain rewind occurs and partially completes before erroring. In the case where there is no rewind, the notifier's current best block is returned.

func RegisterNotifier

func RegisterNotifier(driver *NotifierDriver) error

RegisterNotifier registers a NotifierDriver which is capable of driving a concrete ChainNotifier interface. In the case that this driver has already been registered, an error is returned.

NOTE: This function is safe for concurrent access.

func SupportedNotifiers

func SupportedNotifiers() []string

SupportedNotifiers returns a slice of strings that represent the database drivers that have been registered and are therefore supported.

NOTE: This function is safe for concurrent access.

func UseLogger

func UseLogger(logger btclog.Logger)

UseLogger uses a specified Logger to output package logging info. This should be used in preference to SetLogWriter if the caller is also using btclog.

Types

type BlockEpoch

type BlockEpoch struct {
	// Hash is the block hash of the latest block to be added to the tip of
	// the main chain.
	Hash *chainhash.Hash

	// Height is the height of the latest block to be added to the tip of
	// the main chain.
	Height int32
}

BlockEpoch represents metadata concerning each new block connected to the main chain.

func GetClientMissedBlocks

func GetClientMissedBlocks(chainConn ChainConn, clientBestBlock *BlockEpoch,
	notifierBestHeight int32, backendStoresReorgs bool) ([]BlockEpoch, error)

GetClientMissedBlocks uses a client's best block to determine what blocks it missed being notified about, and returns them in a slice. Its backendStoresReorgs parameter tells it whether or not the notifier's chainConn stores information about blocks that have been reorged out of the chain, which allows GetClientMissedBlocks to find out whether the client's best block has been reorged out of the chain, rewind to the common ancestor and return blocks starting right after the common ancestor.

func RewindChain

func RewindChain(chainConn ChainConn, txConfNotifier *TxConfNotifier,
	currBestBlock BlockEpoch, targetHeight int32) (BlockEpoch, error)

RewindChain handles internal state updates for the notifier's TxConfNotifier It has no effect if given a height greater than or equal to our current best known height. It returns the new best block for the notifier.

type BlockEpochEvent

type BlockEpochEvent struct {
	// Epochs is a receive only channel that will be sent upon each time a
	// new block is connected to the end of the main chain.
	Epochs <-chan *BlockEpoch // MUST be buffered.

	// Cancel is a closure that should be executed by the caller in the
	// case that they wish to abandon their registered spend notification.
	Cancel func()
}

BlockEpochEvent encapsulates an on-going stream of block epoch notifications. Its only field 'Epochs' will be sent upon for each new block connected to the main-chain.

NOTE: If the caller wishes to cancel their registered block epoch notification, the Cancel closure MUST be called.

type ChainConn

type ChainConn interface {
	// GetBlockHeader returns the block header for a hash.
	GetBlockHeader(blockHash *chainhash.Hash) (*wire.BlockHeader, error)

	// GetBlockHeaderVerbose returns the verbose block header for a hash.
	GetBlockHeaderVerbose(blockHash *chainhash.Hash) (
		*btcjson.GetBlockHeaderVerboseResult, error)

	// GetBlockHash returns the hash from a block height.
	GetBlockHash(blockHeight int64) (*chainhash.Hash, error)
}

ChainConn enables notifiers to pass in their chain backend to interface functions that require it.

type ChainNotifier

type ChainNotifier interface {
	// RegisterConfirmationsNtfn registers an intent to be notified once
	// txid reaches numConfs confirmations. We also pass in the pkScript as
	// the default light client instead needs to match on scripts created
	// in the block. The returned ConfirmationEvent should properly notify
	// the client once the specified number of confirmations has been
	// reached for the txid, as well as if the original tx gets re-org'd
	// out of the mainchain.  The heightHint parameter is provided as a
	// convenience to light clients. The heightHint denotes the earliest
	// height in the blockchain in which the target txid _could_ have been
	// included in the chain.  This can be used to bound the search space
	// when checking to see if a notification can immediately be dispatched
	// due to historical data.
	//
	// NOTE: Dispatching notifications to multiple clients subscribed to
	// the same (txid, numConfs) tuple MUST be supported.
	RegisterConfirmationsNtfn(txid *chainhash.Hash, pkScript []byte, numConfs,
		heightHint uint32) (*ConfirmationEvent, error)

	// RegisterSpendNtfn registers an intent to be notified once the target
	// outpoint is successfully spent within a transaction. The script that
	// the outpoint creates must also be specified. This allows this
	// interface to be implemented by BIP 158-like filtering. The returned
	// SpendEvent will receive a send on the 'Spend' transaction once a
	// transaction spending the input is detected on the blockchain.  The
	// heightHint parameter is provided as a convenience to light clients.
	// The heightHint denotes the earliest height in the blockchain in
	// which the target output could have been created.
	//
	// NOTE: The notification should only be triggered when the spending
	// transaction receives a single confirmation.
	//
	// NOTE: Dispatching notifications to multiple clients subscribed to a
	// spend of the same outpoint MUST be supported.
	RegisterSpendNtfn(outpoint *wire.OutPoint, pkScript []byte,
		heightHint uint32) (*SpendEvent, error)

	// RegisterBlockEpochNtfn registers an intent to be notified of each
	// new block connected to the tip of the main chain. The returned
	// BlockEpochEvent struct contains a channel which will be sent upon
	// for each new block discovered.
	//
	// Clients have the option of passing in their best known block.
	// If they specify a block, the ChainNotifier checks whether the client
	// is behind on blocks. If they are, the ChainNotifier sends a backlog
	// of block notifications for the missed blocks.
	RegisterBlockEpochNtfn(*BlockEpoch) (*BlockEpochEvent, error)

	// Start the ChainNotifier. Once started, the implementation should be
	// ready, and able to receive notification registrations from clients.
	Start() error

	// Stops the concrete ChainNotifier. Once stopped, the ChainNotifier
	// should disallow any future requests from potential clients.
	// Additionally, all pending client notifications will be cancelled
	// by closing the related channels on the *Event's.
	Stop() error
}

ChainNotifier represents a trusted source to receive notifications concerning targeted events on the Bitcoin blockchain. The interface specification is intentionally general in order to support a wide array of chain notification implementations such as: btcd's websockets notifications, Bitcoin Core's ZeroMQ notifications, various Bitcoin API services, Electrum servers, etc.

Concrete implementations of ChainNotifier should be able to support multiple concurrent client requests, as well as multiple concurrent notification events. TODO(roasbeef): all events should have a Cancel() method to free up the resource

type ConcurrentQueue

type ConcurrentQueue struct {
	// contains filtered or unexported fields
}

ConcurrentQueue is a concurrent-safe FIFO queue with unbounded capacity. Clients interact with the queue by pushing items into the in channel and popping items from the out channel. There is a goroutine that manages moving items from the in channel to the out channel in the correct order that must be started by calling Start().

func NewConcurrentQueue

func NewConcurrentQueue(bufferSize int) *ConcurrentQueue

NewConcurrentQueue constructs a ConcurrentQueue. The bufferSize parameter is the capacity of the output channel. When the size of the queue is below this threshold, pushes do not incur the overhead of the less efficient overflow structure.

func (*ConcurrentQueue) ChanIn

func (cq *ConcurrentQueue) ChanIn() chan<- interface{}

ChanIn returns a channel that can be used to push new items into the queue.

func (*ConcurrentQueue) ChanOut

func (cq *ConcurrentQueue) ChanOut() <-chan interface{}

ChanOut returns a channel that can be used to pop items from the queue.

func (*ConcurrentQueue) Start

func (cq *ConcurrentQueue) Start()

Start begins a goroutine that manages moving items from the in channel to the out channel. The queue tries to move items directly to the out channel minimize overhead, but if the out channel is full it pushes items to an overflow queue. This must be called before using the queue.

func (*ConcurrentQueue) Stop

func (cq *ConcurrentQueue) Stop()

Stop ends the goroutine that moves items from the in channel to the out channel. This does not clear the queue state, so the queue can be restarted without dropping items.

type ConfNtfn

type ConfNtfn struct {
	// ConfID uniquely identifies the confirmation notification request for
	// the specified transaction.
	ConfID uint64

	// TxID is the hash of the transaction for which confirmation notifications
	// are requested.
	TxID *chainhash.Hash

	// NumConfirmations is the number of confirmations after which the
	// notification is to be sent.
	NumConfirmations uint32

	// Event contains references to the channels that the notifications are to
	// be sent over.
	Event *ConfirmationEvent
	// contains filtered or unexported fields
}

ConfNtfn represents a notifier client's request to receive a notification once the target transaction gets sufficient confirmations. The client is asynchronously notified via the ConfirmationEvent channels.

type ConfirmHintCache

type ConfirmHintCache interface {
	// CommitConfirmHint commits a confirm hint for the transactions to the
	// cache.
	CommitConfirmHint(height uint32, txids ...chainhash.Hash) error

	// QueryConfirmHint returns the latest confirm hint for a transaction
	// hash. ErrConfirmHintNotFound is returned if a confirm hint does not
	// exist within the cache for the transaction hash.
	QueryConfirmHint(txid chainhash.Hash) (uint32, error)

	// PurgeConfirmHint removes the confirm hint for the transactions from
	// the cache.
	PurgeConfirmHint(txids ...chainhash.Hash) error
}

ConfirmHintCache is an interface whose duty is to cache confirm hints for transactions. A confirm hint is defined as the earliest height in the chain at which a transaction could have been included in a block.

type ConfirmationEvent

type ConfirmationEvent struct {
	// Confirmed is a channel that will be sent upon once the transaction
	// has been fully confirmed. The struct sent will contain all the
	// details of the channel's confirmation.
	Confirmed chan *TxConfirmation // MUST be buffered.

	// Updates is a channel that will sent upon, at every incremental
	// confirmation, how many confirmations are left to declare the
	// transaction as fully confirmed.
	Updates chan uint32 // MUST be buffered.

	NegativeConf chan int32 // MUST be buffered.
}

ConfirmationEvent encapsulates a confirmation notification. With this struct, callers can be notified of: the instance the target txid reaches the targeted number of confirmations, how many confirmations are left for the target txid to be fully confirmed at every new block height, and also in the event that the original txid becomes disconnected from the blockchain as a result of a re-org.

Once the txid reaches the specified number of confirmations, the 'Confirmed' channel will be sent upon fulfilling the notification.

If the event that the original transaction becomes re-org'd out of the main chain, the 'NegativeConf' will be sent upon with a value representing the depth of the re-org.

func NewConfirmationEvent

func NewConfirmationEvent(numConfs uint32) *ConfirmationEvent

NewConfirmationEvent constructs a new ConfirmationEvent with newly opened channels.

type HeightHintCache

type HeightHintCache struct {
	// contains filtered or unexported fields
}

HeightHintCache is an implementation of the SpendHintCache and ConfirmHintCache interfaces backed by a channeldb DB instance where the hints will be stored.

func NewHeightHintCache

func NewHeightHintCache(db *channeldb.DB, disable bool) (*HeightHintCache, error)

NewHeightHintCache returns a new height hint cache backed by a database.

func (*HeightHintCache) CommitConfirmHint

func (c *HeightHintCache) CommitConfirmHint(height uint32, txids ...chainhash.Hash) error

CommitConfirmHint commits a confirm hint for the transactions to the cache.

func (*HeightHintCache) CommitSpendHint

func (c *HeightHintCache) CommitSpendHint(height uint32, ops ...wire.OutPoint) error

CommitSpendHint commits a spend hint for the outpoints to the cache.

func (*HeightHintCache) PurgeConfirmHint

func (c *HeightHintCache) PurgeConfirmHint(txids ...chainhash.Hash) error

PurgeConfirmHint removes the confirm hint for the transactions from the cache.

func (*HeightHintCache) PurgeSpendHint

func (c *HeightHintCache) PurgeSpendHint(ops ...wire.OutPoint) error

PurgeSpendHint removes the spend hint for the outpoints from the cache.

func (*HeightHintCache) QueryConfirmHint

func (c *HeightHintCache) QueryConfirmHint(txid chainhash.Hash) (uint32, error)

QueryConfirmHint returns the latest confirm hint for a transaction hash. ErrConfirmHintNotFound is returned if a confirm hint does not exist within the cache for the transaction hash.

func (*HeightHintCache) QuerySpendHint

func (c *HeightHintCache) QuerySpendHint(op wire.OutPoint) (uint32, error)

QuerySpendHint returns the latest spend hint for an outpoint. ErrSpendHintNotFound is returned if a spend hint does not exist within the cache for the outpoint.

type NotifierDriver

type NotifierDriver struct {
	// NotifierType is a string which uniquely identifies the ChainNotifier
	// that this driver, drives.
	NotifierType string

	// New creates a new instance of a concrete ChainNotifier
	// implementation given a variadic set up arguments. The function takes
	// a variadic number of interface parameters in order to provide
	// initialization flexibility, thereby accommodating several potential
	// ChainNotifier implementations.
	New func(args ...interface{}) (ChainNotifier, error)
}

NotifierDriver represents a "driver" for a particular interface. A driver is identified by a globally unique string identifier along with a 'New()' method which is responsible for initializing a particular ChainNotifier concrete implementation.

func RegisteredNotifiers

func RegisteredNotifiers() []*NotifierDriver

RegisteredNotifiers returns a slice of all currently registered notifiers.

NOTE: This function is safe for concurrent access.

type SpendDetail

type SpendDetail struct {
	SpentOutPoint     *wire.OutPoint
	SpenderTxHash     *chainhash.Hash
	SpendingTx        *wire.MsgTx
	SpenderInputIndex uint32
	SpendingHeight    int32
}

SpendDetail contains details pertaining to a spent output. This struct itself is the spentness notification. It includes the original outpoint which triggered the notification, the hash of the transaction spending the output, the spending transaction itself, and finally the input index which spent the target output.

type SpendEvent

type SpendEvent struct {
	// Spend is a receive only channel which will be sent upon once the
	// target outpoint has been spent.
	Spend <-chan *SpendDetail // MUST be buffered.

	// Cancel is a closure that should be executed by the caller in the
	// case that they wish to prematurely abandon their registered spend
	// notification.
	Cancel func()
}

SpendEvent encapsulates a spentness notification. Its only field 'Spend' will be sent upon once the target output passed into RegisterSpendNtfn has been spent on the blockchain.

NOTE: If the caller wishes to cancel their registered spend notification, the Cancel closure MUST be called.

type SpendHintCache

type SpendHintCache interface {
	// CommitSpendHint commits a spend hint for the outpoints to the cache.
	CommitSpendHint(height uint32, ops ...wire.OutPoint) error

	// QuerySpendHint returns the latest spend hint for an outpoint.
	// ErrSpendHintNotFound is returned if a spend hint does not exist
	// within the cache for the outpoint.
	QuerySpendHint(op wire.OutPoint) (uint32, error)

	// PurgeSpendHint removes the spend hint for the outpoints from the
	// cache.
	PurgeSpendHint(ops ...wire.OutPoint) error
}

SpendHintCache is an interface whose duty is to cache spend hints for outpoints. A spend hint is defined as the earliest height in the chain at which an outpoint could have been spent within.

type TxConfNotifier

type TxConfNotifier struct {
	sync.Mutex
	// contains filtered or unexported fields
}

TxConfNotifier is used to register transaction confirmation notifications and dispatch them as the transactions confirm. A client can request to be notified when a particular transaction has sufficient on-chain confirmations (or be notified immediately if the tx already does), and the TxConfNotifier will watch changes to the blockchain in order to satisfy these requests.

func NewTxConfNotifier

func NewTxConfNotifier(startHeight uint32, reorgSafetyLimit uint32,
	hintCache ConfirmHintCache) *TxConfNotifier

NewTxConfNotifier creates a TxConfNotifier. The current height of the blockchain is accepted as a parameter.

func (*TxConfNotifier) ConnectTip

func (tcn *TxConfNotifier) ConnectTip(blockHash *chainhash.Hash,
	blockHeight uint32, txns []*btcutil.Tx) error

ConnectTip handles a new block extending the current chain. This checks each transaction in the block to see if any watched transactions are included. Also, if any watched transactions now have the required number of confirmations as a result of this block being connected, this dispatches notifications.

func (*TxConfNotifier) DisconnectTip

func (tcn *TxConfNotifier) DisconnectTip(blockHeight uint32) error

DisconnectTip handles the tip of the current chain being disconnected during a chain reorganization. If any watched transactions were included in this block, internal structures are updated to ensure a confirmation notification is not sent unless the transaction is included in the new chain.

func (*TxConfNotifier) Register

func (tcn *TxConfNotifier) Register(ntfn *ConfNtfn) error

Register handles a new notification request. The client will be notified when the transaction gets a sufficient number of confirmations on the blockchain.

NOTE: If the transaction has already been included in a block on the chain, the confirmation details must be provided with the UpdateConfDetails method, otherwise we will wait for the transaction to confirm even though it already has.

func (*TxConfNotifier) TearDown

func (tcn *TxConfNotifier) TearDown()

TearDown is to be called when the owner of the TxConfNotifier is exiting. This closes the event channels of all registered notifications that have not been dispatched yet.

func (*TxConfNotifier) UpdateConfDetails

func (tcn *TxConfNotifier) UpdateConfDetails(txid chainhash.Hash,
	clientID uint64, details *TxConfirmation) error

UpdateConfDetails attempts to update the confirmation details for an active notification within the notifier. This should only be used in the case of a transaction that has confirmed before the notifier's current height.

NOTE: The notification should be registered first to ensure notifications are dispatched correctly.

type TxConfStatus

type TxConfStatus uint8

TxConfStatus denotes the status of a transaction's lookup.

const (
	// TxFoundMempool denotes that the transaction was found within the
	// backend node's mempool.
	TxFoundMempool TxConfStatus = iota

	// TxFoundIndex denotes that the transaction was found within the
	// backend node's txindex.
	TxFoundIndex

	// TxNotFoundIndex denotes that the transaction was not found within the
	// backend node's txindex.
	TxNotFoundIndex

	// TxFoundManually denotes that the transaction was found within the
	// chain by scanning for it manually.
	TxFoundManually

	// TxNotFoundManually denotes that the transaction was not found within
	// the chain by scanning for it manually.
	TxNotFoundManually
)

func (TxConfStatus) String

func (t TxConfStatus) String() string

String returns the string representation of the TxConfStatus.

type TxConfirmation

type TxConfirmation struct {
	// BlockHash is the hash of the block that confirmed the original
	// transition.
	BlockHash *chainhash.Hash

	// BlockHeight is the height of the block in which the transaction was
	// confirmed within.
	BlockHeight uint32

	// TxIndex is the index within the block of the ultimate confirmed
	// transaction.
	TxIndex uint32
}

TxConfirmation carries some additional block-level details of the exact block that specified transactions was confirmed within.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL