This commit is meant to fix an occasional flake in the interrogation
tests cause by the async nature of the cancellation of block epoch
notifications. This commit modifies the cancellation to now be fully
synchronous which should eliminate this flake.
This commit fixes a race condition that was introduced while fixing a
lingering bug in the logic to notify block epoch clients. The race
condition would happen as by removing the default case in the select
statement, it was now possible for the client’s block epoch client to
be closed while the routine was attempting a send on it.
We now eliminate this race condition possibility by adding a wait group
to all goroutines launched to dispatch a block epoch notification. With
this modification, the Stop() goroutine will now wait for all other
goroutine to exit before closing the block epoch channels of all
currently registered clients.
This commit a bug introduced in the chain notifier while we were
limiting the usage of mutexes within the package. In a prior commit a
default case was introduced in the select statement in order to avoid
the possibility of the main goroutine blocking when dispatching block
epoch notification.
In order to avoid this potentially disastrous bug, we now instead
launch a new goroutine for each client to ensure that all notifications
are reliably dispatched.
This commit fixes a race condition in the notifyBlockEpochs detected by
the race condition detector. Previously the notifyBlockEpochs function
could cause a race condition when a new caller was either cancelling an
existing notification intent or creating a new one.
We fix this issue by making the call to notifyBlockEpochs synchronous
rather than asynchronous. An alternative would be to add a mutex
guarding the map state. The channel itself is buffered with a good
margin, so there shouldn’t be a huge impact.
This commit minifies the BtcdNotifier concrete implementation of the
ChainNotifier interface to allow callers to optionally cancel an
outstanding block epoch or spend notificaiton intent.
To do this efficiently, we now give each notification intent a unique
ID based on if it’s an epoch intent or a spend intent. We then use this
ID to reference back to the original un-dispatched notification intent
when the caller wishes to cancel the intent.
When iterating with the ChainNotifier, it currently isn’t possible to
cancel a non-dispatched yet active notificaiton intent. As a result,
this can be rather wasteful in many parts of lnd which my repeatedly
create a new spend notification depending on if/when a peer is
connected or not.
In order to fix this, we add a new `Cancel func()` field to both the
`BlockEpochEvent` and `SpendEvent` structs. This new closure attribute
allows the caller to cancel the yet-to-be-dispathed event, allowing the
ChainNotifier to free up resources.
On restarts, notifyBlockEpochs would intermittently attempt to send new
block epoch notifications to clients that had already been shut down,
causing a “send on closed channel” error. This change exits
notifyBlockEpochs upon shutdown so as to prevent this.
This commit makes a large number of minor changes concerning API usage
within the deamon to match the latest version on the upstream btcsuite
libraries.
The major changes are the switch from wire.ShaHash to chainhash.Hash,
and that wire.NewMsgTx() now takes a paramter indicating the version of
the transaction to be created.
Moved transaction states from in-memory maps to persistent BoltDB
buckets. This allows channel force closes to operate reliably if the
daemon is shut down and restarted at any point during the forced
channel closure process.
If the lnd daemon is shut down while multiple subsystems are attempting
to register for notifications, the blocking of those chain notifier
registrations may cause the daemon shutdown to deadlock. The additions
in this commit allow the registration functions to return errors rather
than potentially deadlock when the chain notifier is shut down.
This commit modifies the historical dispatch workflow slightly to also
obtain the full block in which the transaction was confirmed we we can
fully populate the full TxConfirmations struct which was recently added
as part of the confirmation subscription API.
With this change, confirmation triggers that a reached while the demon
is down, will now be deliver exactly as if the trigger was reached
while the daemon was up.
This commit updates the BtcdNotifier implementation of the
ChainNotifier by including the details of a transaction’s confirmation
within the ConfirmationEvent struct sent once a registered txid has
reached a sufficient number of confirmation.
This commit modifies the ChainNotifier interface, specifically the
ConfirmationEvent struct to now return additional details concerning
the exact location in the chain that the transaction was confirmed at.
This information will be very useful within the new routing package, as
within the network, channels are identified via their channel-ID which
is a compact encoding of: blockHeight | txIndex | outputIndex
This commit modifies the Stop method of the default ChainNotifier
client, the BtcdNotifier. We now close the notificaiton channel for all
the currently active block epoch clients in order to give clients a
signal that the entire daemon and possibly the ChainNotifier is
shutting down. This gives clients an extra signal to more thoroughly
implement a graceful shutdown across the daemon.
This commit modifies the recently added logic to the ChainNotifier to:
1. Fix the off-by-one confirmation error that was missed due a flaky
test
2. Ensure that partial historical confirmations are properly handled.
The partial hostile confirmation case arises when a transaction already
a non-zero number of confirmations when the notification is registered,
but less than what would trigger the confirmation notification. To fix
this, transaction which have a partial number of confirmation are now
properly inserted into the confHeap, skipping first first phase for
notifications.
Without these checks, “zombie” notification requests that would never
be dispatched could be registered. This would occur if notification
requests were made for events (transaction confirmation and output
spent) that had already been recorded on the blockchain.
This commit adds support for dispatching the same spend notification to
multiple clients. This is now required by the ChainNotiifer interface
documentation and will be needed within the daemon in order to support
some upcoming refactors.
This commit updates the documentation for the ChainNotifier interface
to specify that all implementation MUST be able to support dispatching
the same notification to multiple clients.
This commit fixes a possible dead lock when dispatching notifications
caused by the circular communication between the notificationDisptcher
thread and the main notification thread within the btcrpcclient.
Rather than potentially blocking for eternity on a blocking send,
notifications are now instantly handled by appending the notification
on an unbounded queue then launching a goroutine to signal the
dispatcher thread that a new item is available within the queue.
This commit adds multi-client support for confirmation notification of
the same transaction. Within the daemon there might be scenarios where
multiple goroutines are waiting for the same transaction to be
confirmed in order to properly fulfill their tasks. Previously if
multiple clients were registered for the same txid confirmation
notification, then only the client who registered last would receive
the notification.
This commit refactors the existing chainntnfns package in order to
allow more easily allow integration into the main system, by allowing
one to gain access to a set of end-to-end tests for a particular
ChainNotifier implementation.
In order to achieve this, the existing set of tests for the only
concrete implementation (`BtcdNoitifer`) have been refactored to test
against all “registered” notifier interfaces registered. This is
achieved by creating the concept of a “driver” for each concrete
`ChainNotifer` implementation. Once a the package of a particular
driver is imported, solely for the side effects, the init() method
automatically registers the driver.
Additionally, the documentation in various areas of the package have
been cleaned up a bit.