Noticed this while updating to latest master in another project:
If there are two notifications for the same output being registered and
the first one does _NOT_ request the block to be included, then the
second one also will not receive the block, even if it explicitly
requests it.
This is caused by the block being removed from the original confirmation
set instead of a copy (as it is done in NotifyHeight and
UpdateConfDetails).
This commit moves the `HeightHintCache` implementation to the
`channeldb` package and inverts the dependency relation between
`chainntnfs` and `channeldb`.
Many packages depend on channeldb for type definitions,
interfaces, etc. `chainntnfs` is an example of that. `chainntnfs`
defines the `SpendHintCache` and `ConfirmHintCache` interfaces but
it also implments them (`HeightHintCache` struct). The implementation
uses logic that should not leak from channeldb (ex: bucket paths).
This makes our code highly coupled + it would not allow us to use any
of these interfaces in a package that is imported by `channeldb`
(circular dependency).
In this commit, we add a new option for the existing confirmation
notification system that optionally allows the caller to specify that a
block should be included as well.
The only quirk w/ the implementation here is the neutrino backend:
usually we get filtered blocks, we so need to first fetch the block
again so we can deliver the full block to the notifier. On the notifier
end, it'll only be checking for the transactions we care about, to
sending a full block doesn't affect the correctness.
We also extend the `testBatchConfirmationNotification` test to assert
that a block is only included if the caller specifies it.
Because Taproot key spend only spends don't allow us to re-construct the
spent pkScript from the witness alone, we cannot support registering
spend notifications for v1 pkScripts only. We instead require the
outpoint to be specified. This commit makes it possible to only match by
outpoint and also adds an itest for it.
This commit was previously split into the following parts to ease
review:
- 2d746f68: replace imports
- 4008f0fd: use ecdsa.Signature
- 849e33d1: remove btcec.S256()
- b8f6ebbd: use v2 library correctly
- fa80bca9: bump go modules
This commit fixes a buggy scenario where:
- a spend of the desired outpoint occurs
- RegisterSpend is called, not immediately notifying
- caller performs a historical dispatch, calling UpdateSpendDetails
- caller is notified on the Spend channel
- re-org occurs
- caller is not notified of the re-org
We fix this by correctly populating the spendsByHeight map when
dispatchSpendDetails is called. This mirrors the confirmation case.
This mirrors the logic for the spend case. This prevents a double
dispatch scenario when combined with a later commit. Otherwise, the
confirmation would linger in the buffer which is not ideal.
When we cancel a confirmation request, we should remove the request from
the height map regardless of the current height. Otherwise we end up in
the situation when the height is reached, the notification is attempted
sent which results in a crash.
If a concurrent call to cancel is made while the notifier is shutting
down, this would cause a panic (close of closed channel) since the
events are not removed from the notification sets.
This addresses a panic when a notification is canceled after its been
detected as included in a block and before its confirmation notification
is dispatched.
This prevents a deadlock while tearing down the TxNotifier if it's
currently blocked delivering a notification. By closing the quit chan
first, we ensure blocked sends/reads can exit and allow the TxNotifier
to proceed tearing down.
A height hint not being set would cause lnd to scan for the
confirmation/spend of a txid/outpoint/address from genesis.
The number of confirmations not being set within a confirmation request
would cause the internal TxNotifier to deadlock when dispatching
updates.
In this commit, we extend the BitcoindNotifier to support registering
scripts for spends notifications. Once the script has been detected as
spent within the chain, a spend notification will be dispatched through
the Spend channel of the SpendEvent returned upon registration.
For scripts that have been spent in the past, the rescan logic has been
modified to match on the script rather than the outpoint. This is done
by re-deriving the script of the output a transaction input is spending
and checking whether it matches ours.
For scripts that are unspent, a request to the backend will be sent to
alert the BitcoindNotifier of when the script was spent by a
transaction. To make this request we encode the script as an address, as
this is what the backend uses to detect the spend. The transaction will
then be proxied through the txUpdates concurrent queue, which will hand
it off to the underlying txNotifier and dispatch spend notifications to
the relevant clients.
Along the way, we also address an issue where we'd miss detecting that
an outpoint/script has been spent in the future due to not receiving a
historical dispatch request from the underlying txNotifier. To fix this,
we ensure that we always request the backend to notify us of the spend
once it detects it at tip, regardless of whether a historical rescan was
detected or not.
In this commit, we extend the BtcdNotifier to support registering
scripts for confirmation notifications. Once the script has been
detected as confirmed within the chain, a confirmation notification will
be dispatched to through the Confirmed channel of the ConfirmationEvent
returned upon registration.
For scripts that have confirmed in the past, the `historicalConfDetails`
method has been modified to skip the txindex and go straight to scanning
the chain manually if confirmation request is for a script. When
scanning the chain, we'll determine whether the script has been
confirmed by locating the script in an output of a confirmed
transaction.
For scripts that have yet to confirm, they will be properly tracked
within the TxNotifier.
In this commit, we refactor the TxNotifier's ProcessRelevantSpendTx to
also detect script spends. This can easily be done as the transaction
filtering logic was refactored into its own method in a previous commit.
In this commit, we modify the TxNotifier's ConnectTip method to also
detect whether a registered script has been confirmed or spent on-chain
by a transaction in the connected block. Once detected, notifications
for them will be queued up for dispatch as with txids/outpoints.
We've also refactored the ConnectTip method into smaller and reusable
methods, which will serve useful later.
In this commit, we refactor the HeightHintCache and its underlying
interfaces to be able to manipulate hints for ConfRequests and
SpendRequests. By doing so, we'll be able to manipulate hints for
scripts if the request includes either a zero hash or a zero outpoint.
These structs allow us to request notifications for either
txids/outpoints or output scripts. We'll be using these in later commits
to index confirmation and spend requests within the TxNotifier.
In this commit, we modify the TxNotifier's ConnectTip method to no
longer dispatch notifications to any clients who had a request fulfilled
within the height connected. Instead, it will queue the notifications
for dispatch and we add a new method NotifyHeight, which will actually
dispatch them. We do this to allow the users of the TxNotifier to be
more flexible when dispatching notifications.
In this commit, we'll now commit the current height of the TxNotifier as
the height hint for an outpoint/transaction after a rescan has been
completed and has determined that the outpoint is unspent/transaction is
unconfirmed. We do this to prevent another potentially long rescan if
the daemon is restarted before a new block comes in (which is when the
hints will be updated again).